graphblas_sparse_linear_algebra 0.62.0

Wrapper for SuiteSparse:GraphBLAS
Documentation
use suitesparse_graphblas_sys::GxB_Matrix_isStoredElement;

use crate::collections::sparse_matrix::{
    ColumnIndex, GetCoordinateIndices, GetGraphblasSparseMatrix, RowIndex, SparseMatrix,
};
use crate::context::CallGraphBlasContext;
use crate::error::{
    GraphblasErrorType, LogicErrorType, SparseLinearAlgebraError, SparseLinearAlgebraErrorType,
};
use crate::index::IndexConversion;
use crate::value_type::ValueType;

pub trait IsSparseMatrixElement {
    fn is_element(
        &self,
        row_index: RowIndex,
        column_index: ColumnIndex,
    ) -> Result<bool, SparseLinearAlgebraError>;
    fn try_is_element(
        &self,
        row_index: RowIndex,
        column_index: ColumnIndex,
    ) -> Result<(), SparseLinearAlgebraError>;

    fn is_element_at_coordinate(
        &self,
        coordinate: &impl GetCoordinateIndices,
    ) -> Result<bool, SparseLinearAlgebraError>;
    fn try_is_element_at_coordinate(
        &self,
        coordinate: &impl GetCoordinateIndices,
    ) -> Result<(), SparseLinearAlgebraError>;
}

impl<T: ValueType> IsSparseMatrixElement for SparseMatrix<T> {
    fn is_element(
        &self,
        row_index: RowIndex,
        column_index: ColumnIndex,
    ) -> Result<bool, SparseLinearAlgebraError> {
        is_sparse_matrix_element(self, row_index, column_index)
    }

    fn try_is_element(
        &self,
        row_index: RowIndex,
        column_index: ColumnIndex,
    ) -> Result<(), SparseLinearAlgebraError> {
        try_is_sparse_matrix_element(self, row_index, column_index)
    }

    fn is_element_at_coordinate(
        &self,
        coordinate: &impl GetCoordinateIndices,
    ) -> Result<bool, SparseLinearAlgebraError> {
        is_sparse_matrix_element_at_coordinate(self, coordinate)
    }

    fn try_is_element_at_coordinate(
        &self,
        coordinate: &impl GetCoordinateIndices,
    ) -> Result<(), SparseLinearAlgebraError> {
        try_is_sparse_matrix_element_at_coordinate(self, coordinate)
    }
}

pub fn is_sparse_matrix_element(
    matrix: &impl GetGraphblasSparseMatrix,
    row_index: RowIndex,
    column_index: ColumnIndex,
) -> Result<bool, SparseLinearAlgebraError> {
    let row_index = row_index.as_graphblas_index()?;
    let column_index = column_index.as_graphblas_index()?;

    let result = matrix.context_ref().call(
        || unsafe {
            GxB_Matrix_isStoredElement(matrix.graphblas_matrix_ptr(), row_index, column_index)
        },
        unsafe { &matrix.graphblas_matrix_ptr() },
    );
    // println!("{:?}", result);
    match result {
        Ok(_) => Ok(true),
        Err(error) => match error.error_type() {
            SparseLinearAlgebraErrorType::LogicErrorType(LogicErrorType::GraphBlas(
                GraphblasErrorType::NoValue,
            )) => Ok(false),
            SparseLinearAlgebraErrorType::LogicErrorType(LogicErrorType::GraphBlas(
                GraphblasErrorType::IndexOutOfBounds,
            )) => Ok(false),
            SparseLinearAlgebraErrorType::LogicErrorType(LogicErrorType::GraphBlas(
                GraphblasErrorType::InvalidIndex,
            )) => Ok(false),
            _ => Err(error),
        },
    }
}

pub fn is_sparse_matrix_element_at_coordinate(
    matrix: &impl GetGraphblasSparseMatrix,
    coordinate: &impl GetCoordinateIndices,
) -> Result<bool, SparseLinearAlgebraError> {
    is_sparse_matrix_element(matrix, coordinate.row_index(), coordinate.column_index())
}

pub fn try_is_sparse_matrix_element(
    matrix: &impl GetGraphblasSparseMatrix,
    row_index: RowIndex,
    column_index: ColumnIndex,
) -> Result<(), SparseLinearAlgebraError> {
    let row_index = row_index.as_graphblas_index()?;
    let column_index = column_index.as_graphblas_index()?;

    let result = matrix.context_ref().call(
        || unsafe {
            GxB_Matrix_isStoredElement(matrix.graphblas_matrix_ptr(), row_index, column_index)
        },
        unsafe { &matrix.graphblas_matrix_ptr() },
    );
    match result {
        Ok(_) => Ok(()),
        Err(error) => Err(error),
    }
}

pub fn try_is_sparse_matrix_element_at_coordinate(
    matrix: &impl GetGraphblasSparseMatrix,
    coordinate: &impl GetCoordinateIndices,
) -> Result<(), SparseLinearAlgebraError> {
    try_is_sparse_matrix_element(matrix, coordinate.row_index(), coordinate.column_index())
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{
        collections::sparse_matrix::{
            operations::SetSparseMatrixElement, ColumnIndex, Coordinate, MatrixElement, RowIndex,
            Size, SparseMatrix,
        },
        context::Context,
    };

    #[test]
    fn is_element_outside_matrix_size() {
        let context = Context::init_default().unwrap();

        let target_height: RowIndex = 10;
        let target_width: ColumnIndex = 5;
        let size = Size::new(target_height, target_width);

        let mut sparse_matrix = SparseMatrix::<i32>::new(context, size).unwrap();

        sparse_matrix
            .set_element(MatrixElement::from_triple(1, 2, 3))
            .unwrap();
        sparse_matrix
            .set_element(MatrixElement::from_triple(1, 4, 4))
            .unwrap();

        assert!(!sparse_matrix
            .is_element(target_height, target_width)
            .unwrap());
    }
}