rsdiff_core/ops/kinds/binary/
mod.rs1pub use self::{args::*, arithmetic::*, specs::*};
6
7pub(crate) mod args;
8pub(crate) mod arithmetic;
9pub(crate) mod specs;
10
11use crate::ops::{Binary, Evaluate, Operand};
12use smart_default::SmartDefault;
13use strum::{AsRefStr, Display, EnumCount, EnumIs, EnumIter, EnumString, VariantNames};
14
15impl<O, P, A, B> Evaluate<P> for O
16where
17 O: BinOp<A, B> + Operand<Kind = Binary>,
18 P: BinaryParams<Lhs = A, Rhs = B>,
19{
20 type Output = <O as BinOp<A, B>>::Output;
21
22 fn eval(&self, args: P) -> Self::Output {
23 let (lhs, rhs) = args.into_pattern();
24 BinOp::eval(self, lhs, rhs)
25 }
26}
27
28#[derive(
29 AsRefStr,
30 Clone,
31 Copy,
32 Debug,
33 Display,
34 EnumCount,
35 EnumIs,
36 EnumIter,
37 EnumString,
38 Eq,
39 Hash,
40 Ord,
41 PartialEq,
42 PartialOrd,
43 SmartDefault,
44 VariantNames,
45)]
46#[cfg_attr(
47 feature = "serde",
48 derive(serde::Deserialize, serde::Serialize),
49 serde(rename_all = "lowercase", untagged)
50)]
51#[non_exhaustive]
52#[repr(C)]
53#[strum(serialize_all = "lowercase")]
54pub enum BinaryOp {
55 #[default]
57 Arith(Arithmetic),
58 ArithAssign(ArithmeticAssign),
59 Max,
60 Min,
61 And,
62 Or,
63 Xor,
64 Shl,
65 Shr,
66 }
68
69impl BinaryOp {
70 pub fn differentiable(&self) -> bool {
71 match self {
72 Self::Arith(_) | Self::ArithAssign(_) => true,
73 _ => false,
74 }
75 }
76
77 pub fn is_commutative(&self) -> bool {
78 match self {
79 Self::Arith(arith) => arith.is_commutative(),
80 BinaryOp::And | BinaryOp::Or | BinaryOp::Xor => true,
81 _ => false,
82 }
83 }
84 nested_constructor!(
85 Arith<Arithmetic>,
86 arithmetic,
87 [add, div, mul, pow, rem, sub]
88 );
89
90 nested_constructor!(
91 ArithAssign<ArithmeticAssign>,
92 arithmetic_assign,
93 [add_assign, div_assign, mul_assign, rem_assign, sub_assign]
94 );
95
96 variant_constructor!(
100 (Max, max),
101 (Min, min),
102 (And, bitand),
103 (Or, bitor),
104 (Xor, bitxor),
105 (Shl, shl),
106 (Shr, shr)
107 );
108}
109
110impl Operand for BinaryOp {
111 type Kind = Binary;
112
113 fn name(&self) -> &str {
114 match self {
115 Self::Arith(inner) => inner.name(),
116 Self::ArithAssign(inner) => inner.name(),
117 Self::Max => "max",
118 Self::Min => "min",
119 Self::And => "and",
120 Self::Or => "or",
121 Self::Xor => "xor",
122 Self::Shl => "shl",
123 Self::Shr => "shr",
124 }
125 }
126
127 fn optype(&self) -> Self::Kind {
128 Binary
129 }
130}