use std::ptr;
use cugraph_sys::{cugraph_ecg, cugraph_error_t, cugraph_hierarchical_clustering_result_t};
use super::EcgResult;
use crate::{
error::{Result, check_error, require_non_null},
graph::{Forward, Graph},
handle::EnteredContext,
params::{FractionF64, IterationCount, NonNegativeF64, defaults},
random::RngState,
types::to_bool_t,
};
#[derive(Debug, Clone, Copy)]
#[must_use]
pub struct EcgParams {
pub min_weight: NonNegativeF64,
pub ensemble_size: IterationCount,
pub max_level: IterationCount,
pub threshold: FractionF64,
pub resolution: FractionF64,
pub do_expensive_check: bool,
}
impl Default for EcgParams {
fn default() -> Self {
Self {
min_weight: NonNegativeF64::new(0.001).expect("literal is non-negative"),
ensemble_size: IterationCount::new(10).expect("literal is non-zero"),
max_level: defaults::LOUVAIN_MAX_LEVEL,
threshold: defaults::ECG_THRESHOLD,
resolution: defaults::ECG_RESOLUTION,
do_expensive_check: false,
}
}
}
pub(crate) fn ecg(
handle: &EnteredContext<'_>,
rng_state: &mut RngState,
graph: &mut Graph<Forward>,
params: &EcgParams,
) -> Result<EcgResult> {
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, "ecg")?;
unsafe {
let code = cugraph_ecg(
handle.handle_ptr(),
rng_state.as_ptr(),
graph_ptr,
params.min_weight.get(),
usize::from(params.ensemble_size),
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(), "ecg")?;
}
let result = require_non_null(result, "ecg", "hierarchical_clustering_result")?;
unsafe { EcgResult::from_raw(result, handle.device(), handle.runtime_bound_lease()) }
}