stacked_linear_algebra_graph/graph/vertex_store/vertex_vector/
vertex_vector.rs

1use std::fmt::Display;
2use std::mem;
3use std::sync::Arc;
4
5use graphblas_sparse_linear_algebra::collections::sparse_vector::clone_graphblas_vector;
6use graphblas_sparse_linear_algebra::collections::sparse_vector::new_graphblas_vector;
7use graphblas_sparse_linear_algebra::collections::sparse_vector::GetGraphblasSparseVector;
8use graphblas_sparse_linear_algebra::collections::sparse_vector::SparseVector;
9use graphblas_sparse_linear_algebra::context::Context as GraphBLASContext;
10use graphblas_sparse_linear_algebra::context::GetContext;
11use graphblas_sparse_linear_algebra::graphblas_bindings::GrB_Vector;
12use graphblas_sparse_linear_algebra::graphblas_bindings::GrB_Vector_free;
13use graphblas_sparse_linear_algebra::operators::apply::ApplyUnaryOperator;
14use graphblas_sparse_linear_algebra::operators::apply::UnaryOperatorApplier;
15use graphblas_sparse_linear_algebra::operators::binary_operator::Assignment;
16use graphblas_sparse_linear_algebra::operators::mask::SelectEntireVector;
17use graphblas_sparse_linear_algebra::operators::mask::VectorMask;
18use graphblas_sparse_linear_algebra::operators::options::OperatorOptions;
19use graphblas_sparse_linear_algebra::operators::unary_operator::Identity;
20use graphblas_sparse_linear_algebra::value_type::ValueType as GraphblasValueType;
21
22use crate::error::GraphComputingError;
23use crate::graph::graph::GetGraphblasContext;
24use crate::graph::indexing::ElementCount;
25use crate::graph::value_type::implement_1_type_macro_with_enum_type_indentifier_for_all_value_types;
26use crate::graph::value_type::implement_macro_for_all_native_value_types;
27use crate::graph::value_type::GetValueTypeIdentifier;
28use crate::graph::value_type::GetValueTypeIdentifierRef;
29use crate::graph::value_type::ValueType;
30use crate::graph::value_type::ValueTypeIdentifier;
31
32use super::GetVectorLength;
33
34unsafe impl Send for VertexVector {}
35unsafe impl Sync for VertexVector {}
36
37#[derive(Debug)]
38pub(crate) struct VertexVector {
39    graphblas_context: Arc<GraphBLASContext>,
40    value_type: ValueTypeIdentifier,
41    sparse_vector: GrB_Vector,
42}
43
44pub(crate) trait CreateVertexVector<T> {
45    fn new(
46        graphblas_context: Arc<GraphBLASContext>,
47        initial_vertex_capacity: ElementCount,
48    ) -> Result<VertexVector, GraphComputingError>;
49}
50
51impl<T: ValueType + GetValueTypeIdentifier> CreateVertexVector<T> for VertexVector {
52    fn new(
53        graphblas_context: Arc<GraphBLASContext>,
54        initial_vertex_capacity: ElementCount,
55    ) -> Result<VertexVector, GraphComputingError> {
56        Ok(VertexVector {
57            graphblas_context: graphblas_context.clone(),
58            sparse_vector: unsafe {
59                new_graphblas_vector(
60                    &graphblas_context,
61                    initial_vertex_capacity,
62                    T::to_graphblas_type(),
63                )?
64            },
65            value_type: T::value_type_identifier(),
66        })
67    }
68}
69
70impl Drop for VertexVector {
71    fn drop(&mut self) -> () {
72        let _ = self
73            .graphblas_context
74            .call_without_detailed_error_information(|| unsafe {
75                GrB_Vector_free(&mut self.sparse_vector)
76            });
77    }
78}
79
80impl Clone for VertexVector {
81    fn clone(&self) -> Self {
82        VertexVector {
83            graphblas_context: self.graphblas_context.to_owned(),
84            value_type: self.value_type.to_owned(),
85            sparse_vector: unsafe {
86                clone_graphblas_vector(self.context_ref(), self.graphblas_vector_ref()).unwrap()
87            },
88        }
89    }
90}
91
92impl Display for VertexVector {
93    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94        writeln!(f, "VertexVector:");
95        writeln!(f, "graphblas_context: {:?}", self.graphblas_context);
96        writeln!(f, "value_type: {:?}", self.value_type);
97        writeln!(
98            f,
99            "sparse_vector: \n{}",
100            <VertexVector as ToSparseVector<f64>>::to_sparse_vector(self).unwrap()
101        );
102        return writeln!(f, "");
103    }
104}
105
106impl GetGraphblasContext for VertexVector {
107    fn graphblas_context(&self) -> Arc<GraphBLASContext> {
108        self.graphblas_context.clone()
109    }
110
111    fn graphblas_context_ref(&self) -> &Arc<GraphBLASContext> {
112        &self.graphblas_context
113    }
114}
115
116impl GetContext for VertexVector {
117    fn context(&self) -> Arc<GraphBLASContext> {
118        self.graphblas_context.clone()
119    }
120
121    fn context_ref(&self) -> &Arc<GraphBLASContext> {
122        &self.graphblas_context
123    }
124}
125
126impl GetGraphblasSparseVector for VertexVector {
127    unsafe fn graphblas_vector(&self) -> GrB_Vector {
128        self.sparse_vector
129    }
130
131    unsafe fn graphblas_vector_ref(&self) -> &GrB_Vector {
132        &self.sparse_vector
133    }
134
135    unsafe fn graphblas_vector_mut_ref(&mut self) -> &mut GrB_Vector {
136        &mut self.sparse_vector
137    }
138}
139
140impl VectorMask for VertexVector {
141    unsafe fn graphblas_vector(&self) -> GrB_Vector {
142        self.sparse_vector
143    }
144}
145
146impl GetValueTypeIdentifierRef for VertexVector {
147    fn value_type_identifier_ref(&self) -> &ValueTypeIdentifier {
148        &self.value_type
149    }
150}
151
152// TODO: this approach should work once Type Alias Impl Trait (TAIT) is stable
153// https://github.com/rust-lang/rust/issues/63063
154// fn apply_to_adjacency_matrices_of_all_value_types<T: ValueType, F: Fn(&SparseVector<T>) -> Result<(), GraphComputingError>>(&self, f: F) -> Result<(), GraphComputingError> {
155//     f(&self.sparse_vector_bool)?;
156//     Ok(())
157// }
158
159pub trait ToSparseVector<T: ValueType> {
160    fn to_sparse_vector(&self) -> Result<SparseVector<T>, GraphComputingError>;
161}
162
163pub trait IntoSparseVector<T: ValueType> {
164    fn into_sparse_vector(self) -> Result<SparseVector<T>, GraphComputingError>;
165}
166
167impl<T: ValueType + ToSparseVectorForValueType<T>> ToSparseVector<T> for VertexVector {
168    fn to_sparse_vector(&self) -> Result<SparseVector<T>, GraphComputingError> {
169        T::to_sparse_vector(self)
170    }
171}
172
173impl<T: ValueType + IntoSparseVectorForValueType<T>> IntoSparseVector<T> for VertexVector {
174    fn into_sparse_vector(self) -> Result<SparseVector<T>, GraphComputingError> {
175        T::into_sparse_vector(self)
176    }
177}
178
179pub(crate) trait ToSparseVectorForValueType<T: ValueType> {
180    fn to_sparse_vector(
181        vector: &(impl GetContext
182              + GetGraphblasSparseVector
183              + GetVectorLength
184              + GetValueTypeIdentifierRef),
185    ) -> Result<SparseVector<T>, GraphComputingError>;
186}
187
188pub(crate) trait IntoSparseVectorForValueType<T: ValueType> {
189    fn into_sparse_vector(vector: VertexVector) -> Result<SparseVector<T>, GraphComputingError>;
190}
191
192pub(crate) trait IntoSparseVectorAndClearValuesForValueType<T: ValueType> {
193    fn into_sparse_vector_and_clear_values(
194        vector: &mut VertexVector,
195    ) -> Result<SparseVector<T>, GraphComputingError>;
196}
197
198macro_rules! implement_to_sparse_vector_for_value_type {
199    ($value_type_identifier:ident, $value_type:ty) => {
200        impl ToSparseVectorForValueType<$value_type> for $value_type {
201            fn to_sparse_vector(
202                vector: &(impl GetContext
203                      + GetGraphblasSparseVector
204                      + GetVectorLength
205                      + GetValueTypeIdentifierRef),
206            ) -> Result<SparseVector<$value_type>, GraphComputingError> {
207                match vector.value_type_identifier_ref() {
208                    &ValueTypeIdentifier::$value_type_identifier => unsafe {
209                        Ok(SparseVector::<$value_type>::from_graphblas_vector(
210                            vector.context(),
211                            clone_graphblas_vector(
212                                vector.context_ref(),
213                                vector.graphblas_vector_ref(),
214                            )?,
215                        )?)
216                    },
217                    _ => {
218                        let mut product_vector =
219                            SparseVector::<$value_type>::new(vector.context(), vector.length()?)?;
220
221                        UnaryOperatorApplier::new().apply_to_vector(
222                            &Identity::<$value_type>::new(),
223                            vector,
224                            &Assignment::<$value_type>::new(),
225                            &mut product_vector,
226                            &SelectEntireVector::new(vector.context()),
227                            &OperatorOptions::new_default(),
228                        )?;
229
230                        return Ok(product_vector);
231                    }
232                }
233            }
234        }
235    };
236}
237implement_1_type_macro_with_enum_type_indentifier_for_all_value_types!(
238    implement_to_sparse_vector_for_value_type
239);
240
241macro_rules! implement_into_sparse_vector_for_value_type {
242    ($value_type_identifier:ident, $value_type:ty) => {
243        impl IntoSparseVectorForValueType<$value_type> for $value_type {
244            fn into_sparse_vector(
245                mut vertex_vector: VertexVector,
246            ) -> Result<SparseVector<$value_type>, GraphComputingError> {
247                <$value_type>::into_sparse_vector_and_clear_values(&mut vertex_vector)
248            }
249        }
250    };
251}
252implement_1_type_macro_with_enum_type_indentifier_for_all_value_types!(
253    implement_into_sparse_vector_for_value_type
254);
255
256macro_rules! implement_into_sparse_vector_for_value_type {
257    ($value_type_identifier:ident, $value_type:ty) => {
258        impl IntoSparseVectorAndClearValuesForValueType<$value_type> for $value_type {
259            fn into_sparse_vector_and_clear_values(
260                vertex_vector: &mut VertexVector,
261            ) -> Result<SparseVector<$value_type>, GraphComputingError> {
262                match vertex_vector.value_type_identifier_ref() {
263                    &ValueTypeIdentifier::$value_type_identifier => unsafe {
264                        let mut graphblas_vector = new_graphblas_vector(
265                            &vertex_vector.graphblas_context,
266                            vertex_vector.length()?,
267                            <$value_type>::to_graphblas_type(),
268                        )?;
269
270                        mem::swap(&mut graphblas_vector, &mut vertex_vector.sparse_vector);
271
272                        Ok(SparseVector::<$value_type>::from_graphblas_vector(
273                            vertex_vector.context(),
274                            graphblas_vector,
275                        )?)
276                    },
277                    _ => {
278                        let mut product_vector = SparseVector::<$value_type>::new(
279                            vertex_vector.context(),
280                            vertex_vector.length()?,
281                        )?;
282
283                        UnaryOperatorApplier::new().apply_to_vector(
284                            &Identity::<$value_type>::new(),
285                            vertex_vector,
286                            &Assignment::<$value_type>::new(),
287                            &mut product_vector,
288                            &SelectEntireVector::new(vertex_vector.context()),
289                            &OperatorOptions::new_default(),
290                        )?;
291
292                        return Ok(product_vector);
293                    }
294                }
295            }
296        }
297    };
298}
299implement_1_type_macro_with_enum_type_indentifier_for_all_value_types!(
300    implement_into_sparse_vector_for_value_type
301);
302
303pub(crate) trait CreateSparseVectorForValueType<T: ValueType> {
304    fn new_sparse_vector(
305        graphblas_context: Arc<GraphBLASContext>,
306        initial_vertex_capacity: ElementCount,
307    ) -> Result<SparseVector<T>, GraphComputingError>;
308}
309
310macro_rules! implement_create_sparse_vector_for_value_type {
311    ($value_type:ty) => {
312        impl CreateSparseVectorForValueType<$value_type> for $value_type {
313            fn new_sparse_vector(
314                graphblas_context: Arc<GraphBLASContext>,
315                initial_vertex_capacity: ElementCount,
316            ) -> Result<SparseVector<$value_type>, GraphComputingError> {
317                Ok(SparseVector::<$value_type>::new(
318                    graphblas_context,
319                    initial_vertex_capacity,
320                )?)
321            }
322        }
323    };
324}
325implement_macro_for_all_native_value_types!(implement_create_sparse_vector_for_value_type);