rsdiff_core/ops/kinds/binary/
mod.rs

1/*
2   Appellation: binary <mod>
3   Contrib: FL03 <jo3mccain@icloud.com>
4*/
5pub 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    // <Kind = String> {
56    #[default]
57    Arith(Arithmetic),
58    ArithAssign(ArithmeticAssign),
59    Max,
60    Min,
61    And,
62    Or,
63    Xor,
64    Shl,
65    Shr,
66    // Custom()
67}
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    // simple_enum_constructor!(
97    //     st Custom, custom, { id: usize }
98    // );
99    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}