rooc/math/
operators.rs

1use core::fmt;
2use std::str::FromStr;
3
4#[allow(unused_imports)]
5use crate::prelude::*;
6#[allow(unused_imports)]
7use serde::{Deserialize, Serialize};
8
9use crate::enum_with_variants_to_string;
10use crate::traits::ToLatex;
11
12enum_with_variants_to_string! {
13    pub enum Operator derives[Debug, PartialEq, Clone, Copy] with_wasm {
14        Add,
15        Sub,
16        Mul,
17        Div,
18        Neg,
19    }
20}
21impl Operator {
22    /// Returns the precedence level of the operator.
23    ///
24    /// Higher precedence values indicate that the operator should be evaluated first.
25    pub fn precedence(&self) -> u8 {
26        match self {
27            Operator::Add | Operator::Sub => 1,
28            Operator::Mul | Operator::Div => 2,
29            Operator::Neg => 3,
30        }
31    }
32
33    /// Determines if the operator is left associative.
34    ///
35    /// Left associative operators are evaluated from left to right.
36    /// For example, a - b - c is evaluated as (a - b) - c.
37    pub fn is_left_associative(&self) -> bool {
38        match self {
39            Operator::Add | Operator::Sub | Operator::Mul | Operator::Div => true,
40            Operator::Neg => false,
41        }
42    }
43}
44
45impl fmt::Display for Operator {
46    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47        let s = match self {
48            Operator::Add => "+".to_string(),
49            Operator::Sub => "-".to_string(),
50            Operator::Mul => "*".to_string(),
51            Operator::Div => "/".to_string(),
52            Operator::Neg => "-".to_string(),
53        };
54
55        f.write_str(&s)
56    }
57}
58
59enum_with_variants_to_string! {
60    pub enum BinOp derives[Debug, PartialEq, Clone, Copy] with_wasm {
61        Add,
62        Sub,
63        Mul,
64        Div,
65        //And
66        //Or
67        //Not
68        //Xor
69    }
70}
71
72impl BinOp {
73    /// Returns the precedence level of the binary operator.
74    pub fn precedence(&self) -> u8 {
75        match self {
76            BinOp::Add | BinOp::Sub => 1,
77            BinOp::Mul | BinOp::Div => 2,
78        }
79    }
80
81    /// Determines if the binary operator is left associative.
82    pub fn is_left_associative(&self) -> bool {
83        match self {
84            BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div => true,
85        }
86    }
87
88    /// Converts a binary operator to the corresponding general Operator enum.
89    pub fn to_operator(&self) -> Operator {
90        match self {
91            BinOp::Add => Operator::Add,
92            BinOp::Sub => Operator::Sub,
93            BinOp::Mul => Operator::Mul,
94            BinOp::Div => Operator::Div,
95        }
96    }
97}
98
99impl ToLatex for BinOp {
100    fn to_latex(&self) -> String {
101        match self {
102            BinOp::Add => "+".to_string(),
103            BinOp::Sub => "-".to_string(),
104            BinOp::Mul => "\\cdot".to_string(),
105            BinOp::Div => "\\div".to_string(),
106        }
107    }
108}
109
110impl fmt::Display for BinOp {
111    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112        let s = match self {
113            BinOp::Add => "+".to_string(),
114            BinOp::Sub => "-".to_string(),
115            BinOp::Mul => "*".to_string(),
116            BinOp::Div => "/".to_string(),
117        };
118
119        f.write_str(&s)
120    }
121}
122
123impl FromStr for BinOp {
124    type Err = ();
125    fn from_str(s: &str) -> Result<Self, Self::Err> {
126        match s {
127            "+" => Ok(BinOp::Add),
128            "-" => Ok(BinOp::Sub),
129            "*" => Ok(BinOp::Mul),
130            "/" => Ok(BinOp::Div),
131            _ => Err(()),
132        }
133    }
134}
135
136enum_with_variants_to_string! {
137    pub enum UnOp derives[Debug, PartialEq, Clone, Copy] with_wasm {
138        Neg,
139    }
140}
141
142impl UnOp {
143    /// Returns the precedence level of the unary operator.
144    pub fn precedence(&self) -> u8 {
145        match self {
146            UnOp::Neg => 3,
147        }
148    }
149
150    /// Determines if the unary operator is left associative.
151    pub fn is_left_associative(&self) -> bool {
152        match self {
153            UnOp::Neg => false,
154        }
155    }
156
157    /// Converts a unary operator to the corresponding general Operator enum.
158    pub fn to_operator(&self) -> Operator {
159        match self {
160            UnOp::Neg => Operator::Neg,
161        }
162    }
163}
164
165impl ToLatex for UnOp {
166    fn to_latex(&self) -> String {
167        match self {
168            UnOp::Neg => "-".to_string(),
169        }
170    }
171}
172
173impl fmt::Display for UnOp {
174    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175        let s = match self {
176            UnOp::Neg => "-".to_string(),
177        };
178
179        f.write_str(&s)
180    }
181}
182
183impl FromStr for UnOp {
184    type Err = ();
185    fn from_str(s: &str) -> Result<Self, Self::Err> {
186        match s {
187            "-" => Ok(UnOp::Neg),
188            _ => Err(()),
189        }
190    }
191}