suan_core/
operator.rs

1//! Implementation of unary and binary operators.
2
3// Full equality and total ordering is implemented to support sorting with following strategy
4// 1. Lexicographic ordering is used between Complex numbers
5// 2. All numbers are (virtually) converted to a complex number when comparing
6// But other binary operators will panic if two operands are not compatible
7
8use num_order::{NumOrd, NumHash};
9use num_rational::{BigRational, Rational64};
10use num_traits::ToPrimitive;
11
12use crate::subject::Subject::{self, *};
13use std::cmp::Ordering;
14use std::ops::{Add, Sub, Mul, Div};
15use std::hash::Hash;
16
17impl PartialEq for Subject {
18    fn eq(&self, other: &Self) -> bool {
19        match (self, other) {
20            // comparison with infinity
21            (Infinity(true), Infinity(true)) => true,
22            (Infinity(false), Infinity(false)) => true,
23            (Infinity(true), _) => false,
24            (Infinity(false), _) => false,
25            (_, Infinity(true)) => false,
26            (_, Infinity(false)) => false,
27
28            // comparison with concrete types
29            (Int(l), Int(r)) => l.num_eq(r),
30            (Int(l), BInt(r)) => l.num_eq(r),
31            (Int(l), Real(r)) => l.num_eq(r),
32            (Int(l), Complex(r)) => l.num_eq(r),
33            (BInt(l), BInt(r)) => l.num_eq(r),
34            (BInt(l), Int(r)) => l.num_eq(r),
35            (Real(l), Int(r)) => l.num_eq(r),
36            (Real(l), Real(r)) => l.num_eq(r),
37            _ => unimplemented!(),
38        }
39    }
40}
41
42impl Eq for Subject {}
43
44impl PartialOrd for Subject {
45    #[inline]
46    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
47        Some(self.cmp(other))
48    }
49}
50
51impl Ord for Subject {
52    #[inline]
53    fn cmp(&self, other: &Self) -> Ordering {
54        match (self, other) {
55            // comparison with infinity
56            (Infinity(true), Infinity(true)) => Ordering::Equal,
57            (Infinity(true), Infinity(false)) => Ordering::Greater,
58            (Infinity(false), Infinity(true)) => Ordering::Less,
59            (Infinity(false), Infinity(false)) => Ordering::Equal,
60            (Infinity(true), _) => Ordering::Greater,
61            (Infinity(false), _) => Ordering::Less,
62            (_, Infinity(true)) => Ordering::Less,
63            (_, Infinity(false)) => Ordering::Greater,
64
65            // comparison with concrete types
66            (Int(l), Int(r)) => l.num_cmp(r),
67            (Int(l), BInt(r)) => l.num_cmp(r),
68            (Int(l), Real(r)) => l.num_cmp(r),
69            (Int(l), Complex(r)) => l.num_cmp(r),
70            (BInt(l), BInt(r)) => l.num_cmp(r),
71            (BInt(l), Int(r)) => l.num_cmp(r),
72            (BInt(l), Real(r)) => l.num_cmp(r),
73            (BInt(l), Complex(r)) => l.num_cmp(r),
74            (Real(l), Int(r)) => l.num_cmp(r),
75            (Real(l), BInt(r)) => l.num_cmp(r),
76            (Real(l), Real(r)) => l.num_cmp(r),
77            (Real(l), Complex(r)) => l.num_cmp(r),
78            _ => unimplemented!(),
79        }
80    }
81}
82
83impl Hash for Subject {
84    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
85        match self {
86            Int(v) => v.num_hash(state),
87            BInt(v) => v.num_hash(state),
88            Rational(v) => v.num_hash(state),
89            BRational(v) => v.num_hash(state),
90            Real(v) => v.num_hash(state),
91            Complex(v) => v.num_hash(state),
92            _ => unimplemented!()
93        }
94    }
95}
96
97impl Add for Subject {
98    type Output = Self;
99    #[inline]
100    fn add(self, rhs: Self) -> Self::Output {
101        match (self, rhs) {
102            (_, Infinity(_)) | (Infinity(_), _) => panic!("operation with infinity is prohibited!"),
103            (Int(l), Int(r)) => (l + r).into(),
104            (Int(l), BInt(r)) => (l + r).into(),
105            (Int(l), Real(r)) => (l as f64 + r).into(),
106            (Int(l), Complex(r)) => (l as f64 + r).into(),
107            (BInt(l), Int(r)) => (l + r).into(),
108            (BInt(l), BInt(r)) => (l + r).into(),
109            (BInt(l), Real(r)) => (l.to_f64().unwrap() + r).into(),
110            (BInt(l), Complex(r)) => (l.to_f64().unwrap() + r).into(),
111            (Real(l), Int(r)) => (l + r as f64).into(),
112            (Real(l), BInt(r)) => (l + r.to_f64().unwrap()).into(),
113            (Real(l), Real(r)) => (l + r).into(),
114            (Real(l), Complex(r)) => (l + r).into(),
115            (Complex(l), Int(r)) => (l + r as f64).into(),
116            (Complex(l), BInt(r)) => (l + r.to_f64().unwrap()).into(),
117            (Complex(l), Real(r)) => (l + r).into(),
118            (Complex(l), Complex(r)) => (l + r).into(),
119            _ => unimplemented!(),
120        }
121    }
122}
123
124impl Sub for Subject {
125    type Output = Self;
126    #[inline]
127    fn sub(self, rhs: Self) -> Self::Output {
128        match (self, rhs) {
129            (_, Infinity(_)) | (Infinity(_), _) => panic!("operation with infinity is prohibited!"),
130            (Int(l), Int(r)) => (l - r).into(),
131            (Int(l), BInt(r)) => (l - r).into(),
132            (Int(l), Real(r)) => (l as f64 - r).into(),
133            (Int(l), Complex(r)) => (l as f64 - r).into(),
134            _ => unimplemented!(),
135        }
136    }
137}
138
139impl Mul for Subject {
140    type Output = Self;
141    #[inline]
142    fn mul(self, rhs: Self) -> Self::Output {
143        match (self, rhs) {
144            (_, Infinity(_)) | (Infinity(_), _) => panic!("operation with infinity is prohibited!"),
145            (Int(l), Int(r)) => (l * r).into(),
146            (Int(l), BInt(r)) => (l * r).into(),
147            (Int(l), Real(r)) => (l as f64 * r).into(),
148            (Int(l), Complex(r)) => (l as f64 * r).into(),
149            _ => unimplemented!(),
150        }
151    }
152}
153
154impl Div for Subject {
155    type Output = Self;
156    #[inline]
157    fn div(self, rhs: Self) -> Self::Output {
158        match (self, rhs) {
159            (_, Infinity(_)) | (Infinity(_), _) => panic!("operation with infinity is prohibited!"),
160            (Int(l), Int(r)) => Rational64::new(l, r).into(),
161            (Int(l), BInt(r)) => BigRational::new(l.into(), r.clone()).into(),
162            (Int(l), Real(r)) => (l as f64 / r).into(),
163            (Int(l), Complex(r)) => (l as f64 / r).into(),
164            (BInt(l), Int(r)) => BigRational::new(l.clone(), r.into()).into(),
165            (BInt(l), BInt(r)) => BigRational::new(l.clone(), r.clone()).into(),
166            (BInt(l), Real(r)) => (l.to_f64().unwrap() / r).into(),
167            (BInt(l), Complex(r)) => (l.to_f64().unwrap() / r).into(),
168            (Real(l), Int(r)) => (l / r as f64).into(),
169            (Real(l), BInt(r)) => (l / r.to_f64().unwrap()).into(),
170            (Real(l), Real(r)) => (l / r).into(),
171            (Real(l), Complex(r)) => (l.to_f64().unwrap() / r).into(),
172            (Complex(l), Int(r)) => (l / r as f64).into(),
173            (Complex(l), BInt(r)) => (l / r.to_f64().unwrap()).into(),
174            (Complex(l), Real(r)) => (l / r).into(),
175            (Complex(l), Complex(r)) => (l / r).into(),
176            _ => unimplemented!(),
177        }
178    }
179}