# Generated by make -f Makefile-cigraph, do not edit by hand
# styler: off

empty_impl <- function(
  n = 0,
  directed = TRUE
) {
  # Argument checks
  n <- as.numeric(n)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_empty,
    n,
    directed
  )

  res
}

add_edges_impl <- function(
  graph,
  edges
) {
  # Argument checks
  ensure_igraph(graph)
  edges <- as_igraph_vs(graph, edges)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_add_edges,
    graph,
    edges - 1
  )

  res
}

empty_attrs_impl <- function(
  n,
  directed
) {
  # Argument checks
  n <- as.numeric(n)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_empty_attrs,
    n,
    directed
  )

  res
}

add_vertices_impl <- function(
  graph,
  nv
) {
  # Argument checks
  ensure_igraph(graph)
  nv <- as.numeric(nv)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_add_vertices,
    graph,
    nv
  )

  res
}

copy_impl <- function(
  from
) {
  # Argument checks
  ensure_igraph(from)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_copy,
    from
  )

  res
}

delete_edges_impl <- function(
  graph,
  edges
) {
  # Argument checks
  ensure_igraph(graph)
  edges <- as_igraph_es(graph, edges)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_delete_edges,
    graph,
    edges - 1
  )

  res
}

delete_vertices_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,
    graph,
    vertices - 1
  )

  res
}

delete_vertices_idx_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
}

vcount_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_vcount,
    graph
  )

  res
}

ecount_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_ecount,
    graph
  )

  res
}

neighbors_impl <- function(
  graph,
  vid,
  mode = c("all", "out", "in", "total")
) {
  # Argument checks
  ensure_igraph(graph)
  vid <- as_igraph_vs(graph, vid)
  if (length(vid) != 1) {
    cli::cli_abort(
      "{.arg vid} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_neighbors,
    graph,
    vid - 1,
    mode
  )
  if (igraph_opt("return.vs.es")) {
    res <- create_vs(graph, res)
  }
  res
}

is_directed_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_is_directed,
    graph
  )

  res
}

degree_impl <- function(
  graph,
  vids = V(graph),
  mode = c("all", "out", "in", "total"),
  loops = TRUE
) {
  # 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 <- as.logical(loops)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_degree,
    graph,
    vids - 1,
    mode,
    loops
  )

  res
}

edge_impl <- function(
  graph,
  eid
) {
  # Argument checks
  ensure_igraph(graph)
  eid <- as.numeric(eid)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_edge,
    graph,
    eid
  )

  res
}

edges_impl <- function(
  graph,
  eids
) {
  # Argument checks
  ensure_igraph(graph)
  eids <- as_igraph_es(graph, eids)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_edges,
    graph,
    eids - 1
  )
  if (igraph_opt("return.vs.es")) {
    res <- create_vs(graph, res)
  }
  res
}

get_eid_impl <- function(
  graph,
  from,
  to,
  directed = TRUE,
  error = TRUE
) {
  # Argument checks
  ensure_igraph(graph)
  from <- as_igraph_vs(graph, from)
  if (length(from) != 1) {
    cli::cli_abort(
      "{.arg from} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  to <- as_igraph_vs(graph, to)
  if (length(to) != 1) {
    cli::cli_abort(
      "{.arg to} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  directed <- as.logical(directed)
  error <- as.logical(error)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_get_eid,
    graph,
    from - 1,
    to - 1,
    directed,
    error
  )
  if (igraph_opt("return.vs.es")) {
    res <- create_es(graph, res)
  }
  res
}

get_eids_impl <- function(
  graph,
  pairs,
  directed = TRUE,
  error = TRUE
) {
  # Argument checks
  ensure_igraph(graph)
  pairs <- as_igraph_vs(graph, pairs)
  directed <- as.logical(directed)
  error <- as.logical(error)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_get_eids,
    graph,
    pairs - 1,
    directed,
    error
  )
  if (igraph_opt("return.vs.es")) {
    res <- create_es(graph, res)
  }
  res
}

get_all_eids_between_impl <- function(
  graph,
  from,
  to,
  directed = TRUE
) {
  # Argument checks
  ensure_igraph(graph)
  from <- as_igraph_vs(graph, from)
  if (length(from) != 1) {
    cli::cli_abort(
      "{.arg from} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  to <- as_igraph_vs(graph, to)
  if (length(to) != 1) {
    cli::cli_abort(
      "{.arg to} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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")
) {
  # Argument checks
  ensure_igraph(graph)
  vid <- as_igraph_vs(graph, vid)
  if (length(vid) != 1) {
    cli::cli_abort(
      "{.arg vid} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_incident,
    graph,
    vid - 1,
    mode
  )
  if (igraph_opt("return.vs.es")) {
    res <- create_es(graph, res)
  }
  res
}

is_same_graph_impl <- function(
  graph1,
  graph2
) {
  # Argument checks
  ensure_igraph(graph1)
  ensure_igraph(graph2)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_is_same_graph,
    graph1,
    graph2
  )

  res
}

create_impl <- function(
  edges,
  n = 0,
  directed = TRUE
) {
  # Argument checks
  edges <- as.numeric(edges)
  n <- as.numeric(n)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_create,
    edges,
    n,
    directed
  )

  res
}

adjacency_impl <- function(
  adjmatrix,
  mode = c("directed", "undirected", "upper", "lower", "min", "plus", "max"),
  loops = c("once", "none", "twice")
) {
  # Argument checks
  adjmatrix[] <- as.numeric(adjmatrix)
  mode <- switch_igraph_arg(
    mode,
    "directed" = 0L,
    "undirected" = 1L,
    "upper" = 2L,
    "lower" = 3L,
    "min" = 4L,
    "plus" = 5L,
    "max" = 6L
  )
  loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_adjacency,
    adjmatrix,
    mode,
    loops
  )

  res
}

sparse_adjacency_impl <- function(
  adjmatrix,
  mode = c("directed", "undirected", "upper", "lower", "min", "plus", "max"),
  loops = c("once", "none", "twice")
) {
  # Argument checks
  requireNamespace("Matrix", quietly = TRUE)
  adjmatrix <- as(as(as(adjmatrix, "dMatrix"), "generalMatrix"), "CsparseMatrix")
  mode <- switch_igraph_arg(
    mode,
    "directed" = 0L,
    "undirected" = 1L,
    "upper" = 2L,
    "lower" = 3L,
    "min" = 4L,
    "plus" = 5L,
    "max" = 6L
  )
  loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_sparse_adjacency,
    adjmatrix,
    mode,
    loops
  )

  res
}

sparse_weighted_adjacency_impl <- function(
  adjmatrix,
  mode = c("directed", "undirected", "upper", "lower", "min", "plus", "max"),
  loops = c("once", "none", "twice")
) {
  # Argument checks
  requireNamespace("Matrix", quietly = TRUE)
  adjmatrix <- as(as(as(adjmatrix, "dMatrix"), "generalMatrix"), "CsparseMatrix")
  mode <- switch_igraph_arg(
    mode,
    "directed" = 0L,
    "undirected" = 1L,
    "upper" = 2L,
    "lower" = 3L,
    "min" = 4L,
    "plus" = 5L,
    "max" = 6L
  )
  loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_sparse_weighted_adjacency,
    adjmatrix,
    mode,
    loops
  )

  res
}

weighted_adjacency_impl <- function(
  adjmatrix,
  mode = c("directed", "undirected", "upper", "lower", "min", "plus", "max"),
  loops = c("once", "none", "twice")
) {
  # Argument checks
  adjmatrix[] <- as.numeric(adjmatrix)
  mode <- switch_igraph_arg(
    mode,
    "directed" = 0L,
    "undirected" = 1L,
    "upper" = 2L,
    "lower" = 3L,
    "min" = 4L,
    "plus" = 5L,
    "max" = 6L
  )
  loops <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_weighted_adjacency,
    adjmatrix,
    mode,
    loops
  )

  res
}

star_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))
  # Function call
  res <- .Call(
    R_igraph_star,
    n,
    mode,
    center
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_wheel,
    n,
    mode,
    center
  )

  res
}

hypercube_impl <- function(
  n,
  directed = FALSE
) {
  # Argument checks
  n <- as.numeric(n)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_hypercube,
    n,
    directed
  )

  res
}

square_lattice_impl <- function(
  dimvector,
  nei = 1,
  directed = FALSE,
  mutual = FALSE,
  periodic = NULL
) {
  # Argument checks
  dimvector <- as.numeric(dimvector)
  nei <- as.numeric(nei)
  directed <- as.logical(directed)
  mutual <- as.logical(mutual)
  if (!is.null(periodic)) {
    periodic <- as.logical(periodic)
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_square_lattice,
    dimvector,
    nei,
    directed,
    mutual,
    periodic
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_triangular_lattice,
    dimvector,
    directed,
    mutual
  )

  res
}

ring_impl <- function(
  n,
  directed = FALSE,
  mutual = FALSE,
  circular = TRUE
) {
  # Argument checks
  n <- as.numeric(n)
  directed <- as.logical(directed)
  mutual <- as.logical(mutual)
  circular <- as.logical(circular)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_ring,
    n,
    directed,
    mutual,
    circular
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_path_graph,
    n,
    directed,
    mutual
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_cycle_graph,
    n,
    directed,
    mutual
  )

  res
}

kary_tree_impl <- function(
  n,
  children = 2,
  type = c("out", "in", "undirected")
) {
  # Argument checks
  n <- as.numeric(n)
  children <- as.numeric(children)
  type <- switch_igraph_arg(type, "out" = 0L, "in" = 1L, "undirected" = 2L)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_kary_tree,
    n,
    children,
    type
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_symmetric_tree,
    branches,
    type
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_regular_tree,
    h,
    k,
    type
  )

  res
}

full_impl <- function(
  n,
  directed = FALSE,
  loops = FALSE
) {
  # Argument checks
  n <- as.numeric(n)
  directed <- as.logical(directed)
  loops <- as.logical(loops)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_full,
    n,
    directed,
    loops
  )

  res
}

full_citation_impl <- function(
  n,
  directed = TRUE
) {
  # Argument checks
  n <- as.numeric(n)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_full_citation,
    n,
    directed
  )

  res
}

atlas_impl <- function(
  number = 0
) {
  # Argument checks
  number <- as.numeric(number)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_atlas,
    number
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_extended_chordal_ring,
    nodes,
    W,
    directed
  )

  res
}

connect_neighborhood_impl <- function(
  graph,
  order = 2,
  mode = c("all", "out", "in", "total")
) {
  # Argument checks
  ensure_igraph(graph)
  order <- as.numeric(order)
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_connect_neighborhood,
    graph,
    order,
    mode
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_graph_power,
    graph,
    order,
    directed
  )

  res
}

linegraph_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_linegraph,
    graph
  )

  res
}

de_bruijn_impl <- function(
  m,
  n
) {
  # Argument checks
  m <- as.numeric(m)
  n <- as.numeric(n)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_de_bruijn,
    m,
    n
  )

  res
}

kautz_impl <- function(
  m,
  n
) {
  # Argument checks
  m <- as.numeric(m)
  n <- as.numeric(n)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_kautz,
    m,
    n
  )

  res
}

famous_impl <- function(
  name
) {
  # Argument checks


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_famous,
    name
  )

  res
}

lcf_vector_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))
  # Function call
  res <- .Call(
    R_igraph_lcf_vector,
    n,
    shifts,
    repeats
  )

  if (igraph_opt("add.params")) {
    res$name <- 'LCF graph'
  }

  res
}

mycielski_graph_impl <- function(
  k
) {
  # Argument checks
  k <- as.numeric(k)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_mycielski_graph,
    k
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_adjlist,
    adjlist,
    mode,
    duplicate
  )

  res
}

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))
  # 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")
  }
  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_full_multipartite,
    n,
    directed,
    mode
  )

  if (igraph_opt("add.params")) {
    res$name <- 'Full multipartite graph'
    res$n <- n
    res$mode <- 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")
) {
  # 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
  )
  method <- switch_igraph_arg(method, "smallest" = 0L, "largest" = 1L, "index" = 2L)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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'
    res$out_deg <- out_deg
    res$in_deg <- in_deg
    res$allowed_edge_types <- allowed_edge_types
    res$method <- method
  }

  res
}

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)
  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
  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'
    res$degrees1 <- degrees1
    res$degrees2 <- degrees2
    res$allowed_edge_types <- allowed_edge_types
    res$method <- method
  }

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_circulant,
    n,
    shifts,
    directed
  )

  if (igraph_opt("add.params")) {
    res$name <- 'Circulant graph'
    res$shifts <- shifts
  }

  res
}

generalized_petersen_impl <- function(
  n,
  k
) {
  # Argument checks
  n <- as.numeric(n)
  k <- as.numeric(k)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_generalized_petersen,
    n,
    k
  )

  res
}

turan_impl <- function(
  n,
  r
) {
  # Argument checks
  n <- as.numeric(n)
  r <- as.numeric(r)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_turan,
    n,
    r
  )

  if (igraph_opt("add.params")) {
    res$name <- 'Turan graph'
    res$n <- n
    res$r <- r
  }

  res
}

weighted_sparsemat_impl <- function(
  A,
  directed,
  attr,
  loops = FALSE
) {
  # Argument checks
  requireNamespace("Matrix", quietly = TRUE)
  A <- as(as(as(A, "dMatrix"), "generalMatrix"), "CsparseMatrix")
  directed <- as.logical(directed)
  loops <- as.logical(loops)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_weighted_sparsemat,
    A,
    directed,
    attr,
    loops
  )

  res
}

barabasi_game_impl <- function(
  n,
  power = 1.0,
  m = 1,
  outseq = NULL,
  outpref = FALSE,
  A = 1.0,
  directed = TRUE,
  algo = c("bag", "psumtree", "psumtree_multiple"),
  start_from = NULL
) {
  # Argument checks
  n <- as.numeric(n)
  power <- as.numeric(power)
  m <- as.numeric(m)
  if (!is.null(outseq)) {
    outseq <- as.numeric(outseq)
  }
  outpref <- as.logical(outpref)
  A <- as.numeric(A)
  directed <- as.logical(directed)
  algo <- switch_igraph_arg(algo, "bag" = 0L, "psumtree" = 1L, "psumtree_multiple" = 2L)
  if (!is.null(start_from)) {
    ensure_igraph(start_from)
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_barabasi_game,
    n,
    power,
    m,
    outseq,
    outpref,
    A,
    directed,
    algo,
    start_from
  )

  res
}

erdos_renyi_game_gnp_impl <- function(
  n,
  p,
  directed = FALSE,
  loops = FALSE
) {
  # Argument checks
  n <- as.numeric(n)
  p <- as.numeric(p)
  directed <- as.logical(directed)
  loops <- as.logical(loops)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_erdos_renyi_game_gnp,
    n,
    p,
    directed,
    loops
  )

  res
}

erdos_renyi_game_gnm_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_erdos_renyi_game_gnm,
    n,
    m,
    directed,
    loops
  )

  res
}

degree_sequence_game_impl <- function(
  out_deg,
  in_deg = NULL,
  method = c("configuration", "fast_heur_simple", "configuration_simple", "edge_switching_simple", "vl")
) {
  # Argument checks
  out_deg <- as.numeric(out_deg)
  if (!is.null(in_deg)) {
    in_deg <- as.numeric(in_deg)
  }
  method <- switch_igraph_arg(
    method,
    "configuration" = 0L,
    "vl" = 1L,
    "fast_heur_simple" = 2L,
    "configuration_simple" = 3L,
    "edge_switching_simple" = 4L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_degree_sequence_game,
    out_deg,
    in_deg,
    method
  )

  res
}

growing_random_game_impl <- function(
  n,
  m = 1,
  ...,
  directed = TRUE,
  citation = FALSE
) {
  # Argument checks
  check_dots_empty()
  n <- as.numeric(n)
  m <- as.numeric(m)
  directed <- as.logical(directed)
  citation <- as.logical(citation)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_growing_random_game,
    n,
    m,
    directed,
    citation
  )

  if (igraph_opt("add.params")) {
    res$name <- 'Growing random graph'
    res$m <- m
    res$citation <- citation
  }

  res
}

barabasi_aging_game_impl <- function(
  nodes,
  m = 1,
  outseq = NULL,
  outpref = FALSE,
  pa_exp = 1.0,
  aging_exp = 0.0,
  aging_bin = 1,
  zero_deg_appeal = 1.0,
  zero_age_appeal = 0.0,
  deg_coef = 1.0,
  age_coef = 1.0,
  directed = TRUE
) {
  # Argument checks
  nodes <- as.numeric(nodes)
  m <- as.numeric(m)
  if (!is.null(outseq)) {
    outseq <- as.numeric(outseq)
  }
  outpref <- as.logical(outpref)
  pa_exp <- as.numeric(pa_exp)
  aging_exp <- as.numeric(aging_exp)
  aging_bin <- as.numeric(aging_bin)
  zero_deg_appeal <- as.numeric(zero_deg_appeal)
  zero_age_appeal <- as.numeric(zero_age_appeal)
  deg_coef <- as.numeric(deg_coef)
  age_coef <- as.numeric(age_coef)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_barabasi_aging_game,
    nodes,
    m,
    outseq,
    outpref,
    pa_exp,
    aging_exp,
    aging_bin,
    zero_deg_appeal,
    zero_age_appeal,
    deg_coef,
    age_coef,
    directed
  )

  res
}

recent_degree_game_impl <- function(
  n,
  power = 1.0,
  window = 1,
  m = 1,
  outseq = NULL,
  outpref = FALSE,
  zero_appeal = 1.0,
  directed = TRUE
) {
  # Argument checks
  n <- as.numeric(n)
  power <- as.numeric(power)
  window <- as.numeric(window)
  m <- as.numeric(m)
  if (!is.null(outseq)) {
    outseq <- as.numeric(outseq)
  }
  outpref <- as.logical(outpref)
  zero_appeal <- as.numeric(zero_appeal)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_recent_degree_game,
    n,
    power,
    window,
    m,
    outseq,
    outpref,
    zero_appeal,
    directed
  )

  res
}

recent_degree_aging_game_impl <- function(
  nodes,
  m = 1,
  outseq = NULL,
  outpref = FALSE,
  pa_exp = 1.0,
  aging_exp = 0.0,
  aging_bin = 1,
  window = 1,
  zero_appeal = 1.0,
  directed = TRUE
) {
  # Argument checks
  nodes <- as.numeric(nodes)
  m <- as.numeric(m)
  if (!is.null(outseq)) {
    outseq <- as.numeric(outseq)
  }
  outpref <- as.logical(outpref)
  pa_exp <- as.numeric(pa_exp)
  aging_exp <- as.numeric(aging_exp)
  aging_bin <- as.numeric(aging_bin)
  window <- as.numeric(window)
  zero_appeal <- as.numeric(zero_appeal)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_recent_degree_aging_game,
    nodes,
    m,
    outseq,
    outpref,
    pa_exp,
    aging_exp,
    aging_bin,
    window,
    zero_appeal,
    directed
  )

  res
}

callaway_traits_game_impl <- function(
  nodes,
  types,
  edges_per_step = 1,
  type_dist,
  pref_matrix,
  directed = FALSE
) {
  # Argument checks
  nodes <- as.numeric(nodes)
  types <- as.numeric(types)
  edges_per_step <- as.numeric(edges_per_step)
  type_dist <- as.numeric(type_dist)
  pref_matrix[] <- as.numeric(pref_matrix)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_callaway_traits_game,
    nodes,
    types,
    edges_per_step,
    type_dist,
    pref_matrix,
    directed
  )

  res
}

establishment_game_impl <- function(
  nodes,
  types,
  k = 1,
  type_dist,
  pref_matrix,
  directed = TRUE
) {
  # Argument checks
  nodes <- as.numeric(nodes)
  types <- as.numeric(types)
  k <- as.numeric(k)
  type_dist <- as.numeric(type_dist)
  pref_matrix[] <- as.numeric(pref_matrix)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_establishment_game,
    nodes,
    types,
    k,
    type_dist,
    pref_matrix,
    directed
  )

  res
}

grg_game_impl <- function(
  nodes,
  radius,
  torus = FALSE
) {
  # Argument checks
  nodes <- as.numeric(nodes)
  radius <- as.numeric(radius)
  torus <- as.logical(torus)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_grg_game,
    nodes,
    radius,
    torus
  )

  res
}

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)
  type_dist <- as.numeric(type_dist)
  fixed_sizes <- as.logical(fixed_sizes)
  pref_matrix[] <- as.numeric(pref_matrix)
  directed <- as.logical(directed)
  loops <- as.logical(loops)

  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
}

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)
  in_types <- as.numeric(in_types)
  type_dist_matrix[] <- as.numeric(type_dist_matrix)
  pref_matrix[] <- as.numeric(pref_matrix)
  loops <- as.logical(loops)

  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
}

rewire_edges_impl <- function(
  graph,
  prob,
  loops = FALSE,
  multiple = FALSE
) {
  # Argument checks
  ensure_igraph(graph)
  prob <- as.numeric(prob)
  loops <- as.logical(loops)
  multiple <- as.logical(multiple)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_rewire_edges,
    graph,
    prob,
    loops,
    multiple
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_rewire_directed_edges,
    graph,
    prob,
    loops,
    mode
  )

  res
}

watts_strogatz_game_impl <- function(
  dim,
  size,
  nei,
  p,
  loops = FALSE,
  multiple = FALSE
) {
  # Argument checks
  dim <- as.numeric(dim)
  size <- as.numeric(size)
  nei <- as.numeric(nei)
  p <- as.numeric(p)
  loops <- as.logical(loops)
  multiple <- as.logical(multiple)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_watts_strogatz_game,
    dim,
    size,
    nei,
    p,
    loops,
    multiple
  )

  res
}

lastcit_game_impl <- function(
  nodes,
  edges_per_node = 1,
  agebins = 1,
  preference,
  directed = TRUE
) {
  # Argument checks
  nodes <- as.numeric(nodes)
  edges_per_node <- as.numeric(edges_per_node)
  agebins <- as.numeric(agebins)
  preference <- as.numeric(preference)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_lastcit_game,
    nodes,
    edges_per_node,
    agebins,
    preference,
    directed
  )

  res
}

cited_type_game_impl <- function(
  nodes,
  types,
  pref,
  edges_per_step = 1,
  directed = TRUE
) {
  # Argument checks
  nodes <- as.numeric(nodes)
  types <- as.numeric(types) - 1
  pref <- as.numeric(pref)
  edges_per_step <- as.numeric(edges_per_step)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_cited_type_game,
    nodes,
    types,
    pref,
    edges_per_step,
    directed
  )

  res
}

citing_cited_type_game_impl <- function(
  nodes,
  types,
  pref,
  edges_per_step = 1,
  directed = TRUE
) {
  # Argument checks
  nodes <- as.numeric(nodes)
  types <- as.numeric(types) - 1
  pref[] <- as.numeric(pref)
  edges_per_step <- as.numeric(edges_per_step)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_citing_cited_type_game,
    nodes,
    types,
    pref,
    edges_per_step,
    directed
  )

  res
}

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)
  bw_factor <- as.numeric(bw_factor)
  ambs <- as.numeric(ambs)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_forest_fire_game,
    nodes,
    fw_prob,
    bw_factor,
    ambs,
    directed
  )

  if (igraph_opt("add.params")) {
    res$name <- 'Forest fire model'
    res$fw_prob <- fw_prob
    res$bw_factor <- bw_factor
    res$ambs <- ambs
  }

  res
}

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))
  # Function call
  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'
    res$islands_n <- islands_n
    res$islands_size <- islands_size
    res$islands_pin <- islands_pin
    res$n_inter <- n_inter
  }

  res
}

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)
  if (!is.null(in_weights)) {
    in_weights <- as.numeric(in_weights)
  }
  loops <- as.logical(loops)
  variant <- switch_igraph_arg(variant, "original" = 0L, "maxent" = 1L, "nr" = 2L)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_chung_lu_game,
    out_weights,
    in_weights,
    loops,
    variant
  )

  if (igraph_opt("add.params")) {
    res$name <- 'Chung-Lu model'
    res$variant <- variant
  }

  res
}

static_fitness_game_impl <- function(
  no_of_edges,
  fitness_out,
  fitness_in = NULL,
  loops = FALSE,
  multiple = FALSE
) {
  # 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)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_static_fitness_game,
    no_of_edges,
    fitness_out,
    fitness_in,
    loops,
    multiple
  )

  if (igraph_opt("add.params")) {
    res$name <- 'Static fitness model'
    res$loops <- loops
    res$multiple <- multiple
  }

  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
) {
  # 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)
  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
  )

  if (igraph_opt("add.params")) {
    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
  }

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_k_regular_game,
    no_of_nodes,
    k,
    directed,
    multiple
  )

  if (igraph_opt("add.params")) {
    res$name <- 'k-regular graph'
    res$k <- k
  }

  res
}

sbm_game_impl <- function(
  n,
  pref_matrix,
  block_sizes,
  directed = FALSE,
  loops = FALSE
) {
  # 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)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_sbm_game,
    n,
    pref_matrix,
    block_sizes,
    directed,
    loops
  )

  if (igraph_opt("add.params")) {
    res$name <- 'Stochastic block model'
    res$loops <- loops
  }

  res
}

hsbm_game_impl <- function(
  n,
  m,
  rho,
  C,
  p
) {
  # Argument checks
  n <- as.numeric(n)
  m <- as.numeric(m)
  rho <- as.numeric(rho)
  C[] <- as.numeric(C)
  p <- as.numeric(p)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_hsbm_game,
    n,
    m,
    rho,
    C,
    p
  )

  if (igraph_opt("add.params")) {
    res$name <- 'Hierarchical stochastic block model'
    res$m <- m
    res$rho <- rho
    res$C <- C
    res$p <- p
  }

  res
}

hsbm_list_game_impl <- function(
  n,
  mlist,
  rholist,
  Clist,
  p
) {
  # Argument checks
  n <- as.numeric(n)
  mlist <- as.numeric(mlist)
  if (!is.list(Clist)) {
    cli::cli_abort("{.arg Clist} must be a list of matrices")
  }
  Clist <- lapply(Clist, function(m) {
    if (!is.matrix(m)) {
      cli::cli_abort("{.arg Clist} must be a list of matrices")
    }
    m[] <- as.numeric(m)
    m
  })
  p <- as.numeric(p)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_hsbm_list_game,
    n,
    mlist,
    rholist,
    Clist,
    p
  )

  if (igraph_opt("add.params")) {
    res$name <- 'Hierarchical stochastic block model'
    res$p <- p
  }

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_correlated_game,
    old_graph,
    corr,
    p,
    permutation
  )

  if (igraph_opt("add.params")) {
    res$name <- 'Correlated random graph'
    res$corr <- corr
    res$p <- p
  }

  res
}

correlated_pair_game_impl <- function(
  n,
  corr,
  p,
  directed = FALSE,
  permutation = NULL
) {
  # Argument checks
  n <- as.numeric(n)
  corr <- as.numeric(corr)
  p <- as.numeric(p)
  directed <- as.logical(directed)
  if (!is.null(permutation)) {
    permutation <- as.numeric(permutation) - 1
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_correlated_pair_game,
    n,
    corr,
    p,
    directed,
    permutation
  )

  res
}

dot_product_game_impl <- function(
  vecs,
  directed = FALSE
) {
  # Argument checks
  vecs[] <- as.numeric(vecs)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_dot_product_game,
    vecs,
    directed
  )

  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)
  v1 <- as_igraph_vs(graph, v1)
  if (length(v1) != 1) {
    cli::cli_abort(
      "{.arg v1} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  v2 <- as_igraph_vs(graph, v2)
  if (length(v2) != 1) {
    cli::cli_abort(
      "{.arg v2} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_are_adjacent,
    graph,
    v1 - 1,
    v2 - 1
  )

  res
}

are_connected_impl <- function(
  graph,
  v1,
  v2
) {
  # Argument checks
  ensure_igraph(graph)
  v1 <- as_igraph_vs(graph, v1)
  if (length(v1) != 1) {
    cli::cli_abort(
      "{.arg v1} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  v2 <- as_igraph_vs(graph, v2)
  if (length(v2) != 1) {
    cli::cli_abort(
      "{.arg v2} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_are_connected,
    graph,
    v1 - 1,
    v2 - 1
  )

  res
}

diameter_impl <- function(
  graph,
  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,
    directed,
    unconnected
  )

  res
}

diameter_dijkstra_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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  directed <- as.logical(directed)
  unconnected <- as.logical(unconnected)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_diameter_dijkstra,
    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)
  vids <- as_igraph_vs(graph, vids)
  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
  }
  if (!is.null(weights) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  normalized <- as.logical(normalized)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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 = -1
) {
  # Argument checks
  ensure_igraph(graph)
  vids <- as_igraph_vs(graph, vids)
  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
  }
  if (!is.null(weights) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  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
  )
  if (igraph_opt("add.vertex.names") && is_named(graph)) {
    names(res$res) <- vertex_attr(graph, "name", vids)
  }
  res
}

distances_impl <- function(
  graph,
  from = V(graph),
  to = V(graph),
  mode = c("out", "in", "all", "total")
) {
  # Argument checks
  ensure_igraph(graph)
  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
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_distances,
    graph,
    from - 1,
    to - 1,
    mode
  )

  res
}

distances_cutoff_impl <- function(
  graph,
  from = V(graph),
  to = V(graph),
  mode = c("out", "in", "all", "total"),
  cutoff = -1
) {
  # Argument checks
  ensure_igraph(graph)
  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
  )
  cutoff <- as.numeric(cutoff)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_distances_cutoff,
    graph,
    from - 1,
    to - 1,
    mode,
    cutoff
  )

  res
}

get_shortest_path_impl <- function(
  graph,
  from,
  to,
  mode = c("out", "in", "all", "total")
) {
  # Argument checks
  ensure_igraph(graph)
  from <- as_igraph_vs(graph, from)
  if (length(from) != 1) {
    cli::cli_abort(
      "{.arg from} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  to <- as_igraph_vs(graph, to)
  if (length(to) != 1) {
    cli::cli_abort(
      "{.arg to} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_get_shortest_path,
    graph,
    from - 1,
    to - 1,
    mode
  )
  if (igraph_opt("return.vs.es")) {
    res$vertices <- create_vs(graph, res$vertices)
  }
  if (igraph_opt("return.vs.es")) {
    res$edges <- create_es(graph, res$edges)
  }
  res
}

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)
  if (length(from) != 1) {
    cli::cli_abort(
      "{.arg from} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  to <- as_igraph_vs(graph, to)
  if (length(to) != 1) {
    cli::cli_abort(
      "{.arg to} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  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
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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)
  }
  if (igraph_opt("return.vs.es")) {
    res$edges <- create_es(graph, res$edges)
  }
  res
}

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)
  if (length(from) != 1) {
    cli::cli_abort(
      "{.arg from} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  to <- as_igraph_vs(graph, to)
  if (length(to) != 1) {
    cli::cli_abort(
      "{.arg to} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  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
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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)
  }
  if (igraph_opt("return.vs.es")) {
    res$edges <- create_es(graph, res$edges)
  }
  res
}

get_shortest_path_astar_impl <- function(
  graph,
  from,
  to,
  weights = NULL,
  mode = c("out", "in", "all", "total"),
  heuristic = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  from <- as_igraph_vs(graph, from)
  if (length(from) != 1) {
    cli::cli_abort(
      "{.arg from} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  to <- as_igraph_vs(graph, to)
  if (length(to) != 1) {
    cli::cli_abort(
      "{.arg to} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  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
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_get_shortest_path_astar,
    graph,
    from - 1,
    to - 1,
    weights,
    mode
  )
  if (igraph_opt("return.vs.es")) {
    res$vertices <- create_vs(graph, res$vertices)
  }
  if (igraph_opt("return.vs.es")) {
    res$edges <- create_es(graph, res$edges)
  }
  res
}

get_shortest_paths_impl <- function(
  graph,
  from,
  to = V(graph),
  mode = c("out", "in", "all", "total")
) {
  # Argument checks
  ensure_igraph(graph)
  from <- as_igraph_vs(graph, from)
  if (length(from) != 1) {
    cli::cli_abort(
      "{.arg from} must specify exactly 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
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_get_shortest_paths,
    graph,
    from - 1,
    to - 1,
    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
}

get_all_shortest_paths_impl <- function(
  graph,
  from,
  to,
  mode = c("out", "in", "all", "total")
) {
  # Argument checks
  ensure_igraph(graph)
  from <- as_igraph_vs(graph, from)
  if (length(from) != 1) {
    cli::cli_abort(
      "{.arg from} must specify exactly 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
  )

  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
}

distances_dijkstra_impl <- function(
  graph,
  from = V(graph),
  to = V(graph),
  weights = NULL,
  mode = c("out", "in", "all", "total")
) {
  # Argument checks
  ensure_igraph(graph)
  from <- as_igraph_vs(graph, from)
  to <- as_igraph_vs(graph, to)
  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
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_distances_dijkstra,
    graph,
    from - 1,
    to - 1,
    weights,
    mode
  )

  res
}

distances_dijkstra_cutoff_impl <- function(
  graph,
  from = V(graph),
  to = V(graph),
  weights = NULL,
  mode = c("out", "in", "all", "total"),
  cutoff = -1
) {
  # 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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )
  cutoff <- as.numeric(cutoff)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_distances_dijkstra_cutoff,
    graph,
    from - 1,
    to - 1,
    weights,
    mode,
    cutoff
  )

  res
}

get_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)
  if (length(from) != 1) {
    cli::cli_abort(
      "{.arg from} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  to <- as_igraph_vs(graph, to)
  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
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_get_shortest_paths_dijkstra,
    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
}

get_shortest_paths_bellman_ford_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)
  if (length(from) != 1) {
    cli::cli_abort(
      "{.arg from} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  to <- as_igraph_vs(graph, to)
  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
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_get_shortest_paths_bellman_ford,
    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
}

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)
  if (length(from) != 1) {
    cli::cli_abort(
      "{.arg from} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  to <- as_igraph_vs(graph, to)
  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
  }
  mode <- switch_igraph_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
}

distances_bellman_ford_impl <- function(
  graph,
  from = V(graph),
  to = V(graph),
  weights = NULL,
  mode = c("out", "in", "all", "total")
) {
  # Argument checks
  ensure_igraph(graph)
  from <- as_igraph_vs(graph, from)
  to <- as_igraph_vs(graph, to)
  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
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_distances_bellman_ford,
    graph,
    from - 1,
    to - 1,
    weights,
    mode
  )

  res
}

distances_johnson_impl <- function(
  graph,
  from = V(graph),
  to = V(graph),
  weights = NULL
) {
  # 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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_distances_johnson,
    graph,
    from - 1,
    to - 1,
    weights
  )

  res
}

distances_floyd_warshall_impl <- function(
  graph,
  from = V(graph),
  to = V(graph),
  weights = NULL,
  mode = c("out", "in", "all", "total"),
  method = c("automatic", "original", "tree")
) {
  # 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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )
  method <- switch_igraph_arg(method, "automatic" = 0L, "original" = 1L, "tree" = 2L)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_distances_floyd_warshall,
    graph,
    from - 1,
    to - 1,
    weights,
    mode,
    method
  )

  res
}

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)
  generators <- as_igraph_vs(graph, generators)
  generators <- generators - 1
  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
  }
  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
  res <- .Call(
    R_igraph_voronoi,
    graph,
    generators,
    weights,
    mode,
    tiebreaker
  )

  res
}

get_all_simple_paths_impl <- function(
  graph,
  from,
  to = V(graph),
  cutoff = -1,
  mode = c("out", "in", "all", "total")
) {
  # Argument checks
  ensure_igraph(graph)
  from <- as_igraph_vs(graph, from)
  if (length(from) != 1) {
    cli::cli_abort(
      "{.arg from} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  to <- as_igraph_vs(graph, to)
  cutoff <- as.numeric(cutoff)
  mode <- switch_igraph_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
}

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)
  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
  }
  k <- as.numeric(k)
  from <- as_igraph_vs(graph, from)
  if (length(from) != 1) {
    cli::cli_abort(
      "{.arg from} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  to <- as_igraph_vs(graph, to)
  if (length(to) != 1) {
    cli::cli_abort(
      "{.arg to} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  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")
) {
  # Argument checks
  ensure_igraph(graph)
  from <- as_igraph_vs(graph, from)
  if (length(from) != 1) {
    cli::cli_abort(
      "{.arg from} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  to <- as_igraph_vs(graph, to)
  if (length(to) != 1) {
    cli::cli_abort(
      "{.arg to} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  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
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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)
  }
  if (igraph_opt("return.vs.es")) {
    res$edges <- create_es(graph, res$edges)
  }
  res
}

get_widest_paths_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)
  if (length(from) != 1) {
    cli::cli_abort(
      "{.arg from} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  to <- as_igraph_vs(graph, to)
  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
  }
  mode <- switch_igraph_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")
) {
  # 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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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 = NULL,
  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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  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
}

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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_spanner,
    graph,
    stretch,
    weights
  )
  if (igraph_opt("return.vs.es")) {
    res <- create_es(graph, res)
  }
  res
}

subcomponent_impl <- function(
  graph,
  vid,
  mode = c("all", "out", "in", "total")
) {
  # Argument checks
  ensure_igraph(graph)
  vid <- as_igraph_vs(graph, vid)
  if (length(vid) != 1) {
    cli::cli_abort(
      "{.arg vid} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_subcomponent,
    graph,
    vid - 1,
    mode
  )
  if (igraph_opt("return.vs.es")) {
    res <- create_vs(graph, res)
  }
  res
}

betweenness_impl <- function(
  graph,
  vids = V(graph),
  directed = TRUE,
  weights = NULL
) {
  # 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
  }
  if (!is.null(weights) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_betweenness,
    graph,
    vids - 1,
    directed,
    weights
  )
  if (igraph_opt("add.vertex.names") && is_named(graph)) {
    names(res) <- vertex_attr(graph, "name", vids)
  }
  res
}

betweenness_cutoff_impl <- function(
  graph,
  vids = V(graph),
  directed = TRUE,
  weights = NULL,
  cutoff = -1
) {
  # 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
  }
  if (!is.null(weights) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  cutoff <- as.numeric(cutoff)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_betweenness_cutoff,
    graph,
    vids - 1,
    directed,
    weights,
    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
) {
  # 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
  }
  if (!is.null(weights) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_betweenness_subset,
    graph,
    vids - 1,
    directed,
    sources - 1,
    targets - 1,
    weights
  )
  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
) {
  # 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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_edge_betweenness,
    graph,
    directed,
    weights
  )

  res
}

edge_betweenness_cutoff_impl <- function(
  graph,
  directed = TRUE,
  weights = NULL,
  cutoff = -1
) {
  # 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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  cutoff <- as.numeric(cutoff)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_edge_betweenness_cutoff,
    graph,
    directed,
    weights,
    cutoff
  )

  res
}

edge_betweenness_subset_impl <- function(
  graph,
  eids = E(graph),
  directed = TRUE,
  sources = V(graph),
  targets = V(graph),
  weights = NULL
) {
  # 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
  }
  if (!is.null(weights) && !all(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
  )

  res
}

harmonic_centrality_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)
  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
  }
  if (!is.null(weights) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  normalized <- as.logical(normalized)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_harmonic_centrality,
    graph,
    vids - 1,
    mode,
    weights,
    normalized
  )
  if (igraph_opt("add.vertex.names") && is_named(graph)) {
    names(res) <- vertex_attr(graph, "name", vids)
  }
  res
}

harmonic_centrality_cutoff_impl <- function(
  graph,
  vids = V(graph),
  mode = c("out", "in", "all", "total"),
  weights = NULL,
  normalized = FALSE,
  cutoff = -1
) {
  # Argument checks
  ensure_igraph(graph)
  vids <- as_igraph_vs(graph, vids)
  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
  }
  if (!is.null(weights) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  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
  )
  if (igraph_opt("add.vertex.names") && is_named(graph)) {
    names(res) <- vertex_attr(graph, "name", vids)
  }
  res
}

pagerank_impl <- function(
  graph,
  algo = c("prpack", "arpack"),
  vids = V(graph),
  directed = TRUE,
  damping = 0.85,
  weights = NULL,
  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(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
  }
  if (is.null(options)) {
    if (algo == 0L) {
      options <- list(niter = 1000, eps = 0.001)
    } else if (algo == 1L) {
      options <- arpack_defaults()
    } else {
      options <- NULL
    }
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_pagerank,
    graph,
    algo,
    vids - 1,
    directed,
    damping,
    weights,
    options
  )
  if (igraph_opt("add.vertex.names") && is_named(graph)) {
    names(res$vector) <- vertex_attr(graph, "name", vids)
  }
  res
}

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_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
  }
  if (!is.null(weights) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  if (is.null(options)) {
    if (algo == 0L) {
      options <- list(niter = 1000, eps = 0.001)
    } else if (algo == 1L) {
      options <- arpack_defaults()
    } else {
      options <- NULL
    }
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_personalized_pagerank,
    graph,
    algo,
    vids - 1,
    directed,
    damping,
    personalized,
    weights,
    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
) {
  # 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
  }
  if (!is.null(weights) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  if (is.null(options)) {
    if (algo == 0L) {
      options <- list(niter = 1000, eps = 0.001)
    } else if (algo == 1L) {
      options <- arpack_defaults()
    } else {
      options <- NULL
    }
  }

  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
  )
  if (igraph_opt("add.vertex.names") && is_named(graph)) {
    names(res$vector) <- vertex_attr(graph, "name", vids)
  }
  if (!details) {
    res <- res$vector
  }
  res
}

rewire_impl <- function(
  rewire,
  n,
  mode = c("simple", "simple_loops")
) {
  # Argument checks
  ensure_igraph(rewire)
  n <- as.numeric(n)
  mode <- switch_igraph_arg(mode, "simple" = 0L, "simple_loops" = 1L)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_rewire,
    rewire,
    n,
    mode
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_induced_subgraph,
    graph,
    vids - 1,
    impl
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_subgraph_from_edges,
    graph,
    eids - 1,
    delete_vertices
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_reverse_edges,
    graph,
    eids - 1
  )

  res
}

average_path_length_impl <- function(
  graph,
  directed = TRUE,
  unconn = TRUE,
  details = FALSE
) {
  # Argument checks
  ensure_igraph(graph)
  directed <- as.logical(directed)
  unconn <- as.logical(unconn)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_average_path_length,
    graph,
    directed,
    unconn
  )
  if (!details) {
    res <- res$res
  }
  res
}

average_path_length_dijkstra_impl <- function(
  graph,
  weights = NULL,
  directed = TRUE,
  unconnected = 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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  directed <- as.logical(directed)
  unconnected <- as.logical(unconnected)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_average_path_length_dijkstra,
    graph,
    weights,
    directed,
    unconnected
  )
  if (!details) {
    res <- res$res
  }
  res
}

path_length_hist_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_path_length_hist,
    graph,
    directed
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_simplify,
    graph,
    remove_multiple,
    remove_loops,
    edge_attr_comb
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_transitivity_undirected,
    graph,
    mode
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_transitivity_local_undirected,
    graph,
    vids - 1,
    mode
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_transitivity_avglocal_undirected,
    graph,
    mode
  )

  res
}

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)
  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
  }
  mode <- switch_igraph_arg(mode, "nan" = 0L, "zero" = 1L)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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
) {
  # Argument checks
  ensure_igraph(graph)
  eids <- as_igraph_es(graph, eids)
  k <- as.numeric(k)
  offset <- as.logical(offset)
  normalize <- as.logical(normalize)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_ecc,
    graph,
    eids - 1,
    k,
    offset,
    normalize
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_reciprocity,
    graph,
    ignore_loops,
    mode
  )

  res
}

constraint_impl <- function(
  graph,
  vids = V(graph),
  weights = NULL
) {
  # 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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_constraint,
    graph,
    vids - 1,
    weights
  )

  res
}

maxdegree_impl <- function(
  graph,
  ...,
  v = V(graph),
  mode = c("all", "out", "in", "total"),
  loops = TRUE
) {
  # Argument checks
  check_dots_empty()
  ensure_igraph(graph)
  v <- as_igraph_vs(graph, v)
  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_maxdegree,
    graph,
    v - 1,
    mode,
    loops
  )

  res
}

density_impl <- function(
  graph,
  loops = FALSE
) {
  # Argument checks
  ensure_igraph(graph)
  loops <- as.logical(loops)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_density,
    graph,
    loops
  )

  res
}

mean_degree_impl <- function(
  graph,
  loops = TRUE
) {
  # Argument checks
  ensure_igraph(graph)
  loops <- as.logical(loops)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_mean_degree,
    graph,
    loops
  )

  res
}

neighborhood_size_impl <- function(
  graph,
  vids,
  order,
  mode = c("all", "out", "in", "total"),
  mindist = 0
) {
  # Argument checks
  ensure_igraph(graph)
  vids <- as_igraph_vs(graph, vids)
  order <- as.numeric(order)
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )
  mindist <- as.numeric(mindist)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_neighborhood_size,
    graph,
    vids - 1,
    order,
    mode,
    mindist
  )

  res
}

neighborhood_impl <- function(
  graph,
  vids,
  order,
  mode = c("all", "out", "in", "total"),
  mindist = 0
) {
  # Argument checks
  ensure_igraph(graph)
  vids <- as_igraph_vs(graph, vids)
  order <- as.numeric(order)
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )
  mindist <- as.numeric(mindist)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_neighborhood,
    graph,
    vids - 1,
    order,
    mode,
    mindist
  )
  if (igraph_opt("return.vs.es")) {
    res <- lapply(res, unsafe_create_vs, graph = graph, verts = V(graph))
  }
  res
}

neighborhood_graphs_impl <- function(
  graph,
  vids,
  order,
  mode = c("all", "out", "in", "total"),
  mindist = 0
) {
  # Argument checks
  ensure_igraph(graph)
  vids <- as_igraph_vs(graph, vids)
  order <- as.numeric(order)
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )
  mindist <- as.numeric(mindist)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_neighborhood_graphs,
    graph,
    vids - 1,
    order,
    mode,
    mindist
  )

  res
}

topological_sorting_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))
  # Function call
  res <- .Call(
    R_igraph_topological_sorting,
    graph,
    mode
  )
  if (igraph_opt("return.vs.es")) {
    res <- create_vs(graph, res)
  }
  res
}

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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  algo <- switch_igraph_arg(algo, "exact_ip" = 0L, "approx_eades" = 1L)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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")
) {
  # Argument checks
  ensure_igraph(graph)
  if (is.null(weights) && "weight" %in% vertex_attr_names(graph)) {
    weights <- V(graph)$weight
  }
  if (!is.null(weights) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  algo <- switch_igraph_arg(algo, "exact_ip" = 0L)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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)
) {
  # Argument checks
  ensure_igraph(graph)
  eids <- as_igraph_es(graph, eids)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_is_loop,
    graph,
    eids - 1
  )

  res
}

is_dag_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_is_dag,
    graph
  )

  res
}

is_acyclic_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_is_acyclic,
    graph
  )

  res
}

is_simple_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_is_simple,
    graph
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_is_multiple,
    graph,
    eids - 1
  )

  res
}

has_loop_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_has_loop,
    graph
  )

  res
}

has_multiple_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_has_multiple,
    graph
  )

  res
}

count_loops_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_count_loops,
    graph
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_count_multiple,
    graph,
    eids - 1
  )

  res
}

girth_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_girth,
    graph
  )
  if (igraph_opt("return.vs.es")) {
    res$circle <- create_vs(graph, res$circle)
  }
  res
}

is_perfect_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_is_perfect,
    graph
  )

  res
}

add_edge_impl <- function(
  graph,
  from,
  to
) {
  # Argument checks
  ensure_igraph(graph)
  from <- as.numeric(from)
  to <- as.numeric(to)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_add_edge,
    graph,
    from,
    to
  )

  res
}

eigenvector_centrality_impl <- function(
  graph,
  directed = FALSE,
  scale = TRUE,
  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) && !all(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_eigenvector_centrality,
    graph,
    directed,
    scale,
    weights,
    options
  )
  if (igraph_opt("add.vertex.names") && is_named(graph)) {
    names(res$vector) <- vertex_attr(graph, "name", V(graph))
  }
  res
}

hub_score_impl <- function(
  graph,
  scale = TRUE,
  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) && !all(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_score,
    graph,
    scale,
    weights,
    options
  )
  if (igraph_opt("add.vertex.names") && is_named(graph)) {
    names(res$vector) <- vertex_attr(graph, "name", V(graph))
  }
  res
}

authority_score_impl <- function(
  graph,
  scale = TRUE,
  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) && !all(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_authority_score,
    graph,
    scale,
    weights,
    options
  )
  if (igraph_opt("add.vertex.names") && is_named(graph)) {
    names(res$vector) <- vertex_attr(graph, "name", V(graph))
  }
  res
}

hub_and_authority_scores_impl <- function(
  graph,
  scale = TRUE,
  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) && !all(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
  )
  if (igraph_opt("add.vertex.names") && is_named(graph)) {
    names(res$hub) <- vertex_attr(graph, "name", V(graph))
  }
  if (igraph_opt("add.vertex.names") && is_named(graph)) {
    names(res$authority) <- vertex_attr(graph, "name", V(graph))
  }
  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_unfold_tree,
    graph,
    mode,
    roots
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_is_mutual,
    graph,
    eids - 1,
    loops
  )

  res
}

has_mutual_impl <- function(
  graph,
  loops = TRUE
) {
  # Argument checks
  ensure_igraph(graph)
  loops <- as.logical(loops)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_has_mutual,
    graph,
    loops
  )

  res
}

maximum_cardinality_search_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_maximum_cardinality_search,
    graph
  )
  if (igraph_opt("return.vs.es")) {
    res$alpham1 <- create_vs(graph, res$alpham1)
  }
  res
}

is_chordal_impl <- function(
  graph,
  alpha = NULL,
  alpham1 = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  if (!is.null(alpha)) {
    alpha <- as.numeric(alpha) - 1
  }
  if (!is.null(alpham1)) {
    alpham1 <- as_igraph_vs(graph, alpham1)
    alpham1 <- alpham1 - 1
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_is_chordal,
    graph,
    alpha,
    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
) {
  # Argument checks
  ensure_igraph(graph)
  vids <- as_igraph_vs(graph, vids)
  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
  }
  if (!is.null(weights) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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
) {
  # 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
  }
  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))
  # Function call
  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
) {
  # 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
  }
  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 = TRUE,
  weights = NULL
) {
  # 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 <- as.logical(loops)
  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
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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
) {
  # Argument checks
  scores <- as.numeric(scores)
  theoretical_max <- as.numeric(theoretical_max)
  normalized <- as.logical(normalized)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_centralization,
    scores,
    theoretical_max,
    normalized
  )

  res
}

centralization_degree_impl <- function(
  graph,
  mode = c("all", "out", "in", "total"),
  loops = TRUE,
  normalized = TRUE
) {
  # Argument checks
  ensure_igraph(graph)
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )
  loops <- as.logical(loops)
  normalized <- as.logical(normalized)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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
) {
  # 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 <- 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)
  directed <- as.logical(directed)
  normalized <- as.logical(normalized)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_centralization_betweenness,
    graph,
    directed,
    normalized
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_centralization_betweenness_tmax,
    graph,
    nodes,
    directed
  )

  res
}

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))
  # Function call
  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")
) {
  # 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))
  # Function call
  res <- .Call(
    R_igraph_centralization_closeness_tmax,
    graph,
    nodes,
    mode
  )

  res
}

centralization_eigenvector_centrality_impl <- function(
  graph,
  directed = FALSE,
  scale = TRUE,
  options = arpack_defaults(),
  normalized = TRUE
) {
  # Argument checks
  ensure_igraph(graph)
  directed <- as.logical(directed)
  scale <- as.logical(scale)
  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
}

centralization_eigenvector_centrality_tmax_impl <- function(
  graph = NULL,
  nodes = 0,
  directed = FALSE,
  scale = TRUE
) {
  # Argument checks
  if (!is.null(graph)) {
    ensure_igraph(graph)
  }
  nodes <- as.numeric(nodes)
  directed <- as.logical(directed)
  scale <- as.logical(scale)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_centralization_eigenvector_centrality_tmax,
    graph,
    nodes,
    directed,
    scale
  )

  res
}

assortativity_nominal_impl <- function(
  graph,
  types,
  directed = TRUE,
  normalized = TRUE
) {
  # Argument checks
  ensure_igraph(graph)
  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
}

assortativity_impl <- function(
  graph,
  values,
  values_in = NULL,
  directed = TRUE,
  normalized = TRUE
) {
  # Argument checks
  ensure_igraph(graph)
  values <- as.numeric(values)
  if (!is.null(values_in)) {
    values_in <- as.numeric(values_in)
  }
  directed <- as.logical(directed)
  normalized <- as.logical(normalized)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_assortativity,
    graph,
    values,
    values_in,
    directed,
    normalized
  )

  res
}

assortativity_degree_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_assortativity_degree,
    graph,
    directed
  )

  res
}

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) && !all(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)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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 = -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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  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)
  max_to_degree <- as.numeric(max_to_degree)

  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
}

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) && !all(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)
  normalized <- as.logical(normalized)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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")
) {
  # 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))
  # Function call
  res <- .Call(
    R_igraph_contract_vertices,
    graph,
    mapping,
    vertex_attr_comb
  )

  res
}

eccentricity_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))
  # Function call
  res <- .Call(
    R_igraph_eccentricity,
    graph,
    vids - 1,
    mode
  )
  if (igraph_opt("add.vertex.names") && is_named(graph)) {
    names(res) <- vertex_attr(graph, "name", vids)
  }
  res
}

eccentricity_dijkstra_impl <- function(
  graph,
  vids = V(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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  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))
  # Function call
  res <- .Call(
    R_igraph_eccentricity_dijkstra,
    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,
  mode = c("all", "out", "in", "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))
  # Function call
  res <- .Call(
    R_igraph_graph_center,
    graph,
    mode
  )
  if (igraph_opt("return.vs.es")) {
    res <- create_vs(graph, res)
  }
  res
}

graph_center_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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  mode <- switch_igraph_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
  )
  if (igraph_opt("return.vs.es")) {
    res <- create_vs(graph, res)
  }
  res
}

radius_impl <- function(
  graph,
  mode = c("all", "out", "in", "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))
  # Function call
  res <- .Call(
    R_igraph_radius,
    graph,
    mode
  )

  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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  mode <- switch_igraph_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
) {
  # Argument checks
  ensure_igraph(graph)
  start_vid <- as_igraph_vs(graph, start_vid)
  if (length(start_vid) != 1) {
    cli::cli_abort(
      "{.arg start_vid} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  directed <- as.logical(directed)
  unconnected <- as.logical(unconnected)

  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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  start_vid <- as_igraph_vs(graph, start_vid)
  if (length(start_vid) != 1) {
    cli::cli_abort(
      "{.arg start_vid} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  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
}

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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  vids <- as_igraph_vs(graph, vids)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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")
) {
  # 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
  }
  start <- as_igraph_vs(graph, start)
  if (length(start) != 1) {
    cli::cli_abort(
      "{.arg start} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )
  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
  )
  if (igraph_opt("return.vs.es")) {
    res$vertices <- create_vs(graph, res$vertices)
  }
  if (igraph_opt("return.vs.es")) {
    res$edges <- create_es(graph, res$edges)
  }
  res
}

random_edge_walk_impl <- function(
  graph,
  weights = NULL,
  start,
  mode = c("out", "in", "all", "total"),
  steps,
  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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  start <- as_igraph_vs(graph, start)
  if (length(start) != 1) {
    cli::cli_abort(
      "{.arg start} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )
  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_edge_walk,
    graph,
    weights,
    start - 1,
    mode,
    steps,
    stuck
  )
  if (igraph_opt("return.vs.es")) {
    res <- create_es(graph, res)
  }
  res
}

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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_global_efficiency,
    graph,
    weights,
    directed
  )

  res
}

local_efficiency_impl <- function(
  graph,
  vids = V(graph),
  weights = NULL,
  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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  directed <- as.logical(directed)
  mode <- switch_igraph_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
  )
  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")
) {
  # 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
  }
  directed <- as.logical(directed)
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_average_local_efficiency,
    graph,
    weights,
    directed,
    mode
  )

  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)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_transitive_closure,
    graph
  )

  res
}

trussness_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_trussness,
    graph
  )

  res
}

is_bigraphical_impl <- function(
  degrees1,
  degrees2,
  allowed_edge_types = c("simple", "loops", "multi", "all")
) {
  # Argument checks
  degrees1 <- as.numeric(degrees1)
  degrees2 <- as.numeric(degrees2)
  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_is_bigraphical,
    degrees1,
    degrees2,
    allowed_edge_types
  )

  res
}

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))
  # Function call
  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")
) {
  # Argument checks
  ensure_igraph(graph)
  root <- as_igraph_vs(graph, root)
  if (length(root) != 1) {
    cli::cli_abort(
      "{.arg root} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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
) {
  # Argument checks
  ensure_igraph(graph)
  types <- handle_vertex_type_arg(types, graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_bipartite_projection_size,
    graph,
    types
  )

  res
}

bipartite_projection_impl <- function(
  graph,
  types,
  probe1 = -1
) {
  # Argument checks
  ensure_igraph(graph)
  types <- handle_vertex_type_arg(types, graph)
  probe1 <- as.numeric(probe1)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_bipartite_projection,
    graph,
    types,
    probe1
  )

  res
}

create_bipartite_impl <- function(
  types,
  edges,
  directed = FALSE
) {
  # Argument checks
  types <- handle_vertex_type_arg(types, res$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(
  incidence,
  directed = FALSE,
  mode = c("all", "out", "in", "total"),
  multiple = FALSE
) {
  # Argument checks
  incidence[] <- as.numeric(incidence)
  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))
  # Function call
  res <- .Call(
    R_igraph_biadjacency,
    incidence,
    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
}

get_biadjacency_impl <- function(
  graph,
  types
) {
  # 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
}

is_bipartite_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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")
) {
  # 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
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_bipartite_game_gnp,
    n1,
    n2,
    p,
    directed,
    mode
  )

  res
}

bipartite_game_gnm_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_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_bipartite_game_gnm,
    n1,
    n2,
    m,
    directed,
    mode
  )

  res
}

bipartite_game_impl <- function(
  type,
  n1,
  n2,
  p = 0.0,
  m = 0,
  directed = FALSE,
  mode = c("all", "out", "in", "total")
) {
  # Argument checks
  type <- switch_igraph_arg(type, "gnp" = 0L, "gnm" = 1L)
  n1 <- as.numeric(n1)
  n2 <- as.numeric(n2)
  p <- as.numeric(p)
  m <- as.numeric(m)
  directed <- as.logical(directed)
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_bipartite_game,
    type,
    n1,
    n2,
    p,
    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
) {
  # Argument checks
  ensure_igraph(graph)
  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
  }
  if (!is.null(weights) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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
) {
  # Argument checks
  ensure_igraph(graph)
  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
  }
  if (!is.null(weights) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_get_laplacian_sparse,
    graph,
    mode,
    normalization,
    weights
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_connected_components,
    graph,
    mode
  )
  if (!details) {
    res <- res$membership
  }
  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_is_connected,
    graph,
    mode
  )

  res
}

decompose_impl <- function(
  graph,
  mode = c("weak", "strong"),
  maxcompno = -1,
  minelements = 1
) {
  # Argument checks
  ensure_igraph(graph)
  mode <- switch_igraph_arg(mode, "weak" = 1L, "strong" = 2L)
  maxcompno <- as.numeric(maxcompno)
  minelements <- as.numeric(minelements)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_decompose,
    graph,
    mode,
    maxcompno,
    minelements
  )

  res
}

articulation_points_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_articulation_points,
    graph
  )
  if (igraph_opt("return.vs.es")) {
    res <- create_vs(graph, res)
  }
  res
}

biconnected_components_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(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)
  }
  res
}

bridges_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_bridges,
    graph
  )
  if (igraph_opt("return.vs.es")) {
    res <- create_es(graph, res)
  }
  res
}

is_biconnected_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_is_biconnected,
    graph
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_count_reachable,
    graph,
    mode
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_bond_percolation,
    graph,
    edge_order - 1
  )

  res
}

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)
    vertex_order <- vertex_order - 1
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_site_percolation,
    graph,
    vertex_order
  )

  res
}

edgelist_percolation_impl <- function(
  edges
) {
  # Argument checks


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_edgelist_percolation,
    edges - 1
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_is_clique,
    graph,
    candidate - 1,
    directed
  )

  res
}

cliques_impl <- function(
  graph,
  min = 0,
  max = 0
) {
  # Argument checks
  ensure_igraph(graph)
  min <- as.numeric(min)
  max <- as.numeric(max)

  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
}

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))
  # Function call
  res <- .Call(
    R_igraph_clique_size_hist,
    graph,
    min_size,
    max_size
  )

  res
}

largest_cliques_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(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
}

maximal_cliques_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))
  # Function call
  res <- .Call(
    R_igraph_maximal_cliques,
    graph,
    min_size,
    max_size
  )
  if (igraph_opt("return.vs.es")) {
    res <- lapply(res, unsafe_create_vs, graph = graph, verts = V(graph))
  }
  res
}

maximal_cliques_subset_impl <- function(
  graph,
  subset,
  outfile = NULL,
  min_size = 0,
  max_size = 0,
  details = FALSE
) {
  # Argument checks
  ensure_igraph(graph)
  subset <- as_igraph_vs(graph, subset)
  subset <- subset - 1
  if (!is.null(outfile)) {
    check_string(outfile)

  }
  min_size <- as.numeric(min_size)
  max_size <- as.numeric(max_size)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_maximal_cliques_subset,
    graph,
    subset,
    outfile,
    min_size,
    max_size
  )
  if (igraph_opt("return.vs.es")) {
    res$res <- lapply(res$res, unsafe_create_vs, graph = graph, verts = V(graph))
  }
  if (!details) {
    res <- res$res
  }
  res
}

maximal_cliques_count_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))
  # Function call
  res <- .Call(
    R_igraph_maximal_cliques_count,
    graph,
    min_size,
    max_size
  )

  res
}

maximal_cliques_file_impl <- function(
  graph,
  res,
  min_size = 0,
  max_size = 0
) {
  # Argument checks
  ensure_igraph(graph)
  check_string(res)

  min_size <- as.numeric(min_size)
  max_size <- as.numeric(max_size)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_maximal_cliques_file,
    graph,
    res,
    min_size,
    max_size
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_maximal_cliques_hist,
    graph,
    min_size,
    max_size
  )

  res
}

clique_number_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_clique_number,
    graph
  )

  res
}

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) && !all(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)

  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) && !all(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) && !all(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_weighted_clique_number,
    graph,
    vertex_weights
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_is_independent_vertex_set,
    graph,
    candidate - 1
  )

  res
}

independent_vertex_sets_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))
  # Function call
  res <- .Call(
    R_igraph_independent_vertex_sets,
    graph,
    min_size,
    max_size
  )
  if (igraph_opt("return.vs.es")) {
    res <- lapply(res, unsafe_create_vs, graph = graph, verts = V(graph))
  }
  res
}

largest_independent_vertex_sets_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_largest_independent_vertex_sets,
    graph
  )
  if (igraph_opt("return.vs.es")) {
    res <- lapply(res, unsafe_create_vs, graph = graph, verts = V(graph))
  }
  res
}

maximal_independent_vertex_sets_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_maximal_independent_vertex_sets,
    graph
  )
  if (igraph_opt("return.vs.es")) {
    res <- lapply(res, unsafe_create_vs, graph = graph, verts = V(graph))
  }
  res
}

independence_number_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_independence_number,
    graph
  )

  res
}

layout_random_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_layout_random,
    graph
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_layout_circle,
    graph,
    order - 1
  )

  res
}

layout_star_impl <- function(
  graph,
  center = V(graph)[1],
  order = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  center <- as_igraph_vs(graph, center)
  if (length(center) != 1) {
    cli::cli_abort(
      "{.arg center} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  if (!is.null(order)) {
    order <- as.numeric(order) - 1
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_layout_star,
    graph,
    center - 1,
    order
  )

  res
}

layout_grid_impl <- function(
  graph,
  width = 0
) {
  # Argument checks
  ensure_igraph(graph)
  width <- as.numeric(width)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_layout_grid,
    graph,
    width
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_layout_grid_3d,
    graph,
    width,
    height
  )

  res
}

layout_fruchterman_reingold_impl <- function(
  graph,
  coords = NULL,
  use_seed = FALSE,
  niter = 500,
  start_temp = sqrt(vcount(graph)),
  grid = c("auto", "grid", "nogrid"),
  weights = NULL,
  minx = NULL,
  maxx = NULL,
  miny = NULL,
  maxy = NULL,
  coolexp = NULL,
  maxdelta = NULL,
  area = NULL,
  repulserad = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  if (!is.null(coords)) {
    coords[] <- as.numeric(coords)
  }
  use_seed <- as.logical(use_seed)
  niter <- as.numeric(niter)
  start_temp <- as.numeric(start_temp)
  grid <- switch_igraph_arg(grid, "grid" = 0L, "nogrid" = 1L, "auto" = 2L)
  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
  }
  if (!is.null(minx)) {
    minx <- as.numeric(minx)
  }
  if (!is.null(maxx)) {
    maxx <- as.numeric(maxx)
  }
  if (!is.null(miny)) {
    miny <- as.numeric(miny)
  }
  if (!is.null(maxy)) {
    maxy <- as.numeric(maxy)
  }
  if (!missing(coolexp)) { warning("Argument `coolexp' is deprecated and has no effect") }
  if (!missing(maxdelta)) { warning("Argument `maxdelta' is deprecated and has no effect") }
  if (!missing(area)) { warning("Argument `area' is deprecated and has no effect") }
  if (!missing(repulserad)) { warning("Argument `repulserad' is deprecated and has no effect") }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_layout_fruchterman_reingold,
    graph,
    coords,
    use_seed,
    niter,
    start_temp,
    grid,
    weights,
    minx,
    maxx,
    miny,
    maxy
  )

  res
}

layout_kamada_kawai_impl <- function(
  graph,
  coords,
  use_seed = FALSE,
  maxiter = 500,
  epsilon = 0.0,
  kkconst = vcount(graph),
  weights = NULL,
  minx = NULL,
  maxx = NULL,
  miny = NULL,
  maxy = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  coords[] <- as.numeric(coords)
  use_seed <- as.logical(use_seed)
  maxiter <- as.numeric(maxiter)
  epsilon <- as.numeric(epsilon)
  kkconst <- as.numeric(kkconst)
  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
  }
  if (!is.null(minx)) {
    minx <- as.numeric(minx)
  }
  if (!is.null(maxx)) {
    maxx <- as.numeric(maxx)
  }
  if (!is.null(miny)) {
    miny <- as.numeric(miny)
  }
  if (!is.null(maxy)) {
    maxy <- as.numeric(maxy)
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_layout_kamada_kawai,
    graph,
    coords,
    use_seed,
    maxiter,
    epsilon,
    kkconst,
    weights,
    minx,
    maxx,
    miny,
    maxy
  )

  res
}

layout_lgl_impl <- function(
  graph,
  maxiter = 150,
  maxdelta = vcount(graph),
  area = vcount(graph)^2,
  coolexp = 1.5,
  repulserad = vcount(graph)^3,
  cellsize = vcount(graph),
  root = -1
) {
  # Argument checks
  ensure_igraph(graph)
  maxiter <- as.numeric(maxiter)
  maxdelta <- as.numeric(maxdelta)
  area <- as.numeric(area)
  coolexp <- as.numeric(coolexp)
  repulserad <- as.numeric(repulserad)
  cellsize <- as.numeric(cellsize)
  root <- as.numeric(root)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_layout_lgl,
    graph,
    maxiter,
    maxdelta,
    area,
    coolexp,
    repulserad,
    cellsize,
    root
  )

  res
}

layout_reingold_tilford_impl <- function(
  graph,
  mode = c("out", "in", "all", "total"),
  roots = NULL,
  rootlevel = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )
  if (!is.null(roots)) {
    roots <- as_igraph_vs(graph, roots)
    roots <- roots - 1
  }
  if (!is.null(rootlevel)) {
    rootlevel <- as.numeric(rootlevel)
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_layout_reingold_tilford,
    graph,
    mode,
    roots,
    rootlevel
  )

  res
}

layout_reingold_tilford_circular_impl <- function(
  graph,
  mode = c("out", "in", "all", "total"),
  roots = NULL,
  rootlevel = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )
  if (!is.null(roots)) {
    roots <- as_igraph_vs(graph, roots)
    roots <- roots - 1
  }
  if (!is.null(rootlevel)) {
    rootlevel <- as.numeric(rootlevel)
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_layout_reingold_tilford_circular,
    graph,
    mode,
    roots,
    rootlevel
  )

  res
}

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))
  # Function call
  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
) {
  # 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_fruchterman_reingold_3d_impl <- function(
  graph,
  coords = NULL,
  use_seed = FALSE,
  niter = 500,
  start_temp = sqrt(vcount(graph)),
  weights = NULL,
  minx = NULL,
  maxx = NULL,
  miny = NULL,
  maxy = NULL,
  minz = NULL,
  maxz = NULL,
  coolexp = NULL,
  maxdelta = NULL,
  area = NULL,
  repulserad = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  if (!is.null(coords)) {
    coords[] <- as.numeric(coords)
  }
  use_seed <- as.logical(use_seed)
  niter <- as.numeric(niter)
  start_temp <- as.numeric(start_temp)
  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
  }
  if (!is.null(minx)) {
    minx <- as.numeric(minx)
  }
  if (!is.null(maxx)) {
    maxx <- as.numeric(maxx)
  }
  if (!is.null(miny)) {
    miny <- as.numeric(miny)
  }
  if (!is.null(maxy)) {
    maxy <- as.numeric(maxy)
  }
  if (!is.null(minz)) {
    minz <- as.numeric(minz)
  }
  if (!is.null(maxz)) {
    maxz <- as.numeric(maxz)
  }
  if (!missing(coolexp)) { warning("Argument `coolexp' is deprecated and has no effect") }
  if (!missing(maxdelta)) { warning("Argument `maxdelta' is deprecated and has no effect") }
  if (!missing(area)) { warning("Argument `area' is deprecated and has no effect") }
  if (!missing(repulserad)) { warning("Argument `repulserad' is deprecated and has no effect") }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_layout_fruchterman_reingold_3d,
    graph,
    coords,
    use_seed,
    niter,
    start_temp,
    weights,
    minx,
    maxx,
    miny,
    maxy,
    minz,
    maxz
  )

  res
}

layout_kamada_kawai_3d_impl <- function(
  graph,
  coords,
  use_seed = FALSE,
  maxiter = 500,
  epsilon = 0.0,
  kkconst = vcount(graph),
  weights = NULL,
  minx = NULL,
  maxx = NULL,
  miny = NULL,
  maxy = NULL,
  minz = NULL,
  maxz = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  coords[] <- as.numeric(coords)
  use_seed <- as.logical(use_seed)
  maxiter <- as.numeric(maxiter)
  epsilon <- as.numeric(epsilon)
  kkconst <- as.numeric(kkconst)
  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
  }
  if (!is.null(minx)) {
    minx <- as.numeric(minx)
  }
  if (!is.null(maxx)) {
    maxx <- as.numeric(maxx)
  }
  if (!is.null(miny)) {
    miny <- as.numeric(miny)
  }
  if (!is.null(maxy)) {
    maxy <- as.numeric(maxy)
  }
  if (!is.null(minz)) {
    minz <- as.numeric(minz)
  }
  if (!is.null(maxz)) {
    maxz <- as.numeric(maxz)
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_layout_kamada_kawai_3d,
    graph,
    coords,
    use_seed,
    maxiter,
    epsilon,
    kkconst,
    weights,
    minx,
    maxx,
    miny,
    maxy,
    minz,
    maxz
  )

  res
}

layout_graphopt_impl <- function(
  graph,
  res,
  niter = 500,
  node_charge = 0.001,
  node_mass = 30,
  spring_length = 0,
  spring_constant = 1,
  max_sa_movement = 5,
  use_seed = FALSE
) {
  # Argument checks
  ensure_igraph(graph)
  res[] <- as.numeric(res)
  niter <- as.numeric(niter)
  node_charge <- as.numeric(node_charge)
  node_mass <- as.numeric(node_mass)
  spring_length <- as.numeric(spring_length)
  spring_constant <- as.numeric(spring_constant)
  max_sa_movement <- as.numeric(max_sa_movement)
  use_seed <- as.logical(use_seed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_layout_graphopt,
    graph,
    res,
    niter,
    node_charge,
    node_mass,
    spring_length,
    spring_constant,
    max_sa_movement,
    use_seed
  )

  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)
  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
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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
) {
  # Argument checks
  ensure_igraph(graph)
  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(graph)) {
    weights <- E(graph)$weight
  }
  if (!is.null(weights) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_layout_drl_3d,
    graph,
    res,
    use_seed,
    options,
    weights
  )

  res
}

layout_merge_dla_impl <- function(
  graphs,
  coords
) {
  # Argument checks
  if (!is.list(graphs)) {
    cli::cli_abort("{.arg graphs} must be a list of igraph objects")
  }
  graphs <- lapply(graphs, function(g) {
    if (!inherits(g, "igraph")) {
      cli::cli_abort("{.arg graphs} must be a list of igraph objects")
    }
    g
  })
  if (!is.list(coords)) {
    cli::cli_abort("{.arg coords} must be a list of matrices")
  }
  coords <- lapply(coords, function(m) {
    if (!is.matrix(m)) {
      cli::cli_abort("{.arg coords} must be a list of matrices")
    }
    m[] <- as.numeric(m)
    m
  })

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_layout_merge_dla,
    graphs,
    coords
  )

  res
}

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
  }
  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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_layout_sugiyama,
    graph,
    layers,
    hgap,
    vgap,
    maxiter,
    weights
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_layout_mds,
    graph,
    dist,
    dim
  )

  res
}

layout_bipartite_impl <- function(
  graph,
  types,
  hgap = 1,
  vgap = 1,
  maxiter = 100
) {
  # Argument checks
  ensure_igraph(graph)
  types <- handle_vertex_type_arg(types, graph)
  hgap <- as.numeric(hgap)
  vgap <- as.numeric(vgap)
  maxiter <- as.numeric(maxiter)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_layout_bipartite,
    graph,
    types,
    hgap,
    vgap,
    maxiter
  )

  res
}

layout_gem_impl <- function(
  graph,
  res = matrix(),
  use_seed = FALSE,
  maxiter = 40,
  temp_max = vcount(graph),
  temp_min = 1,
  temp_init = sqrt(vcount(graph))
) {
  # Argument checks
  ensure_igraph(graph)
  res[] <- as.numeric(res)
  use_seed <- as.logical(use_seed)
  maxiter <- as.numeric(maxiter)
  temp_max <- as.numeric(temp_max)
  temp_min <- as.numeric(temp_min)
  temp_init <- as.numeric(temp_init)

  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
}

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)
  use_seed <- as.logical(use_seed)
  maxiter <- as.numeric(maxiter)
  fineiter <- as.numeric(fineiter)
  cool_fact <- as.numeric(cool_fact)
  weight_node_dist <- as.numeric(weight_node_dist)
  weight_border <- as.numeric(weight_border)
  weight_edge_lengths <- as.numeric(weight_edge_lengths)
  weight_edge_crossings <- as.numeric(weight_edge_crossings)
  weight_node_edge_dist <- as.numeric(weight_node_edge_dist)

  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
}

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)
  use_seed <- as.logical(use_seed)
  if (!is.null(distances)) {
    distances <- as.numeric(distances)
  }
  min_dist <- as.numeric(min_dist)
  epochs <- as.numeric(epochs)
  distances_are_weights <- as.logical(distances_are_weights)

  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
}

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)
  use_seed <- as.logical(use_seed)
  if (!is.null(distances)) {
    distances <- as.numeric(distances)
  }
  min_dist <- as.numeric(min_dist)
  epochs <- as.numeric(epochs)
  distances_are_weights <- as.logical(distances_are_weights)

  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
}

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))
  # Function call
  res <- .Call(
    R_igraph_layout_umap_compute_weights,
    graph,
    distances,
    weights
  )

  res
}

layout_align_impl <- function(
  graph,
  layout
) {
  # Argument checks
  ensure_igraph(graph)
  layout[] <- as.numeric(layout)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_layout_align,
    graph,
    layout
  )

  res
}

cocitation_impl <- function(
  graph,
  vids = V(graph)
) {
  # Argument checks
  ensure_igraph(graph)
  vids <- as_igraph_vs(graph, vids)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_cocitation,
    graph,
    vids - 1
  )

  res
}

bibcoupling_impl <- function(
  graph,
  vids = V(graph)
) {
  # Argument checks
  ensure_igraph(graph)
  vids <- as_igraph_vs(graph, vids)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_bibcoupling,
    graph,
    vids - 1
  )

  res
}

similarity_dice_impl <- function(
  graph,
  vids = V(graph),
  mode = c("all", "out", "in", "total"),
  loops = FALSE
) {
  # 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 <- as.logical(loops)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_similarity_dice,
    graph,
    vids - 1,
    mode,
    loops
  )

  res
}

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))
  # Function call
  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
) {
  # Argument checks
  ensure_igraph(graph)
  pairs <- as_igraph_vs(graph, pairs)
  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_pairs,
    graph,
    pairs - 1,
    mode,
    loops
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_similarity_inverse_log_weighted,
    graph,
    vids - 1,
    mode
  )

  res
}

similarity_jaccard_impl <- function(
  graph,
  vids = V(graph),
  mode = c("all", "out", "in", "total"),
  loops = FALSE
) {
  # 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 <- as.logical(loops)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_similarity_jaccard,
    graph,
    vids - 1,
    mode,
    loops
  )

  res
}

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))
  # Function call
  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
) {
  # Argument checks
  ensure_igraph(graph)
  pairs <- as_igraph_vs(graph, pairs)
  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_pairs,
    graph,
    pairs - 1,
    mode,
    loops
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_compare_communities,
    comm1,
    comm2,
    method
  )

  res
}

community_spinglass_impl <- function(
  graph,
  weights = NULL,
  spins = 25,
  parupdate = FALSE,
  starttemp = 1,
  stoptemp = 0.01,
  coolfact = 0.99,
  update_rule = c("config", "simple"),
  gamma = 1.0,
  implementation = c("orig", "neg"),
  lambda = 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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  spins <- as.numeric(spins)
  parupdate <- as.logical(parupdate)
  starttemp <- as.numeric(starttemp)
  stoptemp <- as.numeric(stoptemp)
  coolfact <- as.numeric(coolfact)
  update_rule <- switch_igraph_arg(update_rule, "simple" = 0L, "config" = 1L)
  gamma <- as.numeric(gamma)
  implementation <- switch_igraph_arg(implementation, "orig" = 0L, "neg" = 1L)
  lambda <- as.numeric(lambda)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_community_spinglass,
    graph,
    weights,
    spins,
    parupdate,
    starttemp,
    stoptemp,
    coolfact,
    update_rule,
    gamma,
    implementation,
    lambda
  )

  res
}

community_spinglass_single_impl <- function(
  graph,
  weights = NULL,
  vertex,
  spins = 25,
  update_rule = c("config", "simple"),
  gamma = 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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  vertex <- as.numeric(vertex)
  spins <- as.numeric(spins)
  update_rule <- switch_igraph_arg(update_rule, "simple" = 0L, "config" = 1L)
  gamma <- as.numeric(gamma)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_community_spinglass_single,
    graph,
    weights,
    vertex,
    spins,
    update_rule,
    gamma
  )

  res
}

community_walktrap_impl <- function(
  graph,
  weights = NULL,
  steps = 4
) {
  # 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
  }
  steps <- as.numeric(steps)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_community_walktrap,
    graph,
    weights,
    steps
  )

  res
}

community_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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_community_edge_betweenness,
    graph,
    directed,
    weights
  )

  res
}

community_eb_get_merges_impl <- function(
  graph,
  directed,
  edges,
  weights = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  directed <- as.logical(directed)
  edges <- as_igraph_es(graph, edges)
  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
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_community_eb_get_merges,
    graph,
    directed,
    edges - 1,
    weights
  )

  res
}

community_fastgreedy_impl <- function(
  graph,
  weights = 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
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_community_fastgreedy,
    graph,
    weights
  )

  res
}

community_to_membership_impl <- function(
  merges,
  nodes,
  steps
) {
  # Argument checks
  nodes <- as.numeric(nodes)
  steps <- as.numeric(steps)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_community_to_membership,
    merges,
    nodes,
    steps
  )

  res
}

le_community_to_membership_impl <- function(
  merges,
  steps,
  membership
) {
  # Argument checks
  steps <- as.numeric(steps)
  membership <- as.numeric(membership)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_le_community_to_membership,
    merges,
    steps,
    membership
  )

  res
}

modularity_impl <- function(
  graph,
  membership,
  weights = NULL,
  resolution = 1.0,
  directed = TRUE
) {
  # 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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  resolution <- as.numeric(resolution)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_modularity,
    graph,
    membership,
    weights,
    resolution,
    directed
  )

  res
}

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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  resolution <- as.numeric(resolution)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_modularity_matrix,
    graph,
    weights,
    resolution,
    directed
  )

  res
}

reindex_membership_impl <- function(
  membership
) {
  # Argument checks
  membership <- as.numeric(membership)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_reindex_membership,
    membership
  )

  res
}

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))
  # Function call
  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
) {
  # Argument checks
  ensure_igraph(graph)
  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
  }
  if (!is.null(weights) && !all(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)
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_community_label_propagation,
    graph,
    mode,
    weights,
    initial,
    fixed
  )

  res
}

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) && !all(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_multilevel,
    graph,
    weights,
    resolution
  )

  res
}

community_optimal_modularity_impl <- function(
  graph,
  weights = 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
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_community_optimal_modularity,
    graph,
    weights
  )

  res
}

community_leiden_impl <- function(
  graph,
  weights = NULL,
  vertex_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) && !all(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) && !all(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)
  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,
    graph,
    weights,
    vertex_weights,
    resolution,
    beta,
    start,
    n_iterations,
    membership
  )

  res
}

split_join_distance_impl <- function(
  comm1,
  comm2
) {
  # Argument checks
  comm1 <- as.numeric(comm1)
  comm2 <- as.numeric(comm2)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_split_join_distance,
    comm1,
    comm2
  )

  res
}

community_infomap_impl <- function(
  graph,
  e_weights = NULL,
  v_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) && !all(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) && !all(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
}

community_voronoi_impl <- function(
  graph,
  lengths = NULL,
  weights = NULL,
  mode = c("out", "in", "all", "total"),
  radius = -1
) {
  # Argument checks
  ensure_igraph(graph)
  if (!is.null(lengths) && !all(is.na(lengths))) {
    lengths <- as.numeric(lengths)
  } else {
    lengths <- NULL
  }
  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
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )
  radius <- as.numeric(radius)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_community_voronoi,
    graph,
    lengths,
    weights,
    mode,
    radius
  )
  if (igraph_opt("return.vs.es")) {
    res$generators <- create_vs(graph, res$generators)
  }
  res
}

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) && !all(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
}

graphlets_candidate_basis_impl <- function(
  graph,
  weights = 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
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_graphlets_candidate_basis,
    graph,
    weights
  )
  if (igraph_opt("return.vs.es")) {
    res$cliques <- lapply(res$cliques, unsafe_create_vs, graph = graph, verts = V(graph))
  }
  res
}

graphlets_project_impl <- function(
  graph,
  weights = NULL,
  cliques,
  Muc,
  startMu = FALSE,
  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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  if (!is.null(cliques) && !is.list(cliques)) {
    cli::cli_abort(
      "{.arg cliques} must be a list or NULL",
      call = rlang::caller_env()
    )
  }
  Muc <- as.numeric(Muc)
  startMu <- as.logical(startMu)
  niter <- as.numeric(niter)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_graphlets_project,
    graph,
    weights,
    if (!is.null(cliques)) lapply(cliques, function(.x) .x - 1),
    Muc,
    startMu,
    niter
  )

  res
}

hrg_fit_impl <- function(
  graph,
  hrg = NULL,
  start = FALSE,
  steps = 0
) {
  # Argument checks
  ensure_igraph(graph)
  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)
  start <- as.logical(start)
  steps <- as.numeric(steps)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_hrg_fit,
    graph,
    hrg,
    start,
    steps
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_hrg_sample,
    hrg
  )

  res
}

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())
  }
  hrg <- lapply(hrg[c("left","right","prob","edges","vertices")], as.numeric)
  num_samples <- as.numeric(num_samples)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_hrg_sample_many,
    hrg,
    num_samples
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_hrg_game,
    hrg
  )

  if (igraph_opt("add.params")) {
    res$name <- 'Hierarchical random graph model'
  }

  res
}

hrg_consensus_impl <- function(
  graph,
  hrg = NULL,
  start = FALSE,
  num_samples = 10000
) {
  # Argument checks
  ensure_igraph(graph)
  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)
  start <- as.logical(start)
  num_samples <- as.numeric(num_samples)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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
) {
  # Argument checks
  ensure_igraph(graph)
  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)
  start <- as.logical(start)
  num_samples <- as.numeric(num_samples)
  num_bins <- as.numeric(num_bins)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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
) {
  # Argument checks
  ensure_igraph(graph)
  prob <- as.numeric(prob)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_hrg_create,
    graph,
    prob
  )

  class(res) <- "igraphHRG"
  res
}

hrg_resize_impl <- function(
  hrg,
  newsize
) {
  # 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)
  newsize <- as.numeric(newsize)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_hrg_resize,
    hrg,
    newsize
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_hrg_size,
    hrg
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_from_hrg_dendrogram,
    hrg
  )

  res
}

get_adjacency_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)
  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 <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_get_adjacency,
    graph,
    type,
    weights,
    loops
  )

  res
}

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)
  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 <- switch_igraph_arg(loops, "none" = 0L, "twice" = 1L, "once" = 2L)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_get_adjacency_sparse,
    graph,
    type,
    weights,
    loops
  )

  res
}

get_edgelist_impl <- function(
  graph,
  bycol = FALSE
) {
  # Argument checks
  ensure_igraph(graph)
  bycol <- as.logical(bycol)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_get_edgelist,
    graph,
    bycol
  )

  res
}

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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_get_stochastic,
    graph,
    column_wise,
    weights
  )

  res
}

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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_get_stochastic_sparse,
    graph,
    column_wise,
    weights
  )

  res
}

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))
  # Function call
  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")
) {
  # 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))
  # Function call
  res <- .Call(
    R_igraph_to_undirected,
    graph,
    mode,
    edge_attr_comb
  )

  res
}

read_graph_edgelist_impl <- function(
  instream,
  n = 0,
  directed = TRUE
) {
  # Argument checks
  check_string(instream)

  n <- as.numeric(n)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_read_graph_edgelist,
    instream,
    n,
    directed
  )

  res
}

read_graph_ncol_impl <- function(
  instream,
  predefnames = NULL,
  names = TRUE,
  weights = TRUE,
  directed = TRUE
) {
  # Argument checks
  check_string(instream)

  names <- as.logical(names)
  weights <- switch_igraph_arg(weights, "no" = 0L, "yes" = 1L, "auto" = 2L)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_read_graph_ncol,
    instream,
    predefnames,
    names,
    weights,
    directed
  )

  res
}

read_graph_lgl_impl <- function(
  instream,
  names = TRUE,
  weights = TRUE,
  directed = TRUE
) {
  # Argument checks
  check_string(instream)

  names <- as.logical(names)
  weights <- switch_igraph_arg(weights, "no" = 0L, "yes" = 1L, "auto" = 2L)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_read_graph_lgl,
    instream,
    names,
    weights,
    directed
  )

  res
}

read_graph_pajek_impl <- function(
  instream
) {
  # Argument checks
  check_string(instream)


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_read_graph_pajek,
    instream
  )

  res
}

read_graph_graphml_impl <- function(
  instream,
  index = 0
) {
  # Argument checks
  check_string(instream)

  index <- as.numeric(index)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_read_graph_graphml,
    instream,
    index
  )

  res
}

read_graph_dimacs_flow_impl <- function(
  instream,
  directed = TRUE
) {
  # Argument checks
  check_string(instream)

  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_read_graph_dimacs_flow,
    instream,
    directed
  )

  res
}

read_graph_graphdb_impl <- function(
  instream,
  directed = FALSE
) {
  # Argument checks
  check_string(instream)

  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_read_graph_graphdb,
    instream,
    directed
  )

  res
}

read_graph_gml_impl <- function(
  instream
) {
  # Argument checks
  check_string(instream)


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_read_graph_gml,
    instream
  )

  res
}

read_graph_dl_impl <- function(
  instream,
  directed = TRUE
) {
  # Argument checks
  check_string(instream)

  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_read_graph_dl,
    instream,
    directed
  )

  res
}

write_graph_edgelist_impl <- function(
  graph,
  outstream
) {
  # Argument checks
  ensure_igraph(graph)
  check_string(outstream)


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_write_graph_edgelist,
    graph,
    outstream
  )

  res
}

write_graph_ncol_impl <- function(
  graph,
  outstream,
  names = "name",
  weights = "weight"
) {
  # Argument checks
  ensure_igraph(graph)
  check_string(outstream)


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_write_graph_ncol,
    graph,
    outstream,
    names,
    weights
  )

  res
}

write_graph_lgl_impl <- function(
  graph,
  outstream,
  names = "name",
  weights = "weight",
  isolates = TRUE
) {
  # Argument checks
  ensure_igraph(graph)
  check_string(outstream)

  isolates <- as.logical(isolates)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_write_graph_lgl,
    graph,
    outstream,
    names,
    weights,
    isolates
  )

  res
}

write_graph_leda_impl <- function(
  graph,
  outstream,
  names = "name",
  weights = "weight"
) {
  # Argument checks
  ensure_igraph(graph)
  check_string(outstream)


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_write_graph_leda,
    graph,
    outstream,
    names,
    weights
  )

  res
}

write_graph_graphml_impl <- function(
  graph,
  outstream,
  prefixattr = TRUE
) {
  # Argument checks
  ensure_igraph(graph)
  check_string(outstream)

  prefixattr <- as.logical(prefixattr)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_write_graph_graphml,
    graph,
    outstream,
    prefixattr
  )

  res
}

write_graph_pajek_impl <- function(
  graph,
  outstream
) {
  # Argument checks
  ensure_igraph(graph)
  check_string(outstream)


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_write_graph_pajek,
    graph,
    outstream
  )

  res
}

write_graph_dimacs_flow_impl <- function(
  graph,
  outstream,
  source = 0,
  target = 0,
  capacity
) {
  # Argument checks
  ensure_igraph(graph)
  check_string(outstream)

  source <- as_igraph_vs(graph, source)
  if (length(source) != 1) {
    cli::cli_abort(
      "{.arg source} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  target <- as_igraph_vs(graph, target)
  if (length(target) != 1) {
    cli::cli_abort(
      "{.arg target} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  capacity <- as.numeric(capacity)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_write_graph_dimacs_flow,
    graph,
    outstream,
    source - 1,
    target - 1,
    capacity
  )

  res
}

write_graph_gml_impl <- function(
  graph,
  outstream,
  options = c("default", "encode_only_quot"),
  id,
  creator = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  check_string(outstream)

  options <- switch_igraph_arg(options, "default" = 0L, "encode_only_quot" = 1L)
  id <- as.numeric(id)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_write_graph_gml,
    graph,
    outstream,
    options,
    id,
    creator
  )

  res
}

write_graph_dot_impl <- function(
  graph,
  outstream
) {
  # Argument checks
  ensure_igraph(graph)
  check_string(outstream)


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_write_graph_dot,
    graph,
    outstream
  )

  res
}

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))
  # Function call
  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
) {
  # Argument checks
  ensure_igraph(graph)
  size <- as.numeric(size)
  if (!is.null(cut_prob)) {
    cut_prob <- as.numeric(cut_prob)
  }
  sample_size <- as.numeric(sample_size)
  if (!is.null(sample)) {
    sample <- as.numeric(sample)
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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
) {
  # 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))
  # Function call
  res <- .Call(
    R_igraph_motifs_randesu_no,
    graph,
    size,
    cut_prob
  )

  res
}

dyad_census_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_dyad_census,
    graph
  )

  res
}

triad_census_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_triad_census,
    graph
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_count_adjacent_triangles,
    graph,
    vids - 1
  )

  res
}

count_triangles_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_count_triangles,
    graph
  )

  res
}

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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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")
) {
  # 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) && !all(is.na(weights_them))) {
    weights_them <- as.numeric(weights_them)
  } else {
    weights_them <- NULL
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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")
) {
  # 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
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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")
) {
  # 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) && !all(is.na(weights_them))) {
    weights_them <- as.numeric(weights_them)
  } else {
    weights_them <- NULL
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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")
) {
  # 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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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")
) {
  # Argument checks
  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) && !all(is.na(weights_them))) {
    weights_them <- as.numeric(weights_them)
  } else {
    weights_them <- NULL
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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
) {
  # 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
  }
  if (!is.null(neighborhoods) && !is.list(neighborhoods)) {
    cli::cli_abort(
      "{.arg neighborhoods} must be a list or NULL",
      call = rlang::caller_env()
    )
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_local_scan_neighborhood_ecount,
    graph,
    weights,
    if (!is.null(neighborhoods)) lapply(neighborhoods, function(.x) .x - 1)
  )

  res
}

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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  if (!is.null(subsets) && !is.list(subsets)) {
    cli::cli_abort(
      "{.arg subsets} must be a list or NULL",
      call = rlang::caller_env()
    )
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_local_scan_subset_ecount,
    graph,
    weights,
    if (!is.null(subsets)) lapply(subsets, function(.x) .x - 1)
  )

  res
}

list_triangles_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_list_triangles,
    graph
  )
  if (igraph_opt("return.vs.es")) {
    res <- create_vs(graph, res)
  }
  res
}

disjoint_union_impl <- function(
  left,
  right
) {
  # Argument checks
  ensure_igraph(left)
  ensure_igraph(right)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_disjoint_union,
    left,
    right
  )

  res
}

disjoint_union_many_impl <- function(
  graphs
) {
  # Argument checks
  if (!is.list(graphs)) {
    cli::cli_abort("{.arg graphs} must be a list of igraph objects")
  }
  graphs <- lapply(graphs, function(g) {
    if (!inherits(g, "igraph")) {
      cli::cli_abort("{.arg graphs} must be a list of igraph objects")
    }
    g
  })

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_disjoint_union_many,
    graphs
  )

  res
}

join_impl <- function(
  left,
  right
) {
  # Argument checks
  ensure_igraph(left)
  ensure_igraph(right)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_join,
    left,
    right
  )

  res
}

union_impl <- function(
  left,
  right
) {
  # Argument checks
  ensure_igraph(left)
  ensure_igraph(right)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_union,
    left,
    right
  )

  res
}

union_many_impl <- function(
  graphs
) {
  # Argument checks
  if (!is.list(graphs)) {
    cli::cli_abort("{.arg graphs} must be a list of igraph objects")
  }
  graphs <- lapply(graphs, function(g) {
    if (!inherits(g, "igraph")) {
      cli::cli_abort("{.arg graphs} must be a list of igraph objects")
    }
    g
  })

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_union_many,
    graphs
  )

  res
}

intersection_impl <- function(
  left,
  right
) {
  # Argument checks
  ensure_igraph(left)
  ensure_igraph(right)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_intersection,
    left,
    right
  )

  res
}

intersection_many_impl <- function(
  graphs
) {
  # Argument checks
  if (!is.list(graphs)) {
    cli::cli_abort("{.arg graphs} must be a list of igraph objects")
  }
  graphs <- lapply(graphs, function(g) {
    if (!inherits(g, "igraph")) {
      cli::cli_abort("{.arg graphs} must be a list of igraph objects")
    }
    g
  })

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_intersection_many,
    graphs
  )

  res
}

difference_impl <- function(
  orig,
  sub
) {
  # Argument checks
  ensure_igraph(orig)
  ensure_igraph(sub)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_difference,
    orig,
    sub
  )

  res
}

complementer_impl <- function(
  graph,
  loops = FALSE
) {
  # Argument checks
  ensure_igraph(graph)
  loops <- as.logical(loops)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_complementer,
    graph,
    loops
  )

  res
}

compose_impl <- function(
  g1,
  g2
) {
  # Argument checks
  ensure_igraph(g1)
  ensure_igraph(g2)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_compose,
    g1,
    g2
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_induced_subgraph_map,
    graph,
    vids - 1,
    impl
  )

  res
}

mycielskian_impl <- function(
  graph,
  k = 1
) {
  # Argument checks
  ensure_igraph(graph)
  k <- as.numeric(k)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_mycielskian,
    graph,
    k
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_product,
    g1,
    g2,
    type
  )

  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) != 1) {
    cli::cli_abort(
      "{.arg root} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }

  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)
  if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) {
    capacity <- E(graph)$capacity
  }
  if (!is.null(capacity) && !all(is.na(capacity))) {
    capacity <- as.numeric(capacity)
  } else {
    capacity <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_gomory_hu_tree,
    graph,
    capacity
  )

  res
}

maxflow_impl <- function(
  graph,
  source,
  target,
  capacity = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  source <- as_igraph_vs(graph, source)
  if (length(source) != 1) {
    cli::cli_abort(
      "{.arg source} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  target <- as_igraph_vs(graph, target)
  if (length(target) != 1) {
    cli::cli_abort(
      "{.arg target} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) {
    capacity <- E(graph)$capacity
  }
  if (!is.null(capacity) && !all(is.na(capacity))) {
    capacity <- as.numeric(capacity)
  } else {
    capacity <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_maxflow,
    graph,
    source - 1,
    target - 1,
    capacity
  )
  if (igraph_opt("return.vs.es")) {
    res$cut <- create_es(graph, res$cut)
  }
  if (igraph_opt("return.vs.es")) {
    res$partition1 <- create_vs(graph, res$partition1)
  }
  if (igraph_opt("return.vs.es")) {
    res$partition2 <- create_vs(graph, res$partition2)
  }
  res
}

maxflow_value_impl <- function(
  graph,
  source,
  target,
  capacity = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  source <- as_igraph_vs(graph, source)
  if (length(source) != 1) {
    cli::cli_abort(
      "{.arg source} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  target <- as_igraph_vs(graph, target)
  if (length(target) != 1) {
    cli::cli_abort(
      "{.arg target} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) {
    capacity <- E(graph)$capacity
  }
  if (!is.null(capacity) && !all(is.na(capacity))) {
    capacity <- as.numeric(capacity)
  } else {
    capacity <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_maxflow_value,
    graph,
    source - 1,
    target - 1,
    capacity
  )

  res
}

mincut_impl <- function(
  graph,
  capacity = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) {
    capacity <- E(graph)$capacity
  }
  if (!is.null(capacity) && !all(is.na(capacity))) {
    capacity <- as.numeric(capacity)
  } else {
    capacity <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_mincut,
    graph,
    capacity
  )
  if (igraph_opt("return.vs.es")) {
    res$partition1 <- create_vs(graph, res$partition1)
  }
  if (igraph_opt("return.vs.es")) {
    res$partition2 <- create_vs(graph, res$partition2)
  }
  if (igraph_opt("return.vs.es")) {
    res$cut <- create_es(graph, res$cut)
  }
  res
}

mincut_value_impl <- function(
  graph,
  capacity = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) {
    capacity <- E(graph)$capacity
  }
  if (!is.null(capacity) && !all(is.na(capacity))) {
    capacity <- as.numeric(capacity)
  } else {
    capacity <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_mincut_value,
    graph,
    capacity
  )

  res
}

residual_graph_impl <- function(
  graph,
  capacity,
  flow
) {
  # Argument checks
  ensure_igraph(graph)
  if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) {
    capacity <- E(graph)$capacity
  }
  if (!is.null(capacity) && !all(is.na(capacity))) {
    capacity <- as.numeric(capacity)
  } else {
    capacity <- NULL
  }
  flow <- as.numeric(flow)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_residual_graph,
    graph,
    capacity,
    flow
  )

  res
}

reverse_residual_graph_impl <- function(
  graph,
  capacity,
  flow
) {
  # Argument checks
  ensure_igraph(graph)
  if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) {
    capacity <- E(graph)$capacity
  }
  if (!is.null(capacity) && !all(is.na(capacity))) {
    capacity <- as.numeric(capacity)
  } else {
    capacity <- NULL
  }
  flow <- as.numeric(flow)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_reverse_residual_graph,
    graph,
    capacity,
    flow
  )

  res
}

st_mincut_impl <- function(
  graph,
  source,
  target,
  capacity = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  source <- as_igraph_vs(graph, source)
  if (length(source) != 1) {
    cli::cli_abort(
      "{.arg source} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  target <- as_igraph_vs(graph, target)
  if (length(target) != 1) {
    cli::cli_abort(
      "{.arg target} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) {
    capacity <- E(graph)$capacity
  }
  if (!is.null(capacity) && !all(is.na(capacity))) {
    capacity <- as.numeric(capacity)
  } else {
    capacity <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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)
  }
  if (igraph_opt("return.vs.es")) {
    res$partition1 <- create_vs(graph, res$partition1)
  }
  if (igraph_opt("return.vs.es")) {
    res$partition2 <- create_vs(graph, res$partition2)
  }
  res
}

st_mincut_value_impl <- function(
  graph,
  source,
  target,
  capacity = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  source <- as_igraph_vs(graph, source)
  if (length(source) != 1) {
    cli::cli_abort(
      "{.arg source} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  target <- as_igraph_vs(graph, target)
  if (length(target) != 1) {
    cli::cli_abort(
      "{.arg target} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) {
    capacity <- E(graph)$capacity
  }
  if (!is.null(capacity) && !all(is.na(capacity))) {
    capacity <- as.numeric(capacity)
  } else {
    capacity <- NULL
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_st_mincut_value,
    graph,
    source - 1,
    target - 1,
    capacity
  )

  res
}

st_vertex_connectivity_impl <- function(
  graph,
  source,
  target,
  neighbors = c("number_of_nodes", "error", "ignore", "negative")
) {
  # Argument checks
  ensure_igraph(graph)
  source <- as_igraph_vs(graph, source)
  if (length(source) != 1) {
    cli::cli_abort(
      "{.arg source} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  target <- as_igraph_vs(graph, target)
  if (length(target) != 1) {
    cli::cli_abort(
      "{.arg target} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  neighbors <- switch_igraph_arg(
    neighbors,
    "error" = 0L,
    "number_of_nodes" = 1L,
    "ignore" = 2L,
    "negative" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_st_vertex_connectivity,
    graph,
    source - 1,
    target - 1,
    neighbors
  )

  res
}

vertex_connectivity_impl <- function(
  graph,
  checks = TRUE
) {
  # Argument checks
  ensure_igraph(graph)
  checks <- as.logical(checks)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_vertex_connectivity,
    graph,
    checks
  )

  res
}

st_edge_connectivity_impl <- function(
  graph,
  source,
  target
) {
  # Argument checks
  ensure_igraph(graph)
  source <- as_igraph_vs(graph, source)
  if (length(source) != 1) {
    cli::cli_abort(
      "{.arg source} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  target <- as_igraph_vs(graph, target)
  if (length(target) != 1) {
    cli::cli_abort(
      "{.arg target} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_st_edge_connectivity,
    graph,
    source - 1,
    target - 1
  )

  res
}

edge_connectivity_impl <- function(
  graph,
  checks = TRUE
) {
  # Argument checks
  ensure_igraph(graph)
  checks <- as.logical(checks)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_edge_connectivity,
    graph,
    checks
  )

  res
}

edge_disjoint_paths_impl <- function(
  graph,
  source,
  target
) {
  # Argument checks
  ensure_igraph(graph)
  source <- as_igraph_vs(graph, source)
  if (length(source) != 1) {
    cli::cli_abort(
      "{.arg source} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  target <- as_igraph_vs(graph, target)
  if (length(target) != 1) {
    cli::cli_abort(
      "{.arg target} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_edge_disjoint_paths,
    graph,
    source - 1,
    target - 1
  )

  res
}

vertex_disjoint_paths_impl <- function(
  graph,
  source,
  target
) {
  # Argument checks
  ensure_igraph(graph)
  source <- as_igraph_vs(graph, source)
  if (length(source) != 1) {
    cli::cli_abort(
      "{.arg source} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  target <- as_igraph_vs(graph, target)
  if (length(target) != 1) {
    cli::cli_abort(
      "{.arg target} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_vertex_disjoint_paths,
    graph,
    source - 1,
    target - 1
  )

  res
}

adhesion_impl <- function(
  graph,
  checks = TRUE
) {
  # Argument checks
  ensure_igraph(graph)
  checks <- as.logical(checks)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_adhesion,
    graph,
    checks
  )

  res
}

cohesion_impl <- function(
  graph,
  checks = TRUE
) {
  # Argument checks
  ensure_igraph(graph)
  checks <- as.logical(checks)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_cohesion,
    graph,
    checks
  )

  res
}

dominator_tree_impl <- function(
  graph,
  root,
  mode = c("out", "in", "all", "total")
) {
  # Argument checks
  ensure_igraph(graph)
  root <- as_igraph_vs(graph, root)
  if (length(root) != 1) {
    cli::cli_abort(
      "{.arg root} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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
) {
  # Argument checks
  ensure_igraph(graph)
  source <- as_igraph_vs(graph, source)
  if (length(source) != 1) {
    cli::cli_abort(
      "{.arg source} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  target <- as_igraph_vs(graph, target)
  if (length(target) != 1) {
    cli::cli_abort(
      "{.arg target} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }

  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
}

all_st_mincuts_impl <- function(
  graph,
  source,
  target,
  capacity = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  source <- as_igraph_vs(graph, source)
  if (length(source) != 1) {
    cli::cli_abort(
      "{.arg source} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  target <- as_igraph_vs(graph, target)
  if (length(target) != 1) {
    cli::cli_abort(
      "{.arg target} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  if (is.null(capacity) && "capacity" %in% edge_attr_names(graph)) {
    capacity <- E(graph)$capacity
  }
  if (!is.null(capacity) && !all(is.na(capacity))) {
    capacity <- as.numeric(capacity)
  } else {
    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
}

even_tarjan_reduction_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_even_tarjan_reduction,
    graph
  )

  res
}

is_separator_impl <- function(
  graph,
  candidate
) {
  # Argument checks
  ensure_igraph(graph)
  candidate <- as_igraph_vs(graph, candidate)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_is_separator,
    graph,
    candidate - 1
  )

  res
}

is_minimal_separator_impl <- function(
  graph,
  candidate
) {
  # Argument checks
  ensure_igraph(graph)
  candidate <- as_igraph_vs(graph, candidate)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_is_minimal_separator,
    graph,
    candidate - 1
  )

  res
}

all_minimal_st_separators_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(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
}

minimum_size_separators_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(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
}

cohesive_blocks_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_cohesive_blocks,
    graph
  )
  if (igraph_opt("return.vs.es")) {
    res$blocks <- lapply(res$blocks, unsafe_create_vs, graph = graph, verts = V(graph))
  }
  class(res) <- "cohesiveBlocks"
  res
}

coreness_impl <- function(
  graph,
  mode = c("all", "out", "in", "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))
  # Function call
  res <- .Call(
    R_igraph_coreness,
    graph,
    mode
  )

  res
}

isoclass_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_isoclass,
    graph
  )

  res
}

isomorphic_impl <- function(
  graph1,
  graph2
) {
  # Argument checks
  ensure_igraph(graph1)
  ensure_igraph(graph2)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_isomorphic,
    graph1,
    graph2
  )

  res
}

isoclass_subgraph_impl <- function(
  graph,
  vids
) {
  # Argument checks
  ensure_igraph(graph)
  vids <- as.numeric(vids)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_isoclass_subgraph,
    graph,
    vids
  )

  res
}

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))
  # Function call
  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
) {
  # Argument checks
  ensure_igraph(graph1)
  ensure_igraph(graph2)
  if (is_missing(vertex_color1)) {
    if ("color" %in% vertex_attr_names(graph1)) {
      vertex_color1 <- V(graph1)$color
    } else {
      vertex_color1 <- NULL
    }
  }
  if (!is.null(vertex_color1)) {
    vertex_color1 <- as.numeric(vertex_color1) - 1
  }
  if (is_missing(vertex_color2)) {
    if ("color" %in% vertex_attr_names(graph2)) {
      vertex_color2 <- V(graph2)$color
    } else {
      vertex_color2 <- NULL
    }
  }
  if (!is.null(vertex_color2)) {
    vertex_color2 <- as.numeric(vertex_color2) - 1
  }
  if (is_missing(edge_color1)) {
    if ("color" %in% edge_attr_names(graph1)) {
      edge_color1 <- E(graph1)$color
    } else {
      edge_color1 <- NULL
    }
  }
  if (!is.null(edge_color1)) {
    edge_color1 <- as.numeric(edge_color1) - 1
  }
  if (is_missing(edge_color2)) {
    if ("color" %in% edge_attr_names(graph2)) {
      edge_color2 <- E(graph2)$color
    } else {
      edge_color2 <- NULL
    }
  }
  if (!is.null(edge_color2)) {
    edge_color2 <- as.numeric(edge_color2) - 1
  }

  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
}

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)
  if (is_missing(vertex_color1)) {
    if ("color" %in% vertex_attr_names(graph1)) {
      vertex_color1 <- V(graph1)$color
    } else {
      vertex_color1 <- NULL
    }
  }
  if (!is.null(vertex_color1)) {
    vertex_color1 <- as.numeric(vertex_color1) - 1
  }
  if (is_missing(vertex_color2)) {
    if ("color" %in% vertex_attr_names(graph2)) {
      vertex_color2 <- V(graph2)$color
    } else {
      vertex_color2 <- NULL
    }
  }
  if (!is.null(vertex_color2)) {
    vertex_color2 <- as.numeric(vertex_color2) - 1
  }
  if (is_missing(edge_color1)) {
    if ("color" %in% edge_attr_names(graph1)) {
      edge_color1 <- E(graph1)$color
    } else {
      edge_color1 <- NULL
    }
  }
  if (!is.null(edge_color1)) {
    edge_color1 <- as.numeric(edge_color1) - 1
  }
  if (is_missing(edge_color2)) {
    if ("color" %in% edge_attr_names(graph2)) {
      edge_color2 <- E(graph2)$color
    } else {
      edge_color2 <- NULL
    }
  }
  if (!is.null(edge_color2)) {
    edge_color2 <- as.numeric(edge_color2) - 1
  }

  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
}

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)
  if (is_missing(vertex_color1)) {
    if ("color" %in% vertex_attr_names(graph1)) {
      vertex_color1 <- V(graph1)$color
    } else {
      vertex_color1 <- NULL
    }
  }
  if (!is.null(vertex_color1)) {
    vertex_color1 <- as.numeric(vertex_color1) - 1
  }
  if (is_missing(vertex_color2)) {
    if ("color" %in% vertex_attr_names(graph2)) {
      vertex_color2 <- V(graph2)$color
    } else {
      vertex_color2 <- NULL
    }
  }
  if (!is.null(vertex_color2)) {
    vertex_color2 <- as.numeric(vertex_color2) - 1
  }
  if (is_missing(edge_color1)) {
    if ("color" %in% edge_attr_names(graph1)) {
      edge_color1 <- E(graph1)$color
    } else {
      edge_color1 <- NULL
    }
  }
  if (!is.null(edge_color1)) {
    edge_color1 <- as.numeric(edge_color1) - 1
  }
  if (is_missing(edge_color2)) {
    if ("color" %in% edge_attr_names(graph2)) {
      edge_color2 <- E(graph2)$color
    } else {
      edge_color2 <- NULL
    }
  }
  if (!is.null(edge_color2)) {
    edge_color2 <- as.numeric(edge_color2) - 1
  }

  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
}

subisomorphic_impl <- function(
  graph1,
  graph2
) {
  # Argument checks
  ensure_igraph(graph1)
  ensure_igraph(graph2)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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
) {
  # Argument checks
  ensure_igraph(graph1)
  ensure_igraph(graph2)
  if (is_missing(vertex_color1)) {
    if ("color" %in% vertex_attr_names(graph1)) {
      vertex_color1 <- V(graph1)$color
    } else {
      vertex_color1 <- NULL
    }
  }
  if (!is.null(vertex_color1)) {
    vertex_color1 <- as.numeric(vertex_color1) - 1
  }
  if (is_missing(vertex_color2)) {
    if ("color" %in% vertex_attr_names(graph2)) {
      vertex_color2 <- V(graph2)$color
    } else {
      vertex_color2 <- NULL
    }
  }
  if (!is.null(vertex_color2)) {
    vertex_color2 <- as.numeric(vertex_color2) - 1
  }
  if (is_missing(edge_color1)) {
    if ("color" %in% edge_attr_names(graph1)) {
      edge_color1 <- E(graph1)$color
    } else {
      edge_color1 <- NULL
    }
  }
  if (!is.null(edge_color1)) {
    edge_color1 <- as.numeric(edge_color1) - 1
  }
  if (is_missing(edge_color2)) {
    if ("color" %in% edge_attr_names(graph2)) {
      edge_color2 <- E(graph2)$color
    } else {
      edge_color2 <- NULL
    }
  }
  if (!is.null(edge_color2)) {
    edge_color2 <- as.numeric(edge_color2) - 1
  }

  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
}

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)
  if (is_missing(vertex_color1)) {
    if ("color" %in% vertex_attr_names(graph1)) {
      vertex_color1 <- V(graph1)$color
    } else {
      vertex_color1 <- NULL
    }
  }
  if (!is.null(vertex_color1)) {
    vertex_color1 <- as.numeric(vertex_color1) - 1
  }
  if (is_missing(vertex_color2)) {
    if ("color" %in% vertex_attr_names(graph2)) {
      vertex_color2 <- V(graph2)$color
    } else {
      vertex_color2 <- NULL
    }
  }
  if (!is.null(vertex_color2)) {
    vertex_color2 <- as.numeric(vertex_color2) - 1
  }
  if (is_missing(edge_color1)) {
    if ("color" %in% edge_attr_names(graph1)) {
      edge_color1 <- E(graph1)$color
    } else {
      edge_color1 <- NULL
    }
  }
  if (!is.null(edge_color1)) {
    edge_color1 <- as.numeric(edge_color1) - 1
  }
  if (is_missing(edge_color2)) {
    if ("color" %in% edge_attr_names(graph2)) {
      edge_color2 <- E(graph2)$color
    } else {
      edge_color2 <- NULL
    }
  }
  if (!is.null(edge_color2)) {
    edge_color2 <- as.numeric(edge_color2) - 1
  }

  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
}

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)
  if (is_missing(vertex_color1)) {
    if ("color" %in% vertex_attr_names(graph1)) {
      vertex_color1 <- V(graph1)$color
    } else {
      vertex_color1 <- NULL
    }
  }
  if (!is.null(vertex_color1)) {
    vertex_color1 <- as.numeric(vertex_color1) - 1
  }
  if (is_missing(vertex_color2)) {
    if ("color" %in% vertex_attr_names(graph2)) {
      vertex_color2 <- V(graph2)$color
    } else {
      vertex_color2 <- NULL
    }
  }
  if (!is.null(vertex_color2)) {
    vertex_color2 <- as.numeric(vertex_color2) - 1
  }
  if (is_missing(edge_color1)) {
    if ("color" %in% edge_attr_names(graph1)) {
      edge_color1 <- E(graph1)$color
    } else {
      edge_color1 <- NULL
    }
  }
  if (!is.null(edge_color1)) {
    edge_color1 <- as.numeric(edge_color1) - 1
  }
  if (is_missing(edge_color2)) {
    if ("color" %in% edge_attr_names(graph2)) {
      edge_color2 <- E(graph2)$color
    } else {
      edge_color2 <- NULL
    }
  }
  if (!is.null(edge_color2)) {
    edge_color2 <- as.numeric(edge_color2) - 1
  }

  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
}

canonical_permutation_impl <- function(
  graph,
  colors = NULL,
  sh = c("fm", "f", "fs", "fl", "flm", "fsm")
) {
  # Argument checks
  ensure_igraph(graph)
  if (is_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
  }
  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
  res <- .Call(
    R_igraph_canonical_permutation,
    graph,
    colors,
    sh
  )

  res
}

permute_vertices_impl <- function(
  graph,
  permutation
) {
  # Argument checks
  ensure_igraph(graph)
  permutation <- as.numeric(permutation) - 1

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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")
) {
  # Argument checks
  ensure_igraph(graph1)
  ensure_igraph(graph2)
  if (is_missing(colors1)) {
    if ("color" %in% vertex_attr_names(graph1)) {
      colors1 <- V(graph1)$color
    } else {
      colors1 <- NULL
    }
  }
  if (!is.null(colors1)) {
    colors1 <- as.numeric(colors1) - 1
  }
  if (is_missing(colors2)) {
    if ("color" %in% vertex_attr_names(graph2)) {
      colors2 <- V(graph2)$color
    } else {
      colors2 <- NULL
    }
  }
  if (!is.null(colors2)) {
    colors2 <- as.numeric(colors2) - 1
  }
  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
  res <- .Call(
    R_igraph_isomorphic_bliss,
    graph1,
    graph2,
    colors1,
    colors2,
    sh
  )

  res
}

count_automorphisms_impl <- function(
  graph,
  colors = NULL,
  sh = c("fm", "f", "fs", "fl", "flm", "fsm")
) {
  # Argument checks
  ensure_igraph(graph)
  if (is_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
  }
  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
  res <- .Call(
    R_igraph_count_automorphisms,
    graph,
    colors,
    sh
  )

  res
}

automorphism_group_impl <- function(
  graph,
  colors = NULL,
  sh = c("fm", "f", "fs", "fl", "flm", "fsm"),
  details = FALSE
) {
  # Argument checks
  ensure_igraph(graph)
  if (is_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
  }
  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
  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))
  }
  if (!details) {
    res <- res$generators
  }
  res
}

subisomorphic_lad_impl <- function(
  pattern,
  target,
  domains = NULL,
  induced,
  time_limit
) {
  # Argument checks
  ensure_igraph(pattern)
  ensure_igraph(target)
  if (!is.null(domains) && !is.list(domains)) {
    cli::cli_abort(
      "{.arg domains} must be a list or NULL",
      call = rlang::caller_env()
    )
  }
  induced <- as.logical(induced)
  time_limit <- as.numeric(time_limit)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_subisomorphic_lad,
    pattern,
    target,
    if (!is.null(domains)) lapply(domains, function(.x) .x - 1),
    induced,
    time_limit
  )

  res
}

simplify_and_colorize_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_simplify_and_colorize,
    graph
  )

  res
}

graph_count_impl <- function(
  n,
  directed = FALSE
) {
  # Argument checks
  n <- as.numeric(n)
  directed <- as.logical(directed)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_graph_count,
    n,
    directed
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_is_matching,
    graph,
    types,
    matching
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_is_maximal_matching,
    graph,
    types,
    matching
  )

  res
}

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)
  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
  }
  eps <- as.numeric(eps)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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()
) {
  # 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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  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)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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()
) {
  # 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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  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)
  scaled <- as.logical(scaled)
  options <- modify_list(arpack_defaults(), options)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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()
) {
  # Argument checks
  ensure_igraph(graph)
  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)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_eigen_adjacency,
    graph,
    algorithm,
    which,
    options
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_power_law_fit,
    data,
    xmin,
    force_continuous
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_sir,
    graph,
    beta,
    gamma,
    no_sim
  )

  class(res) <- "sir"
  res
}

running_mean_impl <- function(
  data,
  binwidth
) {
  # Argument checks
  data <- as.numeric(data)
  binwidth <- as.numeric(binwidth)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_running_mean,
    data,
    binwidth
  )

  res
}

random_sample_impl <- function(
  l,
  h,
  length
) {
  # Argument checks
  l <- as.numeric(l)
  h <- as.numeric(h)
  length <- as.numeric(length)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_random_sample,
    l,
    h,
    length
  )

  res
}

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_2d,
    data
  )

  res
}

dim_select_impl <- function(
  sv
) {
  # Argument checks
  sv <- as.numeric(sv)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_dim_select,
    sv
  )

  res
}

almost_equals_impl <- function(
  a,
  b,
  eps
) {
  # Argument checks
  a <- as.numeric(a)
  b <- as.numeric(b)
  eps <- as.numeric(eps)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_almost_equals,
    a,
    b,
    eps
  )

  res
}

cmp_epsilon_impl <- function(
  a,
  b,
  eps
) {
  # Argument checks
  a <- as.numeric(a)
  b <- as.numeric(b)
  eps <- as.numeric(eps)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_cmp_epsilon,
    a,
    b,
    eps
  )

  res
}

eigen_matrix_impl <- function(
  A,
  sA,
  fun,
  n,
  algorithm,
  which,
  options = arpack_defaults()
) {
  # Argument checks
  A[] <- as.numeric(A)
  requireNamespace("Matrix", quietly = TRUE)
  sA <- as(as(as(sA, "dMatrix"), "generalMatrix"), "CsparseMatrix")
  n <- as.integer(n)
  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)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_eigen_matrix,
    A,
    sA,
    n,
    algorithm,
    which,
    options
  )

  res
}

eigen_matrix_symmetric_impl <- function(
  A,
  sA,
  fun,
  n,
  algorithm,
  which,
  options = arpack_defaults()
) {
  # Argument checks
  A[] <- as.numeric(A)
  requireNamespace("Matrix", quietly = TRUE)
  sA <- as(as(as(sA, "dMatrix"), "generalMatrix"), "CsparseMatrix")
  n <- as.integer(n)
  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)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_eigen_matrix_symmetric,
    A,
    sA,
    n,
    algorithm,
    which,
    options
  )

  res
}

solve_lsap_impl <- function(
  c,
  n
) {
  # Argument checks
  c[] <- as.numeric(c)
  n <- as.numeric(n)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_solve_lsap,
    c,
    n
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_find_cycle,
    graph,
    mode
  )
  if (igraph_opt("return.vs.es")) {
    res$vertices <- create_vs(graph, res$vertices)
  }
  if (igraph_opt("return.vs.es")) {
    res$edges <- create_es(graph, res$edges)
  }
  res
}

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_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)

  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
}

is_eulerian_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_is_eulerian,
    graph
  )

  res
}

eulerian_path_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_eulerian_path,
    graph
  )
  if (igraph_opt("return.vs.es")) {
    res$epath <- create_es(graph, res$epath)
  }
  if (igraph_opt("return.vs.es")) {
    res$vpath <- create_vs(graph, res$vpath)
  }
  res
}

eulerian_cycle_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_eulerian_cycle,
    graph
  )
  if (igraph_opt("return.vs.es")) {
    res$epath <- create_es(graph, res$epath)
  }
  if (igraph_opt("return.vs.es")) {
    res$vpath <- create_vs(graph, res$vpath)
  }
  res
}

fundamental_cycles_impl <- function(
  graph,
  start = NULL,
  bfs_cutoff = -1,
  weights = NULL
) {
  # Argument checks
  ensure_igraph(graph)
  if (!is.null(start)) {
    start <- as_igraph_vs(graph, start)
    if (length(start) != 1) {
      cli::cli_abort(
        "{.arg start} must specify exactly one vertex",
        call = rlang::caller_env()
      )
    }
  }
  bfs_cutoff <- as.numeric(bfs_cutoff)
  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
  }

  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
}

minimum_cycle_basis_impl <- function(
  graph,
  bfs_cutoff = -1,
  complete = TRUE,
  use_cycle_order = TRUE,
  weights = NULL
) {
  # 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
  }
  if (!is.null(weights) && !all(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
}

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))
  # Function call
  res <- .Call(
    R_igraph_is_tree,
    graph,
    mode
  )
  if (igraph_opt("return.vs.es") && vcount(graph) != 0) {
    res$root <- create_vs(graph, res$root)
  }
  if (!details) {
    res <- res$res
  }
  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_is_forest,
    graph,
    mode
  )
  if (igraph_opt("return.vs.es")) {
    res$roots <- create_vs(graph, res$roots)
  }
  if (!details) {
    res <- res$res
  }
  res
}

from_prufer_impl <- function(
  prufer
) {
  # Argument checks
  prufer <- as.numeric(prufer) - 1

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_from_prufer,
    prufer
  )

  if (igraph_opt("add.params")) {
    res$name <- 'Tree from Prufer sequence'
    res$prufer <- prufer
  }

  res
}

to_prufer_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_to_prufer,
    graph
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_tree_from_parent_vector,
    parents,
    type
  )

  res
}

is_complete_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_is_complete,
    graph
  )

  res
}

minimum_spanning_tree_impl <- function(
  graph,
  weights = 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
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_minimum_spanning_tree,
    graph,
    weights
  )
  if (igraph_opt("return.vs.es")) {
    res <- create_es(graph, res)
  }
  res
}

minimum_spanning_tree_unweighted_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_minimum_spanning_tree_unweighted,
    graph
  )

  res
}

minimum_spanning_tree_prim_impl <- function(
  graph,
  weights
) {
  # 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
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_minimum_spanning_tree_prim,
    graph,
    weights
  )

  res
}

random_spanning_tree_impl <- function(
  graph,
  vid = 0
) {
  # Argument checks
  ensure_igraph(graph)
  if (!is.null(vid)) {
    vid <- as_igraph_vs(graph, vid)
    if (length(vid) != 1) {
      cli::cli_abort(
        "{.arg vid} must specify exactly one vertex",
        call = rlang::caller_env()
      )
    }
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  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")
) {
  # 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))
  # Function call
  res <- .Call(
    R_igraph_tree_game,
    n,
    directed,
    method
  )

  res
}

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))
  # 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
}

is_vertex_coloring_impl <- function(
  graph,
  types
) {
  # Argument checks
  ensure_igraph(graph)
  if (is_missing(types)) {
    if ("color" %in% vertex_attr_names(graph)) {
      types <- V(graph)$color
    } else {
      types <- NULL
    }
  }
  if (!is.null(types)) {
    types <- as.numeric(types) - 1
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_is_vertex_coloring,
    graph,
    types
  )

  res
}

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))
  # Function call
  res <- .Call(
    R_igraph_is_bipartite_coloring,
    graph,
    types
  )

  res
}

is_edge_coloring_impl <- function(
  graph,
  types
) {
  # Argument checks
  ensure_igraph(graph)
  if (is_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
  }

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_is_edge_coloring,
    graph,
    types
  )

  res
}

deterministic_optimal_imitation_impl <- function(
  graph,
  vid,
  optimality = c("maximum", "minimum"),
  quantities,
  strategies,
  mode = c("out", "in", "all", "total")
) {
  # Argument checks
  ensure_igraph(graph)
  vid <- as_igraph_vs(graph, vid)
  if (length(vid) != 1) {
    cli::cli_abort(
      "{.arg vid} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  optimality <- switch_igraph_arg(optimality, "minimum" = 0L, "maximum" = 1L)
  strategies <- as.numeric(strategies)
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_deterministic_optimal_imitation,
    graph,
    vid - 1,
    optimality,
    quantities,
    strategies,
    mode
  )

  res
}

moran_process_impl <- function(
  graph,
  weights = NULL,
  quantities,
  strategies,
  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) && !all(is.na(weights))) {
    weights <- as.numeric(weights)
  } else {
    weights <- NULL
  }
  strategies <- as.numeric(strategies)
  mode <- switch_igraph_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
}

roulette_wheel_imitation_impl <- function(
  graph,
  vid,
  is_local,
  quantities,
  strategies,
  mode = c("out", "in", "all", "total")
) {
  # Argument checks
  ensure_igraph(graph)
  vid <- as_igraph_vs(graph, vid)
  if (length(vid) != 1) {
    cli::cli_abort(
      "{.arg vid} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  is_local <- as.logical(is_local)
  strategies <- as.numeric(strategies)
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_roulette_wheel_imitation,
    graph,
    vid - 1,
    is_local,
    quantities,
    strategies,
    mode
  )

  res
}

stochastic_imitation_impl <- function(
  graph,
  vid,
  algo,
  quantities,
  strategies,
  mode = c("out", "in", "all", "total")
) {
  # Argument checks
  ensure_igraph(graph)
  vid <- as_igraph_vs(graph, vid)
  if (length(vid) != 1) {
    cli::cli_abort(
      "{.arg vid} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  strategies <- as.numeric(strategies)
  mode <- switch_igraph_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
}

convergence_degree_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_convergence_degree,
    graph
  )

  res
}

has_attribute_table_impl <- function(
) {
  # Argument checks


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_has_attribute_table
  )

  res
}

progress_impl <- function(
  message,
  percent
) {
  # Argument checks
  percent <- as.numeric(percent)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_progress,
    message,
    percent
  )

  res
}

status_impl <- function(
  message
) {
  # Argument checks


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_status,
    message
  )

  res
}

strerror_impl <- function(
  igraph_errno
) {
  # Argument checks
  igraph_errno <- as.numeric(igraph_errno)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_strerror,
    igraph_errno
  )

  res
}

expand_path_to_pairs_impl <- function(
  path
) {
  # Argument checks
  path <- as_igraph_vs(path, path)
  path <- path - 1

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_expand_path_to_pairs,
    path
  )
  if (igraph_opt("return.vs.es")) {
    res <- create_vs(path, res)
  }
  res
}

invalidate_cache_impl <- function(
  graph
) {
  # Argument checks
  ensure_igraph(graph)

  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_invalidate_cache,
    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) != 1) {
      cli::cli_abort(
        "{.arg start} must specify exactly one vertex",
        call = rlang::caller_env()
      )
    }
  }
  edge_path <- as_igraph_es(graph, edge_path)
  mode <- switch_igraph_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


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_version
  )

  res
}

bfs_closure_impl <- function(
  graph,
  root,
  roots = NULL,
  mode = c("out", "in", "all", "total"),
  unreachable,
  restricted = NULL,
  callback
) {
  # Argument checks
  ensure_igraph(graph)
  root <- as_igraph_vs(graph, root)
  if (length(root) != 1) {
    cli::cli_abort(
      "{.arg root} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  if (!is.null(roots)) {
    roots <- as_igraph_vs(graph, roots)
    roots <- roots - 1
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )
  unreachable <- as.logical(unreachable)
  if (!is.null(restricted)) {
    restricted <- as_igraph_vs(graph, restricted)
    restricted <- restricted - 1
  }
  if (!is.null(callback)) {
    if (!is.function(callback)) {
      cli::cli_abort("{.arg callback} must be a function")
    }
    callback_wrapped <- function(...) {
      tryCatch(
        {
          out <- callback(...)
          if (is.logical(out) && length(out) == 1 && !is.na(out)) {
            out
          } else {
            rlang::error_cnd(message = "Callback returned a value different from TRUE or FALSE")
          }
        },
        error = function(e) e,
        interrupt = function(e) e
      )
    }
  } else {
    callback_wrapped <- NULL
  }


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_bfs_closure,
    graph,
    root - 1,
    roots,
    mode,
    unreachable,
    restricted,
    callback_wrapped
  )
  if (igraph_opt("return.vs.es")) {
    res$order <- create_vs(graph, res$order)
  }
  res
}

dfs_closure_impl <- function(
  graph,
  root,
  mode = c("out", "in", "all", "total"),
  unreachable,
  in_callback,
  out_callback
) {
  # Argument checks
  ensure_igraph(graph)
  root <- as_igraph_vs(graph, root)
  if (length(root) != 1) {
    cli::cli_abort(
      "{.arg root} must specify exactly one vertex",
      call = rlang::caller_env()
    )
  }
  mode <- switch_igraph_arg(
    mode,
    "out" = 1L,
    "in" = 2L,
    "all" = 3L,
    "total" = 3L
  )
  unreachable <- as.logical(unreachable)
  if (!is.null(in_callback)) {
    if (!is.function(in_callback)) {
      cli::cli_abort("{.arg callback} must be a function")
    }
    in_callback_wrapped <- function(...) {
      tryCatch(
        {
          out <- in_callback(...)
          if (is.logical(out) && length(out) == 1 && !is.na(out)) {
            out
          } else {
            rlang::error_cnd(message = "Callback returned a value different from TRUE or FALSE")
          }
        },
        error = function(e) e,
        interrupt = function(e) e
      )
    }
  } else {
    in_callback_wrapped <- NULL
  }

  if (!is.null(out_callback)) {
    if (!is.function(out_callback)) {
      cli::cli_abort("{.arg callback} must be a function")
    }
    out_callback_wrapped <- function(...) {
      tryCatch(
        {
          out <- out_callback(...)
          if (is.logical(out) && length(out) == 1 && !is.na(out)) {
            out
          } else {
            rlang::error_cnd(message = "Callback returned a value different from TRUE or FALSE")
          }
        },
        error = function(e) e,
        interrupt = function(e) e
      )
    }
  } else {
    out_callback_wrapped <- NULL
  }


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_dfs_closure,
    graph,
    root - 1,
    mode,
    unreachable,
    in_callback_wrapped,
    out_callback_wrapped
  )
  if (igraph_opt("return.vs.es")) {
    res$order <- create_vs(graph, res$order)
  }
  if (igraph_opt("return.vs.es")) {
    res$order_out <- create_vs(graph, res$order_out)
  }
  res
}

cliques_callback_closure_impl <- function(
  graph,
  min_size = 0,
  max_size = 0,
  callback
) {
  # Argument checks
  ensure_igraph(graph)
  min_size <- as.numeric(min_size)
  max_size <- as.numeric(max_size)
  if (!is.null(callback)) {
    if (!is.function(callback)) {
      cli::cli_abort("{.arg callback} must be a function")
    }
    callback_wrapped <- function(...) {
      tryCatch(
        {
          out <- callback(...)
          if (is.logical(out) && length(out) == 1 && !is.na(out)) {
            out
          } else {
            rlang::error_cnd(message = "Callback returned a value different from TRUE or FALSE")
          }
        },
        error = function(e) e,
        interrupt = function(e) e
      )
    }
  } else {
    callback_wrapped <- NULL
  }


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_cliques_callback_closure,
    graph,
    min_size,
    max_size,
    callback_wrapped
  )

  res
}

maximal_cliques_callback_closure_impl <- function(
  graph,
  min_size = 0,
  max_size = 0,
  callback
) {
  # Argument checks
  ensure_igraph(graph)
  min_size <- as.numeric(min_size)
  max_size <- as.numeric(max_size)
  if (!is.null(callback)) {
    if (!is.function(callback)) {
      cli::cli_abort("{.arg callback} must be a function")
    }
    callback_wrapped <- function(...) {
      tryCatch(
        {
          out <- callback(...)
          if (is.logical(out) && length(out) == 1 && !is.na(out)) {
            out
          } else {
            rlang::error_cnd(message = "Callback returned a value different from TRUE or FALSE")
          }
        },
        error = function(e) e,
        interrupt = function(e) e
      )
    }
  } else {
    callback_wrapped <- NULL
  }


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_maximal_cliques_callback_closure,
    graph,
    min_size,
    max_size,
    callback_wrapped
  )

  res
}

community_leading_eigenvector_callback_closure_impl <- function(
  graph,
  weights = NULL,
  membership = NULL,
  steps = -1,
  options = arpack_defaults(),
  start = FALSE,
  callback = NULL,
  extra = NULL,
  env = parent.frame(),
  env_arp = environment(igraph.i.levc.arp)
) {
  # 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
  }
  if (!is.null(membership)) {
    membership <- as.numeric(membership)
  }
  steps <- as.numeric(steps)
  options <- modify_list(arpack_defaults(), options)
  start <- as.logical(start)
  if (!is.null(callback)) {
    if (!is.function(callback)) {
      cli::cli_abort("{.arg callback} must be a function")
    }
    callback_wrapped <- function(...) {
      tryCatch(
        {
          out <- callback(...)
          if (is.logical(out) && length(out) == 1 && !is.na(out)) {
            out
          } else {
            rlang::error_cnd(message = "Callback returned a value different from TRUE or FALSE")
          }
        },
        error = function(e) e,
        interrupt = function(e) e
      )
    }
  } else {
    callback_wrapped <- NULL
  }


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_community_leading_eigenvector_callback_closure,
    graph,
    weights,
    membership,
    steps,
    options,
    start,
    callback_wrapped,
    extra,
    env,
    env_arp
  )

  class(res) <- "igraph.eigenc"
  res
}

get_isomorphisms_vf2_callback_closure_impl <- function(
  graph1,
  graph2,
  vertex_color1 = NULL,
  vertex_color2 = NULL,
  edge_color1 = NULL,
  edge_color2 = NULL,
  callback
) {
  # Argument checks
  ensure_igraph(graph1)
  ensure_igraph(graph2)
  if (is_missing(vertex_color1)) {
    if ("color" %in% vertex_attr_names(graph1)) {
      vertex_color1 <- V(graph1)$color
    } else {
      vertex_color1 <- NULL
    }
  }
  if (!is.null(vertex_color1)) {
    vertex_color1 <- as.numeric(vertex_color1) - 1
  }
  if (is_missing(vertex_color2)) {
    if ("color" %in% vertex_attr_names(graph2)) {
      vertex_color2 <- V(graph2)$color
    } else {
      vertex_color2 <- NULL
    }
  }
  if (!is.null(vertex_color2)) {
    vertex_color2 <- as.numeric(vertex_color2) - 1
  }
  if (is_missing(edge_color1)) {
    if ("color" %in% edge_attr_names(graph1)) {
      edge_color1 <- E(graph1)$color
    } else {
      edge_color1 <- NULL
    }
  }
  if (!is.null(edge_color1)) {
    edge_color1 <- as.numeric(edge_color1) - 1
  }
  if (is_missing(edge_color2)) {
    if ("color" %in% edge_attr_names(graph2)) {
      edge_color2 <- E(graph2)$color
    } else {
      edge_color2 <- NULL
    }
  }
  if (!is.null(edge_color2)) {
    edge_color2 <- as.numeric(edge_color2) - 1
  }
  if (!is.null(callback)) {
    if (!is.function(callback)) {
      cli::cli_abort("{.arg callback} must be a function")
    }
    callback_wrapped <- function(...) {
      tryCatch(
        {
          out <- callback(...)
          if (is.logical(out) && length(out) == 1 && !is.na(out)) {
            out
          } else {
            rlang::error_cnd(message = "Callback returned a value different from TRUE or FALSE")
          }
        },
        error = function(e) e,
        interrupt = function(e) e
      )
    }
  } else {
    callback_wrapped <- NULL
  }


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_get_isomorphisms_vf2_callback_closure,
    graph1,
    graph2,
    vertex_color1,
    vertex_color2,
    edge_color1,
    edge_color2,
    callback_wrapped
  )

  res
}

get_subisomorphisms_vf2_callback_closure_impl <- function(
  graph1,
  graph2,
  vertex_color1 = NULL,
  vertex_color2 = NULL,
  edge_color1 = NULL,
  edge_color2 = NULL,
  callback
) {
  # Argument checks
  ensure_igraph(graph1)
  ensure_igraph(graph2)
  if (is_missing(vertex_color1)) {
    if ("color" %in% vertex_attr_names(graph1)) {
      vertex_color1 <- V(graph1)$color
    } else {
      vertex_color1 <- NULL
    }
  }
  if (!is.null(vertex_color1)) {
    vertex_color1 <- as.numeric(vertex_color1) - 1
  }
  if (is_missing(vertex_color2)) {
    if ("color" %in% vertex_attr_names(graph2)) {
      vertex_color2 <- V(graph2)$color
    } else {
      vertex_color2 <- NULL
    }
  }
  if (!is.null(vertex_color2)) {
    vertex_color2 <- as.numeric(vertex_color2) - 1
  }
  if (is_missing(edge_color1)) {
    if ("color" %in% edge_attr_names(graph1)) {
      edge_color1 <- E(graph1)$color
    } else {
      edge_color1 <- NULL
    }
  }
  if (!is.null(edge_color1)) {
    edge_color1 <- as.numeric(edge_color1) - 1
  }
  if (is_missing(edge_color2)) {
    if ("color" %in% edge_attr_names(graph2)) {
      edge_color2 <- E(graph2)$color
    } else {
      edge_color2 <- NULL
    }
  }
  if (!is.null(edge_color2)) {
    edge_color2 <- as.numeric(edge_color2) - 1
  }
  if (!is.null(callback)) {
    if (!is.function(callback)) {
      cli::cli_abort("{.arg callback} must be a function")
    }
    callback_wrapped <- function(...) {
      tryCatch(
        {
          out <- callback(...)
          if (is.logical(out) && length(out) == 1 && !is.na(out)) {
            out
          } else {
            rlang::error_cnd(message = "Callback returned a value different from TRUE or FALSE")
          }
        },
        error = function(e) e,
        interrupt = function(e) e
      )
    }
  } else {
    callback_wrapped <- NULL
  }


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_get_subisomorphisms_vf2_callback_closure,
    graph1,
    graph2,
    vertex_color1,
    vertex_color2,
    edge_color1,
    edge_color2,
    callback_wrapped
  )

  res
}

simple_cycles_callback_closure_impl <- function(
  graph,
  mode = c("out", "in", "all", "total"),
  min_cycle_length = -1,
  max_cycle_length = -1,
  callback
) {
  # 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)
  if (!is.null(callback)) {
    if (!is.function(callback)) {
      cli::cli_abort("{.arg callback} must be a function")
    }
    callback_wrapped <- function(...) {
      tryCatch(
        {
          out <- callback(...)
          if (is.logical(out) && length(out) == 1 && !is.na(out)) {
            out
          } else {
            rlang::error_cnd(message = "Callback returned a value different from TRUE or FALSE")
          }
        },
        error = function(e) e,
        interrupt = function(e) e
      )
    }
  } else {
    callback_wrapped <- NULL
  }


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_simple_cycles_callback_closure,
    graph,
    mode,
    min_cycle_length,
    max_cycle_length,
    callback_wrapped
  )

  res
}

motifs_randesu_callback_closure_impl <- function(
  graph,
  size,
  cut_prob = NULL,
  callback
) {
  # Argument checks
  ensure_igraph(graph)
  size <- as.numeric(size)
  if (!is.null(cut_prob)) {
    cut_prob <- as.numeric(cut_prob)
  }
  if (!is.null(callback)) {
    if (!is.function(callback)) {
      cli::cli_abort("{.arg callback} must be a function")
    }
    callback_wrapped <- function(...) {
      tryCatch(
        {
          out <- callback(...)
          if (is.logical(out) && length(out) == 1 && !is.na(out)) {
            out
          } else {
            rlang::error_cnd(message = "Callback returned a value different from TRUE or FALSE")
          }
        },
        error = function(e) e,
        interrupt = function(e) e
      )
    }
  } else {
    callback_wrapped <- NULL
  }


  on.exit(.Call(R_igraph_finalizer))
  # Function call
  res <- .Call(
    R_igraph_motifs_randesu_callback_closure,
    graph,
    size,
    cut_prob,
    callback_wrapped
  )

  res
}

