use std::ptr;
use cugraph_sys::{cugraph_error_t, cugraph_hierarchical_clustering_result_t, cugraph_louvain};
use super::LouvainResult;
use crate::{
error::{Result, check_error, require_non_null},
graph::{Forward, Graph},
handle::EnteredContext,
params::{IterationCount, NonNegativeF64, PositiveF64, defaults},
types::to_bool_t,
};
#[derive(Debug, Clone, Copy)]
#[must_use]
pub struct LouvainParams {
pub max_level: IterationCount,
pub threshold: NonNegativeF64,
pub resolution: PositiveF64,
pub do_expensive_check: bool,
}
impl Default for LouvainParams {
fn default() -> Self {
Self {
max_level: defaults::LOUVAIN_MAX_LEVEL,
threshold: defaults::LOUVAIN_THRESHOLD,
resolution: defaults::LOUVAIN_RESOLUTION,
do_expensive_check: false,
}
}
}
pub(crate) fn louvain(
handle: &EnteredContext<'_>,
graph: &mut Graph<Forward>,
params: &LouvainParams,
) -> Result<LouvainResult> {
let mut result: *mut cugraph_hierarchical_clustering_result_t = ptr::null_mut();
let mut error: *mut cugraph_error_t = ptr::null_mut();
let graph_ptr = graph.as_ptr(handle, "louvain")?;
unsafe {
let code = cugraph_louvain(
handle.handle_ptr(),
graph_ptr,
usize::from(params.max_level),
params.threshold.get(),
params.resolution.get(),
to_bool_t(params.do_expensive_check),
&mut result,
&mut error,
);
check_error(code, error, handle.device(), "louvain")?;
}
let result = require_non_null(result, "louvain", "hierarchical_clustering_result")?;
unsafe { LouvainResult::from_raw(result, handle.device(), handle.runtime_bound_lease()) }
}