1use std::marker::PhantomData;
2use std::ptr;
3
4use crate::graphblas_bindings::*;
5use crate::value_type::utilities_to_implement_traits_for_all_value_types::{
6 implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_floating_point_types,
7 implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_graphblas_index_integer_value_types,
8 implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_integer_value_types,
9 implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types,
10};
11use crate::value_type::ValueType;
12
13pub trait AccumulatorBinaryOperator<T>
14where
15 T: ValueType,
16{
17 fn accumulator_graphblas_type(&self) -> GrB_BinaryOp;
18}
19
20pub trait BinaryOperator<T>: AccumulatorBinaryOperator<T>
21where
22 T: ValueType,
23{
24 fn graphblas_type(&self) -> GrB_BinaryOp;
25}
26
27pub trait ReturnsBool {}
28
29macro_rules! implement_binary_operator {
30 ($operator_name:ident, $graphblas_operator_trait_name:ident) => {
31 pub trait $graphblas_operator_trait_name<T: ValueType> {
32 fn graphblas_type() -> GrB_BinaryOp;
33 }
34
35 impl<T: ValueType + $graphblas_operator_trait_name<T>> BinaryOperator<T>
36 for $operator_name<T>
37 {
38 fn graphblas_type(&self) -> GrB_BinaryOp {
39 T::graphblas_type()
40 }
41 }
42
43 impl<T: ValueType + $graphblas_operator_trait_name<T>> AccumulatorBinaryOperator<T>
44 for $operator_name<T>
45 {
46 fn accumulator_graphblas_type(&self) -> GrB_BinaryOp {
47 T::graphblas_type()
48 }
49 }
50
51 impl<T: ValueType> $operator_name<T> {
52 pub fn new() -> Self {
53 Self {
54 _evaluation_domain: PhantomData,
55 }
56 }
57 }
58 };
59}
60
61macro_rules! implement_typed_binary_operator {
62 ($operator_trait_name:ident,
63 $graphblas_operator_name:ident,
64 $value_type:ty
65 ) => {
66 impl $operator_trait_name<$value_type> for $value_type {
67 fn graphblas_type() -> GrB_BinaryOp {
68 unsafe { $graphblas_operator_name }
69 }
70 }
71 };
72}
73
74macro_rules! implement_binary_operator_with_bool_return_type {
105 ($operator_name:ident, $graphblas_operator_trait_name:ident) => {
106 pub trait $graphblas_operator_trait_name<T: ValueType> {
107 fn graphblas_type() -> GrB_BinaryOp;
108 }
109
110 impl<T: ValueType + $graphblas_operator_trait_name<T>> BinaryOperator<T>
111 for $operator_name<T>
112 {
113 fn graphblas_type(&self) -> GrB_BinaryOp {
114 T::graphblas_type()
115 }
116 }
117
118 impl<T: ValueType + $graphblas_operator_trait_name<T>> AccumulatorBinaryOperator<T>
119 for $operator_name<T>
120 {
121 fn accumulator_graphblas_type(&self) -> GrB_BinaryOp {
122 T::graphblas_type()
123 }
124 }
125
126 impl<T: ValueType> $operator_name<T> {
127 pub fn new() -> Self {
128 Self {
129 _evaluation_domain: PhantomData,
130 }
131 }
132 }
133
134 impl<T: ValueType> ReturnsBool for $operator_name<T> {}
135 };
136}
137
138macro_rules! implement_typed_binary_operator_with_bool_return_type {
139 ($operator_trait_name:ident,
140 $graphblas_operator_name:ident,
141 $value_type:ty
142 ) => {
143 impl $operator_trait_name<$value_type> for $value_type {
144 fn graphblas_type() -> GrB_BinaryOp {
145 unsafe { $graphblas_operator_name }
146 }
147 }
148 };
149}
150
151macro_rules! implement_binary_operator_for_boolean {
152 (
153 $operator_name:ident,
154 $graphblas_operator_name:ident
155 ) => {
156 impl BinaryOperator<bool> for $operator_name<bool> {
157 fn graphblas_type(&self) -> GrB_BinaryOp {
158 unsafe { $graphblas_operator_name }
159 }
160 }
161
162 impl AccumulatorBinaryOperator<bool> for $operator_name<bool> {
163 fn accumulator_graphblas_type(&self) -> GrB_BinaryOp {
164 unsafe { $graphblas_operator_name }
165 }
166 }
167
168 impl $operator_name<bool> {
169 pub fn new() -> Self {
170 Self {
171 _evaluation_domain: PhantomData,
172 }
173 }
174 }
175
176 impl ReturnsBool for $operator_name<bool> {}
177 };
178}
179
180macro_rules! define_binary_operator {
181 ($identifier: ident) => {
182 #[derive(Debug, Clone)]
183 pub struct $identifier<T>
184 where
185 T: ValueType,
186 {
187 _evaluation_domain: PhantomData<T>,
188 }
189 };
190}
191
192define_binary_operator!(Assignment);
193impl<T: ValueType> AccumulatorBinaryOperator<T> for Assignment<T> {
194 fn accumulator_graphblas_type(&self) -> GrB_BinaryOp {
195 ptr::null_mut()
196 }
197}
198
199impl<T: ValueType> Assignment<T> {
202 pub fn new() -> Self {
203 Self {
204 _evaluation_domain: PhantomData,
205 }
206 }
207}
208
209define_binary_operator!(First);
211implement_binary_operator!(First, FirstTyped);
212implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
213 implement_typed_binary_operator,
214 FirstTyped,
215 GrB_FIRST
216);
217
218define_binary_operator!(Second);
220implement_binary_operator!(Second, SecondTyped);
221implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
222 implement_typed_binary_operator,
223 SecondTyped,
224 GrB_SECOND
225);
226
227define_binary_operator!(One);
229implement_binary_operator!(One, OneTyped);
230implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
231 implement_typed_binary_operator,
232 OneTyped,
233 GrB_ONEB
234);
235
236define_binary_operator!(Power);
238implement_binary_operator!(Power, PowerTyped);
239implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
240 implement_typed_binary_operator,
241 PowerTyped,
242 GxB_POW
243);
244
245define_binary_operator!(Plus);
247implement_binary_operator!(Plus, PlusTyped);
248implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
249 implement_typed_binary_operator,
250 PlusTyped,
251 GrB_PLUS
252);
253
254define_binary_operator!(Minus);
256implement_binary_operator!(Minus, MinusTyped);
257implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
258 implement_typed_binary_operator,
259 MinusTyped,
260 GrB_MINUS
261);
262
263define_binary_operator!(ReverseMinus);
265implement_binary_operator!(ReverseMinus, ReverseMinusTyped);
266implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
267 implement_typed_binary_operator,
268 ReverseMinusTyped,
269 GxB_RMINUS
270);
271
272define_binary_operator!(Times);
274implement_binary_operator!(Times, TimesTyped);
275implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
276 implement_typed_binary_operator,
277 TimesTyped,
278 GrB_TIMES
279);
280
281define_binary_operator!(Divide);
283implement_binary_operator!(Divide, DivideTyped);
284implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
285 implement_typed_binary_operator,
286 DivideTyped,
287 GrB_DIV
288);
289
290define_binary_operator!(ReverseDivide);
292implement_binary_operator!(ReverseDivide, ReverseDivideTyped);
293implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
294 implement_typed_binary_operator,
295 ReverseDivideTyped,
296 GxB_RDIV
297);
298
299#[derive(Debug, Clone)]
301pub struct IsEqual<T>
302where
303 T: ValueType,
304{
305 _evaluation_domain: PhantomData<T>,
306}
307
308implement_binary_operator_with_bool_return_type!(IsEqual, IsEqualTyped);
309implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
310 implement_typed_binary_operator_with_bool_return_type,
311 IsEqualTyped,
312 GrB_EQ
313);
314
315define_binary_operator!(TypedIsEqual);
317implement_binary_operator!(TypedIsEqual, TypedIsEqualTyped);
318implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
319 implement_typed_binary_operator,
320 TypedIsEqualTyped,
321 GxB_ISEQ
322);
323
324#[derive(Debug, Clone)]
326pub struct IsNotEqual<T>
327where
328 T: ValueType,
329{
330 _evaluation_domain: PhantomData<T>,
331}
332
333implement_binary_operator_with_bool_return_type!(IsNotEqual, IsNotEqualTyped);
334implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
335 implement_typed_binary_operator_with_bool_return_type,
336 IsNotEqualTyped,
337 GrB_NE
338);
339
340define_binary_operator!(TypedIsNotEqual);
342implement_binary_operator!(TypedIsNotEqual, TypedIsNotEqualTyped);
343implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
344 implement_typed_binary_operator,
345 TypedIsNotEqualTyped,
346 GxB_ISNE
347);
348
349define_binary_operator!(Any);
351implement_binary_operator!(Any, AnyTyped);
352implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
353 implement_typed_binary_operator,
354 AnyTyped,
355 GxB_ANY
356);
357
358define_binary_operator!(Min);
360implement_binary_operator!(Min, MinTyped);
361implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
362 implement_typed_binary_operator,
363 MinTyped,
364 GrB_MIN
365);
366
367define_binary_operator!(Max);
369implement_binary_operator!(Max, MaxTyped);
370implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
371 implement_typed_binary_operator,
372 MaxTyped,
373 GrB_MAX
374);
375
376#[derive(Debug, Clone)]
378pub struct IsGreaterThan<T>
379where
380 T: ValueType,
381{
382 _evaluation_domain: PhantomData<T>,
383}
384
385implement_binary_operator_with_bool_return_type!(IsGreaterThan, IsGreaterThanTyped);
386implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
387 implement_typed_binary_operator_with_bool_return_type,
388 IsGreaterThanTyped,
389 GrB_GT
390);
391
392define_binary_operator!(TypedIsGreaterThan);
394implement_binary_operator!(TypedIsGreaterThan, TypedIsGreaterThanTyped);
395implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
396 implement_typed_binary_operator,
397 TypedIsGreaterThanTyped,
398 GxB_ISGT
399);
400
401#[derive(Debug, Clone)]
403pub struct IsGreaterThanOrEqualTo<T>
404where
405 T: ValueType,
406{
407 _evaluation_domain: PhantomData<T>,
408}
409
410implement_binary_operator_with_bool_return_type!(
411 IsGreaterThanOrEqualTo,
412 IsGreaterThanOrEqualToTyped
413);
414implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
415 implement_typed_binary_operator_with_bool_return_type,
416 IsGreaterThanOrEqualToTyped,
417 GrB_GE
418);
419
420define_binary_operator!(TypedIsGreaterThanOrEqualTo);
422implement_binary_operator!(
423 TypedIsGreaterThanOrEqualTo,
424 TypedIsGreaterThanOrEqualToTyped
425);
426implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
427 implement_typed_binary_operator,
428 TypedIsGreaterThanOrEqualToTyped,
429 GxB_ISGE
430);
431
432#[derive(Debug, Clone)]
434pub struct IsLessThan<T>
435where
436 T: ValueType,
437{
438 _evaluation_domain: PhantomData<T>,
439}
440
441implement_binary_operator_with_bool_return_type!(IsLessThan, IsLessThanTyped);
442implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
443 implement_typed_binary_operator_with_bool_return_type,
444 IsLessThanTyped,
445 GrB_LT
446);
447
448define_binary_operator!(TypedIsLessThan);
450implement_binary_operator!(TypedIsLessThan, TypedIsLessThanTyped);
451implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
452 implement_typed_binary_operator,
453 TypedIsLessThanTyped,
454 GxB_ISLT
455);
456
457#[derive(Debug, Clone)]
459pub struct IsLessThanOrEqualTo<T>
460where
461 T: ValueType,
462{
463 _evaluation_domain: PhantomData<T>,
464}
465
466implement_binary_operator_with_bool_return_type!(IsLessThanOrEqualTo, IsLessThanOrEqualToTyped);
467implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
468 implement_typed_binary_operator_with_bool_return_type,
469 IsLessThanOrEqualToTyped,
470 GrB_LE
471);
472
473define_binary_operator!(TypedIsLessThanOrEqualTo);
475implement_binary_operator!(TypedIsLessThanOrEqualTo, TypedIsLessThanOrEqualToTyped);
476implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
477 implement_typed_binary_operator,
478 TypedIsLessThanOrEqualToTyped,
479 GxB_ISLE
480);
481
482define_binary_operator!(LogicalOr);
484implement_binary_operator_for_boolean!(LogicalOr, GrB_LOR);
485
486define_binary_operator!(TypedLogicalOr);
488implement_binary_operator!(TypedLogicalOr, TypedLogicalOrTyped);
489implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
490 implement_typed_binary_operator,
491 TypedLogicalOrTyped,
492 GxB_LOR
493);
494
495define_binary_operator!(LogicalAnd);
497implement_binary_operator_for_boolean!(LogicalAnd, GrB_LAND);
498
499define_binary_operator!(TypedLogicalAnd);
501implement_binary_operator!(TypedLogicalAnd, TypedLogicalAndTyped);
502implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
503 implement_typed_binary_operator,
504 TypedLogicalAndTyped,
505 GxB_LAND
506);
507
508define_binary_operator!(LogicalExclusiveOr);
510implement_binary_operator_for_boolean!(LogicalExclusiveOr, GrB_LXOR);
511
512define_binary_operator!(TypedLogicalExclusiveOr);
514implement_binary_operator!(TypedLogicalExclusiveOr, TypedLogicalExclusiveOrTyped);
515implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_value_types!(
516 implement_typed_binary_operator,
517 TypedLogicalExclusiveOrTyped,
518 GxB_LXOR
519);
520
521define_binary_operator!(FloatingPointFourQuadrantArcTangent);
523implement_binary_operator!(
524 FloatingPointFourQuadrantArcTangent,
525 FloatingPointFourQuadrantArcTangentTyped
526);
527implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_floating_point_types!(
528 implement_typed_binary_operator,
529 FloatingPointFourQuadrantArcTangentTyped,
530 GxB_ATAN2
531);
532
533define_binary_operator!(FloatingPointHypotenuse);
535implement_binary_operator!(FloatingPointHypotenuse, FloatingPointHypotenuseTyped);
536implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_floating_point_types!(
537 implement_typed_binary_operator,
538 FloatingPointHypotenuseTyped,
539 GxB_HYPOT
540);
541
542define_binary_operator!(FloatingPointRemainder);
545implement_binary_operator!(FloatingPointRemainder, FloatingPointRemainderTyped);
546implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_floating_point_types!(
547 implement_typed_binary_operator,
548 FloatingPointRemainderTyped,
549 GxB_REMAINDER
550);
551
552define_binary_operator!(FloatingPointModulus);
555implement_binary_operator!(FloatingPointModulus, FloatingPointModulusTyped);
556implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_floating_point_types!(
557 implement_typed_binary_operator,
558 FloatingPointModulusTyped,
559 GxB_FMOD
560);
561
562define_binary_operator!(LDExp);
565implement_binary_operator!(LDExp, LDExpTyped);
566implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_floating_point_types!(
567 implement_typed_binary_operator,
568 LDExpTyped,
569 GxB_LDEXP
570);
571
572define_binary_operator!(FloatingPointFromMagnitudeAndSign);
574implement_binary_operator!(
575 FloatingPointFromMagnitudeAndSign,
576 FloatingPointFromMagnitudeAndSignTyped
577);
578implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_floating_point_types!(
579 implement_typed_binary_operator,
580 FloatingPointFromMagnitudeAndSignTyped,
581 GxB_COPYSIGN
582);
583
584define_binary_operator!(BitWiseLogicalOr);
587implement_binary_operator!(BitWiseLogicalOr, BitWiseLogicalOrTyped);
588implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_integer_value_types!(
589 implement_typed_binary_operator,
590 BitWiseLogicalOrTyped,
591 GrB_BOR
592);
593
594define_binary_operator!(BitWiseLogicalAnd);
595implement_binary_operator!(BitWiseLogicalAnd, BitWiseLogicalAndTyped);
596implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_integer_value_types!(
597 implement_typed_binary_operator,
598 BitWiseLogicalAndTyped,
599 GrB_BAND
600);
601
602define_binary_operator!(BitWiseLogicalExclusiveNotOr);
603implement_binary_operator!(
604 BitWiseLogicalExclusiveNotOr,
605 BitWiseLogicalExclusiveNotOrTyped
606);
607implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_integer_value_types!(
608 implement_typed_binary_operator,
609 BitWiseLogicalExclusiveNotOrTyped,
610 GrB_BXNOR
611);
612
613define_binary_operator!(BitWiseLogicalExclusiveOr);
614implement_binary_operator!(BitWiseLogicalExclusiveOr, BitWiseLogicalExclusiveOrTyped);
615implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_integer_value_types!(
616 implement_typed_binary_operator,
617 BitWiseLogicalExclusiveOrTyped,
618 GrB_BXOR
619);
620
621define_binary_operator!(GetBit);
622implement_binary_operator!(GetBit, GetBitTyped);
623implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_integer_value_types!(
624 implement_typed_binary_operator,
625 GetBitTyped,
626 GxB_BGET
627);
628
629define_binary_operator!(SetBit);
630implement_binary_operator!(SetBit, SetBitTyped);
631implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_integer_value_types!(
632 implement_typed_binary_operator,
633 SetBitTyped,
634 GxB_BSET
635);
636
637define_binary_operator!(ClearBit);
638implement_binary_operator!(ClearBit, ClearBitTyped);
639implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_integer_value_types!(
640 implement_typed_binary_operator,
641 ClearBitTyped,
642 GxB_BCLR
643);
644
645define_binary_operator!(ShiftBit);
647implement_binary_operator!(ShiftBit, ShiftBitTyped);
648implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_integer_value_types!(
649 implement_typed_binary_operator,
650 ShiftBitTyped,
651 GxB_BSHIFT
652);
653
654define_binary_operator!(RowIndexFirstArgument);
655implement_binary_operator!(RowIndexFirstArgument, RowIndexFirstArgumentTyped);
656implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_graphblas_index_integer_value_types!(
657 implement_typed_binary_operator,
658 RowIndexFirstArgumentTyped,
659 GxB_FIRSTI
660);
661
662define_binary_operator!(ColumnIndexFirstArgument);
663implement_binary_operator!(ColumnIndexFirstArgument, ColumnIndexFirstArgumentTyped);
664implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_graphblas_index_integer_value_types!(
665 implement_typed_binary_operator,
666 ColumnIndexFirstArgumentTyped,
667 GxB_FIRSTJ
668);
669
670define_binary_operator!(RowIndexSecondArgument);
671implement_binary_operator!(RowIndexSecondArgument, RowIndexSecondArgumentTyped);
672implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_graphblas_index_integer_value_types!(
673 implement_typed_binary_operator,
674 RowIndexSecondArgumentTyped,
675 GxB_SECONDI
676);
677
678define_binary_operator!(ColumnIndexSecondArgument);
679implement_binary_operator!(ColumnIndexSecondArgument, ColumnIndexSecondArgumentTyped);
680implement_macro_with_1_type_trait_and_typed_graphblas_function_for_all_graphblas_index_integer_value_types!(
681 implement_typed_binary_operator,
682 ColumnIndexSecondArgumentTyped,
683 GxB_SECONDJ
684);
685
686#[cfg(test)]
687mod tests {
688 use crate::{
689 collections::{
690 sparse_matrix::{
691 operations::{FromMatrixElementList, GetSparseMatrixElementValue},
692 MatrixElementList, Size, SparseMatrix,
693 },
694 sparse_scalar::SparseScalar,
695 sparse_vector::{
696 operations::{FromVectorElementList, GetSparseVectorElementValue},
697 SparseVector, VectorElementList,
698 },
699 Collection,
700 },
701 context::Context,
702 operators::{
703 apply::{ApplyBinaryOperatorWithSparseScalar, BinaryOperatorApplier},
704 mask::{SelectEntireMatrix, SelectEntireVector},
705 options::{OperatorOptions, OptionsForOperatorWithMatrixAsFirstArgument},
706 },
707 };
708
709 use super::*;
710
711 #[test]
712 fn new_binary_operator() {
713 let first = First::<bool>::new();
714 let _graphblas_type = first.graphblas_type();
715
716 let plus = Plus::<i8>::new();
717 let _graphblas_type = plus.graphblas_type();
718 }
719
720 #[test]
721 fn test_divide_by_zero() {
722 let context = Context::init_default().unwrap();
723
724 let element_list =
725 VectorElementList::<u8>::from_element_vector(vec![(1, 1).into(), (2, 0).into()]);
726
727 let vector_length: usize = 10;
728 let vector = SparseVector::<u8>::from_element_list(
729 context.clone(),
730 vector_length,
731 element_list,
732 &First::<u8>::new(),
733 )
734 .unwrap();
735
736 let mut product_vector = SparseVector::<u8>::new(context.clone(), vector_length).unwrap();
737
738 let operator = BinaryOperatorApplier::new();
739
740 let second_argument = SparseScalar::<u8>::from_value(context.clone(), 0).unwrap();
741 operator
742 .apply_with_vector_as_left_argument(
743 &vector,
744 &Divide::<u8>::new(),
745 &second_argument,
746 &Assignment::new(),
747 &mut product_vector,
748 &SelectEntireVector::new(context.clone()),
749 &OperatorOptions::new_default(),
750 )
751 .unwrap();
752
753 println!("{}", product_vector);
754 assert_eq!(product_vector.element_value_or_default(1).unwrap(), u8::MAX);
755 assert_eq!(product_vector.element_value(2).unwrap(), Some(0));
756
757 let operator = BinaryOperatorApplier::new();
758
759 let mut product_vector = SparseVector::<f32>::new(context.clone(), vector_length).unwrap();
760 operator
761 .apply_with_vector_as_left_argument(
762 &vector,
763 &Divide::<u8>::new(),
764 &second_argument,
765 &Assignment::new(),
766 &mut product_vector,
767 &SelectEntireVector::new(context.clone()),
768 &OperatorOptions::new_default(),
769 )
770 .unwrap();
771
772 println!("{}", product_vector);
773 assert_eq!(
774 product_vector.element_value_or_default(1).unwrap(),
775 u8::MAX as f32
776 );
777 assert_eq!(product_vector.element_value_or_default(2).unwrap(), 0f32);
778
779 let operator = BinaryOperatorApplier::new();
780 operator
781 .apply_with_vector_as_left_argument(
782 &vector,
783 &Divide::<f32>::new(),
784 &second_argument,
785 &Assignment::new(),
786 &mut product_vector,
787 &SelectEntireVector::new(context.clone()),
788 &OperatorOptions::new_default(),
789 )
790 .unwrap();
791 println!("{}", product_vector);
792 assert_eq!(
793 product_vector.element_value_or_default(1).unwrap(),
794 f32::INFINITY
795 );
796 assert!(f32::is_nan(
797 product_vector.element_value_or_default(2).unwrap()
798 ));
799 }
800
801 #[test]
802 fn test_ldexp_and_type_casting_for_floating_point_operators() {
803 let context = Context::init_default().unwrap();
804
805 let element_list = VectorElementList::<u8>::from_element_vector(vec![
806 (0, 1).into(),
807 (1, 2).into(),
808 (2, 3).into(),
809 ]);
810
811 let vector_length: usize = 10;
812 let vector = SparseVector::<u8>::from_element_list(
813 context.clone(),
814 vector_length,
815 element_list,
816 &First::<u8>::new(),
817 )
818 .unwrap();
819
820 let mut product_vector = SparseVector::<u8>::new(context.clone(), vector_length).unwrap();
821
822 let operator = BinaryOperatorApplier::new();
823
824 let second_argument = SparseScalar::<f32>::from_value(context.clone(), 0.5).unwrap();
825 operator
826 .apply_with_vector_as_left_argument(
827 &vector,
828 &LDExp::<f32>::new(),
829 &second_argument,
830 &Assignment::new(),
831 &mut product_vector,
832 &SelectEntireVector::new(context.clone()),
833 &OperatorOptions::new_default(),
834 )
835 .unwrap();
836
837 println!("{}", product_vector);
838 assert_eq!(product_vector.element_value_or_default(0).unwrap(), 1);
839 assert_eq!(product_vector.element_value_or_default(1).unwrap(), 2);
840 assert_eq!(product_vector.element_value_or_default(2).unwrap(), 3);
841 }
842
843 #[test]
844 fn test_bitshift() {
845 let context = Context::init_default().unwrap();
846
847 let element_list = VectorElementList::<f64>::from_element_vector(vec![
848 (0, u16::MAX as f64).into(),
849 (1, u16::MAX as f64).into(),
850 (2, u16::MAX as f64 + 0.5).into(),
851 ]);
852
853 let vector_length: usize = 10;
854 let vector = SparseVector::<f64>::from_element_list(
855 context.clone(),
856 vector_length,
857 element_list,
858 &First::<f64>::new(),
859 )
860 .unwrap();
861
862 let mut product_vector = SparseVector::<f32>::new(context.clone(), vector_length).unwrap();
863
864 let operator = BinaryOperatorApplier::new();
865
866 for i in 0..3 {
867 let second_argument =
868 SparseScalar::<f32>::from_value(context.clone(), i as f32 + 0.5).unwrap();
869 operator
870 .apply_with_vector_as_left_argument(
871 &vector,
872 &ShiftBit::<u8>::new(),
873 &second_argument,
874 &Assignment::new(),
875 &mut product_vector,
876 &SelectEntireVector::new(context.clone()),
877 &OperatorOptions::new_default(),
878 )
879 .unwrap();
880
881 println!("{}", product_vector);
882 match i {
883 0 => {
884 assert_eq!(product_vector.element_value_or_default(2).unwrap(), 255f32);
885 }
886 1 => {
887 assert_eq!(product_vector.element_value_or_default(2).unwrap(), 254f32);
888 }
889 2 => {
890 assert_eq!(product_vector.element_value_or_default(2).unwrap(), 252f32);
891 }
892 3 => {
893 assert_eq!(product_vector.element_value_or_default(2).unwrap(), 248f32);
894 }
895 _ => {}
896 }
897 }
898 }
899
900 #[test]
901 fn test_index() {
902 let context = Context::init_default().unwrap();
903
904 let element_list = MatrixElementList::<u8>::from_element_vector(vec![
905 (1, 1, 1).into(),
906 (2, 1, 2).into(),
907 (4, 2, 4).into(),
908 (5, 2, 5).into(),
909 ]);
910
911 let matrix_size: Size = (10, 15).into();
912 let matrix = SparseMatrix::<u8>::from_element_list(
913 context.clone(),
914 matrix_size,
915 element_list,
916 &First::<u8>::new(),
917 )
918 .unwrap();
919
920 let mut product_matrix = SparseMatrix::<u8>::new(context.clone(), matrix_size).unwrap();
921
922 let operator = BinaryOperatorApplier::new();
923
924 let second_argument = SparseScalar::<u8>::from_value(context.clone(), 10).unwrap();
925 operator
926 .apply_with_matrix_as_left_argument(
927 &matrix,
928 &RowIndexFirstArgument::<i64>::new(),
929 &second_argument,
930 &Assignment::new(),
931 &mut product_matrix,
932 &SelectEntireMatrix::new(context.clone()),
933 &OptionsForOperatorWithMatrixAsFirstArgument::new_default(),
934 )
935 .unwrap();
936
937 println!("{}", product_matrix);
938
939 assert_eq!(product_matrix.number_of_stored_elements().unwrap(), 4);
940 assert_eq!(product_matrix.element_value_or_default(1, 1).unwrap(), 1);
941 assert_eq!(product_matrix.element_value_or_default(2, 1).unwrap(), 2);
942 assert_eq!(product_matrix.element_value_or_default(4, 2).unwrap(), 4);
943 assert_eq!(product_matrix.element_value_or_default(5, 2).unwrap(), 5);
944 }
945}