oxidd_rules_mtbdd/terminal/
i64.rs1use 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);