stacked_linear_algebra_graph/graph/edge_store/adjacency_matrix_attribute_caching/
transpose.rs1use graphblas_sparse_linear_algebra::collections::sparse_matrix::operations::sparse_matrix_size;
2use graphblas_sparse_linear_algebra::collections::sparse_matrix::GetMatrixDimensions;
3use graphblas_sparse_linear_algebra::operators::binary_operator::Assignment;
4use graphblas_sparse_linear_algebra::operators::mask::MatrixMask;
5use graphblas_sparse_linear_algebra::operators::options::OptionsForOperatorWithMatrixArgument;
6use graphblas_sparse_linear_algebra::operators::transpose::TransposeMatrix;
7use graphblas_sparse_linear_algebra::{
8 collections::sparse_matrix::GetGraphblasSparseMatrix, context::GetContext,
9 operators::transpose::MatrixTranspose,
10};
11use once_cell::sync::Lazy;
12
13use crate::error::GraphComputingError;
14use crate::graph::edge_store::weighted_adjacency_matrix::{
15 CreateWeightedAdjacencyMatrix, WeightedAdjacencyMatrix,
16};
17use crate::graph::value_type::implement_macro_for_all_native_value_types_with_capitalized_value_type;
18
19static DEFAULT_GRAPHBLAS_OPERATOR_OPTIONS: Lazy<OptionsForOperatorWithMatrixArgument> =
20 Lazy::new(|| OptionsForOperatorWithMatrixArgument::new_default());
21
22static MATRIX_TRANSPOSE_OPERATOR: Lazy<MatrixTranspose> = Lazy::new(|| MatrixTranspose::new());
23
24macro_rules! create_lazy_static_assignment_operator {
25 ($VALUE_TYPE:ident, $value_type:ty) => {
26 paste::paste! {
27 static [<ASSIGNMENT_OPERATOR_ $VALUE_TYPE>]: Lazy<Assignment<$value_type>> = Lazy::new(|| Assignment::<$value_type>::new());
28 }
29 };
30}
31implement_macro_for_all_native_value_types_with_capitalized_value_type!(
32 create_lazy_static_assignment_operator
33);
34
35macro_rules! create_transpose_adjacency_matrix_function {
36 ($VALUE_TYPE:ident, $value_type:ty) => {
37 paste::paste! {
38 pub(crate) fn [<transpose_adjacency_matrix_ $value_type>](
39 adjacency_matrix: &(impl GetGraphblasSparseMatrix + GetContext),
40 mask: &(impl MatrixMask + GetContext)
41 ) -> Result<WeightedAdjacencyMatrix, GraphComputingError> {
42 let sparse_matrix_size = sparse_matrix_size(adjacency_matrix)?; let mut transposed_adjacency_matrix =
44 <WeightedAdjacencyMatrix as CreateWeightedAdjacencyMatrix<$value_type>>::new(
45 adjacency_matrix.context(),
46 sparse_matrix_size.column_width(),
47 )?;
48
49 MatrixTranspose::new().apply(
50 adjacency_matrix,
51 &Assignment::<$value_type>::new(),
52 &mut transposed_adjacency_matrix,
53 mask,
55 &*DEFAULT_GRAPHBLAS_OPERATOR_OPTIONS,
56 )?;
57
58 Ok(transposed_adjacency_matrix)
70 }
71 }
72 };
73}
74implement_macro_for_all_native_value_types_with_capitalized_value_type!(
75 create_transpose_adjacency_matrix_function
76);
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 use graphblas_sparse_linear_algebra::{context::Context, operators::mask::SelectEntireMatrix};
83
84 use crate::graph::{
85 edge_store::weighted_adjacency_matrix::{
86 operations::{GetEdgeWeight, SetEdge},
87 CreateWeightedAdjacencyMatrix, WeightedAdjacencyMatrix,
88 },
89 indexing::VertexIndex,
90 };
91
92 #[test]
93 fn transpose_adjacency_matrix() {
94 let context = Context::init_default().unwrap();
95
96 let mut adjacency_matrix = <WeightedAdjacencyMatrix as CreateWeightedAdjacencyMatrix<
97 u32,
98 >>::new(context.clone(), 10)
99 .unwrap();
100
101 adjacency_matrix
102 .set_edge_unchecked(&VertexIndex::new(0), &VertexIndex::new(0), 1e3)
103 .unwrap();
104 adjacency_matrix
105 .set_edge_unchecked(&VertexIndex::new(1), &VertexIndex::new(0), 2e3)
106 .unwrap();
107
108 let transposed = transpose_adjacency_matrix_u32(
109 &adjacency_matrix,
110 &SelectEntireMatrix::new(context.clone()),
111 )
112 .unwrap();
113
114 assert_eq!(
115 GetEdgeWeight::<u32>::edge_weight_unchecked(
116 &transposed,
117 &VertexIndex::new(0),
118 &VertexIndex::new(0)
119 )
120 .unwrap()
121 .unwrap(),
122 1000u32
123 );
124 assert_eq!(
125 GetEdgeWeight::<u32>::edge_weight_unchecked(
126 &transposed,
127 &VertexIndex::new(0),
128 &VertexIndex::new(1)
129 )
130 .unwrap()
131 .unwrap(),
132 2000u32
133 );
134 assert_eq!(
135 GetEdgeWeight::<u32>::edge_weight_unchecked(
136 &transposed,
137 &VertexIndex::new(1),
138 &VertexIndex::new(0)
139 )
140 .unwrap(),
141 None
142 );
143 }
144}