acme_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::{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    Clone,
30    Copy,
31    Debug,
32    Display,
33    EnumCount,
34    EnumIs,
35    EnumIter,
36    EnumString,
37    Eq,
38    Hash,
39    Ord,
40    PartialEq,
41    PartialOrd,
42    SmartDefault,
43    VariantNames,
44)]
45#[cfg_attr(
46    feature = "serde",
47    derive(serde::Deserialize, serde::Serialize),
48    serde(rename_all = "lowercase", untagged)
49)]
50#[non_exhaustive]
51#[repr(C)]
52#[strum(serialize_all = "lowercase")]
53pub enum BinaryOp {
54    // <Kind = String> {
55    #[default]
56    Arith(Arithmetic),
57    ArithAssign(ArithmeticAssign),
58    Max,
59    Min,
60    And,
61    Or,
62    Xor,
63    Shl,
64    Shr,
65    // Custom()
66}
67
68impl BinaryOp {
69    pub fn differentiable(&self) -> bool {
70        match self {
71            Self::Arith(_) | Self::ArithAssign(_) => true,
72            _ => false,
73        }
74    }
75
76    pub fn is_commutative(&self) -> bool {
77        match self {
78            Self::Arith(arith) => arith.is_commutative(),
79            BinaryOp::And | BinaryOp::Or | BinaryOp::Xor => true,
80            _ => false,
81        }
82    }
83    nested_constructor!(
84        Arith<Arithmetic>,
85        arithmetic,
86        [add, div, mul, pow, rem, sub]
87    );
88
89    nested_constructor!(
90        ArithAssign<ArithmeticAssign>,
91        arithmetic_assign,
92        [add_assign, div_assign, mul_assign, rem_assign, sub_assign]
93    );
94
95    // simple_enum_constructor!(
96    //     st Custom, custom, { id: usize }
97    // );
98    variant_constructor!(
99        (Max, max),
100        (Min, min),
101        (And, bitand),
102        (Or, bitor),
103        (Xor, bitxor),
104        (Shl, shl),
105        (Shr, shr)
106    );
107}
108
109impl Operand for BinaryOp {
110    type Kind = Binary;
111
112    fn name(&self) -> &str {
113        match self {
114            Self::Arith(inner) => inner.name(),
115            Self::ArithAssign(inner) => inner.name(),
116            Self::Max => "max",
117            Self::Min => "min",
118            Self::And => "and",
119            Self::Or => "or",
120            Self::Xor => "xor",
121            Self::Shl => "shl",
122            Self::Shr => "shr",
123        }
124    }
125
126    fn optype(&self) -> Self::Kind {
127        Binary
128    }
129}