oxidd_rules_mtbdd/terminal/
i64.rs

1use std::cmp::Ordering;
2use std::fmt::{self, Display};
3use std::ops::{Add, Div, Mul, Sub};
4use std::str::FromStr;
5
6use oxidd_core::function::NumberBase;
7
8#[derive(Clone, Copy, PartialEq, Eq, Hash)]
9pub enum I64 {
10    NaN,
11    MinusInf,
12    Num(i64),
13    PlusInf,
14}
15
16impl From<i64> for I64 {
17    fn from(value: i64) -> Self {
18        Self::Num(value)
19    }
20}
21
22impl NumberBase for I64 {
23    #[inline]
24    fn zero() -> Self {
25        Self::Num(0)
26    }
27    #[inline]
28    fn one() -> Self {
29        Self::Num(1)
30    }
31    #[inline]
32    fn nan() -> Self {
33        Self::NaN
34    }
35
36    #[inline]
37    fn add(&self, rhs: &Self) -> Self {
38        self + rhs
39    }
40    #[inline]
41    fn sub(&self, rhs: &Self) -> Self {
42        self - rhs
43    }
44    #[inline]
45    fn mul(&self, rhs: &Self) -> Self {
46        self * rhs
47    }
48    #[inline]
49    fn div(&self, rhs: &Self) -> Self {
50        self / rhs
51    }
52}
53
54impl PartialOrd for I64 {
55    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
56        use I64::*;
57        match (self, other) {
58            (Num(lhs), Num(rhs)) => Some(lhs.cmp(rhs)),
59            (NaN, NaN) | (MinusInf, MinusInf) | (PlusInf, PlusInf) => Some(Ordering::Equal),
60            (NaN, _) | (_, NaN) => None,
61            (MinusInf, _) | (_, PlusInf) => Some(Ordering::Less),
62            (_, MinusInf) | (PlusInf, _) => Some(Ordering::Greater),
63        }
64    }
65}
66
67impl<Tag: Default> oxidd_dump::ParseTagged<Tag> for I64 {
68    fn parse(s: &str) -> Option<(Self, Tag)> {
69        let val = match s {
70            "nan" | "NaN" | "NAN" => Self::NaN,
71            "-∞" | "-inf" | "-infinity" | "-Inf" | "-Infinity" | "-INF" | "-INFINITY"
72            | "MinusInf" => Self::MinusInf,
73            "∞" | "inf" | "infinity" | "Inf" | "Infinity" | "INF" | "INFINITY" | "+∞" | "+inf"
74            | "+infinity" | "+Inf" | "+Infinity" | "+INF" | "+INFINITY" | "PlusInf" => {
75                Self::PlusInf
76            }
77            _ => Self::Num(i64::from_str(s).ok()?),
78        };
79        Some((val, Tag::default()))
80    }
81}
82
83impl Display for I64 {
84    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85        match self {
86            I64::NaN => f.write_str("NaN"),
87            I64::MinusInf => f.write_str("-∞"),
88            I64::Num(n) => n.fmt(f),
89            I64::PlusInf => f.write_str("+∞"),
90        }
91    }
92}
93impl fmt::Debug for I64 {
94    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95        Display::fmt(self, f)
96    }
97}
98
99impl oxidd_dump::AsciiDisplay for I64 {
100    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101        match self {
102            I64::NaN => f.write_str("NaN"),
103            I64::MinusInf => f.write_str("-Inf"),
104            I64::Num(n) => n.fmt(f),
105            I64::PlusInf => f.write_str("+Inf"),
106        }
107    }
108}
109
110impl Add for I64 {
111    type Output = I64;
112
113    #[inline]
114    fn add(self, rhs: Self) -> I64 {
115        use I64::*;
116        match (self, rhs) {
117            (Num(lhs), Num(rhs)) => match lhs.checked_add(rhs) {
118                Some(n) => Num(n),
119                None => {
120                    if lhs > 0 && rhs > 0 || lhs < 0 && rhs < 0 {
121                        PlusInf
122                    } else {
123                        MinusInf
124                    }
125                }
126            },
127            (NaN, _) | (_, NaN) | (MinusInf, PlusInf) | (PlusInf, MinusInf) => NaN,
128            (MinusInf, _) | (_, MinusInf) => MinusInf,
129            (PlusInf, _) | (_, PlusInf) => PlusInf,
130        }
131    }
132}
133
134impl Sub for I64 {
135    type Output = I64;
136
137    #[inline]
138    fn sub(self, rhs: Self) -> I64 {
139        use I64::*;
140        match (self, rhs) {
141            (Num(lhs), Num(rhs)) => match lhs.checked_sub(rhs) {
142                Some(n) => Num(n),
143                None => {
144                    if lhs > 0 && rhs < 0 || lhs < 0 && rhs > 0 {
145                        PlusInf
146                    } else {
147                        MinusInf
148                    }
149                }
150            },
151            (NaN, _) | (_, NaN) | (MinusInf, MinusInf) | (PlusInf, PlusInf) => NaN,
152            (MinusInf, _) | (_, PlusInf) => MinusInf,
153            (PlusInf, _) | (_, MinusInf) => PlusInf,
154        }
155    }
156}
157
158impl Mul for I64 {
159    type Output = I64;
160
161    #[inline]
162    fn mul(self, rhs: Self) -> I64 {
163        use I64::*;
164        match (self, rhs) {
165            (Num(lhs), Num(rhs)) => match lhs.checked_mul(rhs) {
166                Some(n) => Num(n),
167                None => {
168                    if lhs > 0 && rhs > 0 || lhs < 0 && rhs < 0 {
169                        PlusInf
170                    } else {
171                        MinusInf
172                    }
173                }
174            },
175            (NaN, _) | (_, NaN) | (MinusInf, PlusInf) | (PlusInf, MinusInf) => NaN,
176            (MinusInf, _) | (_, MinusInf) => MinusInf,
177            (PlusInf, _) | (_, PlusInf) => PlusInf,
178        }
179    }
180}
181
182impl Div for I64 {
183    type Output = I64;
184
185    #[inline]
186    fn div(self, rhs: Self) -> I64 {
187        use I64::*;
188        match (self, rhs) {
189            (Num(lhs), Num(rhs)) => {
190                if rhs == 0 {
191                    match lhs.cmp(&0) {
192                        Ordering::Less => MinusInf,
193                        Ordering::Equal => NaN,
194                        Ordering::Greater => PlusInf,
195                    }
196                } else if lhs == i64::MIN && rhs == -1 {
197                    PlusInf
198                } else {
199                    Num(lhs / rhs)
200                }
201            }
202            (Num(_), MinusInf | PlusInf) => Num(0),
203            (PlusInf, Num(_)) => PlusInf,
204            (MinusInf, Num(_)) => MinusInf,
205            _ => NaN,
206        }
207    }
208}
209
210super::impl_ref_op!(I64, Add, add);
211super::impl_ref_op!(I64, Sub, sub);
212super::impl_ref_op!(I64, Mul, mul);
213super::impl_ref_op!(I64, Div, div);