graphblas_sparse_linear_algebra/operators/monoid/
monoid.rs1use 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 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 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); assert_eq!(product.element_value_or_default(1).unwrap(), false); assert_eq!(product.element_value_or_default(2).unwrap(), false); assert_eq!(product.element_value_or_default(3).unwrap(), true);
291 assert_eq!(product.element_value_or_default(4).unwrap(), true); assert_eq!(product.element_value_or_default(5).unwrap(), true); assert_eq!(product.element_value_or_default(6).unwrap(), false); }
295}