Skip to main content

cugraph/labeling/
connected_components.rs

1//! Connected-components algorithms.
2
3use std::ptr;
4
5use cugraph_sys::{
6    cugraph_error_t, cugraph_labeling_result_t, cugraph_strongly_connected_components,
7    cugraph_weakly_connected_components,
8};
9
10use super::LabelingResult;
11use crate::{
12    error::{Result, check_error, require_non_null},
13    graph::Graph,
14    handle::EnteredContext,
15    types::to_bool_t,
16};
17
18/// Parameters shared by weakly and strongly connected components.
19#[derive(Debug, Clone, Copy, Default)]
20#[must_use]
21pub struct ConnectedComponentsParams {
22    /// Whether to run expensive input validation in the C library.
23    pub do_expensive_check: bool,
24}
25
26/// Compute weakly connected components.
27///
28/// The native cuGraph API requires a symmetric graph. This wrapper does not
29/// add a Rust-side graph-property hard failure; native validation reports
30/// detailed graph-property errors when checks are enabled.
31pub(crate) fn weakly_connected_components<T>(
32    handle: &EnteredContext<'_>,
33    graph: &mut Graph<T>,
34    params: &ConnectedComponentsParams,
35) -> Result<LabelingResult> {
36    let mut result: *mut cugraph_labeling_result_t = ptr::null_mut();
37    let mut error: *mut cugraph_error_t = ptr::null_mut();
38    let graph_ptr = graph.as_ptr(handle, "weakly_connected_components")?;
39
40    // SAFETY: `graph` and `handle` are live for the duration of the call, and
41    // `result`/`error` are valid out-pointers.
42    unsafe {
43        let code = cugraph_weakly_connected_components(
44            handle.handle_ptr(),
45            graph_ptr,
46            to_bool_t(params.do_expensive_check),
47            &mut result,
48            &mut error,
49        );
50        check_error(code, error, handle.device(), "weakly_connected_components")?;
51    }
52
53    let result = require_non_null(result, "weakly_connected_components", "labeling_result")?;
54
55    // SAFETY: on success, cuGraph transfers ownership of the result pointer.
56    unsafe { LabelingResult::from_raw(result, handle.device(), handle.runtime_bound_lease()) }
57}
58
59/// Compute strongly connected components.
60pub(crate) fn strongly_connected_components<T>(
61    handle: &EnteredContext<'_>,
62    graph: &mut Graph<T>,
63    params: &ConnectedComponentsParams,
64) -> Result<LabelingResult> {
65    let mut result: *mut cugraph_labeling_result_t = ptr::null_mut();
66    let mut error: *mut cugraph_error_t = ptr::null_mut();
67    let graph_ptr = graph.as_ptr(handle, "strongly_connected_components")?;
68
69    // SAFETY: `graph` and `handle` are live for the duration of the call, and
70    // `result`/`error` are valid out-pointers.
71    unsafe {
72        let code = cugraph_strongly_connected_components(
73            handle.handle_ptr(),
74            graph_ptr,
75            to_bool_t(params.do_expensive_check),
76            &mut result,
77            &mut error,
78        );
79        check_error(code, error, handle.device(), "strongly_connected_components")?;
80    }
81
82    let result = require_non_null(result, "strongly_connected_components", "labeling_result")?;
83
84    // SAFETY: on success, cuGraph transfers ownership of the result pointer.
85    unsafe { LabelingResult::from_raw(result, handle.device(), handle.runtime_bound_lease()) }
86}