graphblas_sparse_linear_algebra/operators/monoid/
monoid.rs

1use std::marker::PhantomData;
2
3use crate::graphblas_bindings::*;
4use crate::value_type::utilities_to_implement_traits_for_all_value_types::{
5    implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types_except_bool,
6    implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types_with_postfix,
7    implement_macro_with_1_type_trait_and_typed_graphblas_function_for_unsigned_integers_with_postfix,
8};
9use crate::value_type::ValueType;
10
11pub trait Monoid<T>
12where
13    T: ValueType,
14{
15    fn graphblas_type(&self) -> GrB_Monoid;
16}
17
18macro_rules! implement_monoid_operator {
19    ($monoid_operator_name:ident, $graphblas_operator_trait_name:ident) => {
20        pub trait $graphblas_operator_trait_name<T: ValueType> {
21            fn graphblas_type() -> GrB_Monoid;
22        }
23
24        impl<T: ValueType + $graphblas_operator_trait_name<T>> Monoid<T>
25            for $monoid_operator_name<T>
26        {
27            fn graphblas_type(&self) -> GrB_Monoid {
28                T::graphblas_type()
29            }
30        }
31
32        impl<T: ValueType> $monoid_operator_name<T> {
33            pub fn new() -> Self {
34                Self {
35                    _value_type: PhantomData,
36                }
37            }
38        }
39    };
40}
41
42macro_rules! implement_typed_monoid_operator {
43    ($operator_trait_name:ident,
44        $graphblas_operator_name:ident,
45        $value_type:ty
46    ) => {
47        impl $operator_trait_name<$value_type> for $value_type {
48            fn graphblas_type() -> GrB_Monoid {
49                unsafe { $graphblas_operator_name }
50            }
51        }
52    };
53}
54
55#[derive(Debug, Clone)]
56pub struct Min<T: ValueType> {
57    _value_type: PhantomData<T>,
58}
59
60implement_monoid_operator!(Min, MinMonoidTyped);
61
62implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types_except_bool!(
63    implement_typed_monoid_operator,
64    MinMonoidTyped,
65    GrB_MIN_MONOID
66);
67
68#[derive(Debug, Clone)]
69pub struct Max<T: ValueType> {
70    _value_type: PhantomData<T>,
71}
72
73implement_monoid_operator!(Max, MaxMonoidTyped);
74
75implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types_except_bool!(
76    implement_typed_monoid_operator,
77    MaxMonoidTyped,
78    GrB_MAX_MONOID
79);
80
81#[derive(Debug, Clone)]
82pub struct Plus<T: ValueType> {
83    _value_type: PhantomData<T>,
84}
85
86implement_monoid_operator!(Plus, PlusMonoidTyped);
87
88implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types_except_bool!(
89    implement_typed_monoid_operator,
90    PlusMonoidTyped,
91    GrB_PLUS_MONOID
92);
93
94#[derive(Debug, Clone)]
95pub struct Times<T: ValueType> {
96    _value_type: PhantomData<T>,
97}
98
99implement_monoid_operator!(Times, TimesMonoidTyped);
100
101implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types_except_bool!(
102    implement_typed_monoid_operator,
103    TimesMonoidTyped,
104    GrB_TIMES_MONOID
105);
106
107#[derive(Debug, Clone)]
108pub struct Any<T: ValueType> {
109    _value_type: PhantomData<T>,
110}
111
112implement_monoid_operator!(Any, AnyMonoidTyped);
113
114implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types_with_postfix!(
115    implement_typed_monoid_operator,
116    AnyMonoidTyped,
117    GxB_ANY,
118    MONOID
119);
120
121#[derive(Debug, Clone)]
122pub struct LogicalOr<T: ValueType> {
123    _value_type: PhantomData<T>,
124}
125
126#[derive(Debug, Clone)]
127pub struct LogicalAnd<T: ValueType> {
128    _value_type: PhantomData<T>,
129}
130
131#[derive(Debug, Clone)]
132pub struct LogicalExclusiveOr<T: ValueType> {
133    _value_type: PhantomData<T>,
134}
135
136#[derive(Debug, Clone)]
137pub struct Equal<T: ValueType> {
138    _value_type: PhantomData<T>,
139}
140
141implement_monoid_operator!(LogicalOr, LogicalOrMonoidTyped);
142implement_monoid_operator!(LogicalAnd, LogicalAndMonoidTyped);
143implement_monoid_operator!(LogicalExclusiveOr, LogicalExclusiveOrMonoidTyped);
144implement_monoid_operator!(Equal, EqualMonoidTyped);
145
146implement_typed_monoid_operator!(LogicalOrMonoidTyped, GrB_LOR_MONOID_BOOL, bool);
147implement_typed_monoid_operator!(LogicalAndMonoidTyped, GrB_LAND_MONOID_BOOL, bool);
148implement_typed_monoid_operator!(LogicalExclusiveOrMonoidTyped, GrB_LXOR_MONOID_BOOL, bool);
149implement_typed_monoid_operator!(EqualMonoidTyped, GrB_LXNOR_MONOID_BOOL, bool);
150
151#[derive(Debug, Clone)]
152pub struct BitwiseLogicalOr<T: ValueType> {
153    _value_type: PhantomData<T>,
154}
155
156#[derive(Debug, Clone)]
157pub struct BitwiseLogicalAnd<T: ValueType> {
158    _value_type: PhantomData<T>,
159}
160
161#[derive(Debug, Clone)]
162pub struct BitwiseLogicalExclusiveOr<T: ValueType> {
163    _value_type: PhantomData<T>,
164}
165
166implement_monoid_operator!(BitwiseLogicalOr, BitwiseLogicalOrMonoidTyped);
167implement_monoid_operator!(BitwiseLogicalAnd, BitwiseLogicalAndMonoidTyped);
168implement_monoid_operator!(
169    BitwiseLogicalExclusiveOr,
170    BitwiseLogicalExclusiveOrMonoidTyped
171);
172
173implement_macro_with_1_type_trait_and_typed_graphblas_function_for_unsigned_integers_with_postfix!(
174    implement_typed_monoid_operator,
175    BitwiseLogicalOrMonoidTyped,
176    GxB_BOR,
177    MONOID
178);
179
180implement_macro_with_1_type_trait_and_typed_graphblas_function_for_unsigned_integers_with_postfix!(
181    implement_typed_monoid_operator,
182    BitwiseLogicalAndMonoidTyped,
183    GxB_BAND,
184    MONOID
185);
186
187implement_macro_with_1_type_trait_and_typed_graphblas_function_for_unsigned_integers_with_postfix!(
188    implement_typed_monoid_operator,
189    BitwiseLogicalExclusiveOrMonoidTyped,
190    GxB_BXOR,
191    MONOID
192);
193
194#[cfg(test)]
195mod tests {
196    use super::*;
197
198    use crate::collections::sparse_vector::operations::{
199        FromVectorElementList, GetSparseVectorElementList, GetSparseVectorElementValue,
200    };
201    use crate::collections::sparse_vector::{SparseVector, VectorElementList};
202    use crate::context::Context;
203    use crate::operators::binary_operator::{Assignment, First};
204    use crate::operators::element_wise_addition::{
205        ApplyElementWiseVectorAdditionMonoidOperator, ElementWiseVectorAdditionMonoidOperator,
206    };
207    use crate::operators::mask::SelectEntireVector;
208    use crate::operators::options::OptionsForOperatorWithMatrixArguments;
209
210    #[test]
211    fn new_binary_operator() {
212        let min_monoid = Min::<f32>::new();
213        let _graphblas_type = min_monoid.graphblas_type();
214    }
215
216    #[test]
217    fn test_element_wise_addition_with_equality_operator() {
218        let context = Context::init_default().unwrap();
219
220        let operator = Equal::<bool>::new();
221        let options = OptionsForOperatorWithMatrixArguments::new_default();
222        let equality_operator = ElementWiseVectorAdditionMonoidOperator::new();
223
224        let length = 7;
225
226        let multiplier = SparseVector::<bool>::new(context.clone(), length).unwrap();
227        let multiplicant = multiplier.clone();
228        let mut product = multiplier.clone();
229
230        // Test multiplication of empty matrices
231        equality_operator
232            .apply(
233                &multiplier,
234                &operator,
235                &multiplicant,
236                &Assignment::new(),
237                &mut product,
238                &SelectEntireVector::new(context.clone()),
239                &options,
240            )
241            .unwrap();
242        let element_list = product.element_list().unwrap();
243
244        assert_eq!(element_list.length(), 0);
245
246        let multiplier_element_list = VectorElementList::<bool>::from_element_vector(vec![
247            (1, false).into(),
248            (3, true).into(),
249            (5, false).into(),
250            (6, true).into(),
251        ]);
252        let multiplier = SparseVector::<bool>::from_element_list(
253            context.clone(),
254            length,
255            multiplier_element_list,
256            &First::<bool>::new(),
257        )
258        .unwrap();
259
260        let multiplicant_element_list = VectorElementList::<bool>::from_element_vector(vec![
261            (3, true).into(),
262            (4, true).into(),
263            (5, false).into(),
264            (6, false).into(),
265        ]);
266        let multiplicant = SparseVector::<bool>::from_element_list(
267            context.clone(),
268            length,
269            multiplicant_element_list,
270            &First::<bool>::new(),
271        )
272        .unwrap();
273
274        // Test multiplication of full matrices
275        equality_operator
276            .apply(
277                &multiplier,
278                &operator,
279                &multiplicant,
280                &Assignment::new(),
281                &mut product,
282                &SelectEntireVector::new(context.clone()),
283                &options,
284            )
285            .unwrap();
286
287        assert_eq!(product.element_value_or_default(0).unwrap(), false); // operator does not apply on empty
288        assert_eq!(product.element_value_or_default(1).unwrap(), false); // false unequal to empty
289        assert_eq!(product.element_value_or_default(2).unwrap(), false); // operator does not apply on empty
290        assert_eq!(product.element_value_or_default(3).unwrap(), true);
291        assert_eq!(product.element_value_or_default(4).unwrap(), true); // true and empty => true
292        assert_eq!(product.element_value_or_default(5).unwrap(), true); // true and false => true
293        assert_eq!(product.element_value_or_default(6).unwrap(), false); // false and true => false
294    }
295}