graphblas_sparse_linear_algebra/operators/
transpose.rs

1use crate::collections::sparse_matrix::GetGraphblasSparseMatrix;
2use crate::context::CallGraphBlasContext;
3use crate::error::SparseLinearAlgebraError;
4use crate::graphblas_bindings::GrB_transpose;
5
6use crate::value_type::ValueType;
7
8use super::binary_operator::AccumulatorBinaryOperator;
9use super::mask::MatrixMask;
10use super::options::GetOptionsForOperatorWithMatrixArgument;
11
12#[derive(Debug, Clone)]
13pub struct MatrixTranspose {}
14
15// Implemented methods do not provide mutable access to GraphBLAS operators or options.
16// Code review must consider that no mtable access is provided.
17// https://doc.rust-lang.org/nomicon/send-and-sync.html
18unsafe impl Send for MatrixTranspose {}
19unsafe impl Sync for MatrixTranspose {}
20
21impl MatrixTranspose {
22    pub fn new() -> Self {
23        Self {}
24    }
25}
26
27pub trait TransposeMatrix<EvaluationDomain: ValueType> {
28    fn apply(
29        &self,
30        matrix: &impl GetGraphblasSparseMatrix,
31        accumulator: &impl AccumulatorBinaryOperator<EvaluationDomain>,
32        transpose: &mut impl GetGraphblasSparseMatrix,
33        mask: &impl MatrixMask,
34        options: &impl GetOptionsForOperatorWithMatrixArgument,
35    ) -> Result<(), SparseLinearAlgebraError>;
36}
37
38impl<EvaluationDomain: ValueType> TransposeMatrix<EvaluationDomain> for MatrixTranspose {
39    fn apply(
40        &self,
41        matrix: &impl GetGraphblasSparseMatrix,
42        accumulator: &impl AccumulatorBinaryOperator<EvaluationDomain>,
43        transpose: &mut impl GetGraphblasSparseMatrix,
44        mask: &impl MatrixMask,
45        options: &impl GetOptionsForOperatorWithMatrixArgument,
46    ) -> Result<(), SparseLinearAlgebraError> {
47        let context = transpose.context_ref();
48
49        context.call(
50            || unsafe {
51                GrB_transpose(
52                    transpose.graphblas_matrix(),
53                    mask.graphblas_matrix(),
54                    accumulator.accumulator_graphblas_type(),
55                    matrix.graphblas_matrix(),
56                    options.graphblas_descriptor(),
57                )
58            },
59            unsafe { transpose.graphblas_matrix_ref() },
60        )?;
61
62        Ok(())
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69    use crate::collections::sparse_matrix::operations::{
70        FromMatrixElementList, GetSparseMatrixElementValue,
71    };
72    use crate::collections::sparse_matrix::{MatrixElementList, SparseMatrix};
73    use crate::context::Context;
74    use crate::operators::binary_operator::{Assignment, First};
75    use crate::operators::mask::SelectEntireMatrix;
76    use crate::operators::options::OptionsForOperatorWithMatrixArgument;
77
78    #[test]
79    fn test_transpose() {
80        let context = Context::init_default().unwrap();
81
82        let element_list = MatrixElementList::<u8>::from_element_vector(vec![
83            (0, 0, 1).into(),
84            (1, 0, 2).into(),
85            (0, 1, 3).into(),
86            (1, 1, 4).into(),
87        ]);
88
89        let matrix = SparseMatrix::<u8>::from_element_list(
90            context.clone(),
91            (2, 2).into(),
92            element_list.clone(),
93            &First::<u8>::new(),
94        )
95        .unwrap();
96
97        let mut matrix_transpose = SparseMatrix::<u8>::new(context.clone(), (2, 2).into()).unwrap();
98
99        let transpose_operator = MatrixTranspose::new();
100
101        transpose_operator
102            .apply(
103                &matrix,
104                &Assignment::<u8>::new(),
105                &mut matrix_transpose,
106                &SelectEntireMatrix::new(context.clone()),
107                &OptionsForOperatorWithMatrixArgument::new_default(),
108            )
109            .unwrap();
110
111        assert_eq!(matrix_transpose.element_value_or_default(0, 0).unwrap(), 1);
112        assert_eq!(matrix_transpose.element_value_or_default(1, 0).unwrap(), 3);
113        assert_eq!(matrix_transpose.element_value_or_default(0, 1).unwrap(), 2);
114        assert_eq!(matrix_transpose.element_value_or_default(1, 1).unwrap(), 4);
115    }
116}