surreal/repr/mod.rs
1use std::cmp::Ordering;
2use std::fmt;
3use std::ops;
4
5mod arith;
6mod order;
7
8/// A struct to represent surreal numbers with non-infinite sets.
9#[derive(Debug, Clone)]
10pub struct Surreal {
11 left: Vec<Surreal>,
12 right: Vec<Surreal>,
13}
14
15impl Surreal {
16 /// Creates a new surreal number given two vectors of references to surreal numbers. Each
17 /// vector corresponds to a left set and a right set, where each number in the left set must
18 /// be less than all numbers in the right set.
19 ///
20 /// # Panics
21 ///
22 /// Panics if any `Surreal` in `left` is greater than or equal to any `Surreal` in `right`.
23 ///
24 /// # Examples
25 ///
26 /// ```
27 /// let zero = surreal::Surreal::new(vec![], vec![]);
28 /// let one = surreal::Surreal::new(vec![&zero], vec![]);
29 /// let neg_one = surreal::Surreal::new(vec![], vec![&zero]);
30 /// ```
31 pub fn new(left: Vec<&Surreal>, right: Vec<&Surreal>) -> Surreal {
32 for xl in &left {
33 for xr in &right {
34 if order::leq(xr, xl) {
35 panic!("Items in the left set must be less than items in the right set");
36 }
37 }
38 }
39
40 Surreal {
41 left: order::cnv(left),
42 right: order::cnv(right),
43 }
44 }
45
46 /// Creates a new pseudo-surreal number given two vectors of references to surreal numbers.
47 /// While each vector still corresponds to a left set and a right set, each number in the left
48 /// set doesn't have to be less than all numbers in the right set.
49 ///
50 /// # Examples
51 ///
52 /// ```
53 /// let zero = surreal::Surreal::new(vec![], vec![]);
54 /// let pseudo = surreal::Surreal::pseudo(vec![&zero], vec![&zero]);
55 /// ```
56 pub fn pseudo(left: Vec<&Surreal>, right: Vec<&Surreal>) -> Surreal {
57 Surreal {
58 left: order::cnv(left),
59 right: order::cnv(right),
60 }
61 }
62
63 /// Returns the left set of a surreal number (as a `Vec<Surreal>` instead of a
64 /// `Vec<&Surreal>`).
65 ///
66 /// # Examples
67 ///
68 /// ```
69 /// let zero = surreal::Surreal::new(vec![], vec![]);
70 /// let one = surreal::Surreal::new(vec![&zero], vec![]);
71 ///
72 /// assert!(zero.left().is_empty());
73 /// assert!(one.left()[0] == zero);
74 /// ```
75 pub fn left(&self) -> Vec<Surreal> {
76 self.left.clone()
77 }
78
79 /// Returns the right set of a surreal number (as a `Vec<Surreal>` instead of a
80 /// `Vec<&Surreal>`).
81 ///
82 /// # Examples
83 ///
84 /// ```
85 /// let zero = surreal::Surreal::new(vec![], vec![]);
86 /// let neg_one = surreal::Surreal::new(vec![], vec![&zero]);
87 ///
88 /// assert!(zero.right().is_empty());
89 /// assert!(neg_one.right()[0] == zero);
90 /// ```
91 pub fn right(&self) -> Vec<Surreal> {
92 self.right.clone()
93 }
94}
95
96impl PartialEq for Surreal {
97 fn eq(&self, other: &Surreal) -> bool {
98 order::leq(self, other) && order::leq(other, self)
99 }
100}
101
102impl Eq for Surreal {}
103
104impl PartialOrd for Surreal {
105 fn partial_cmp(&self, other: &Surreal) -> Option<Ordering> {
106 if !order::leq(self, other) {
107 Some(Ordering::Greater)
108 } else if !order::leq(other, self) {
109 Some(Ordering::Less)
110 } else {
111 Some(Ordering::Equal)
112 }
113 }
114}
115
116impl<'a, 'b> ops::Add<&'b Surreal> for &'a Surreal {
117 type Output = Surreal;
118
119 fn add(self, other: &'b Surreal) -> Surreal {
120 arith::add(self, other)
121 }
122}
123
124/// **Note**: Currently, division does not work for numbers created on or after day 4, i.e. numbers
125/// with 4 or more layers of nested sets.
126///
127/// # Panics
128///
129/// Panics if the divisor is zero. Panics if the quotient will have infinite sets.
130impl<'a, 'b> ops::Div<&'b Surreal> for &'a Surreal {
131 type Output = Surreal;
132
133 fn div(self, other: &'b Surreal) -> Surreal {
134 let zero = Surreal::new(vec![], vec![]);
135
136 if other == &zero {
137 panic!("Cannot divide by zero");
138 } else if (super::stof(self) / super::stof(other)).fract() * 256.0 % 1.0 != 0.0 {
139 panic!("Quotient will have infinite sets"); // isn't representable as finite f32
140 }
141
142 arith::mul(self, &arith::inv(other))
143 }
144}
145
146/// **Note**: Currently, multiplication does not work for numbers created on or after day 4, i.e.
147/// numbers with 4 or more layers of nested sets.
148impl<'a, 'b> ops::Mul<&'b Surreal> for &'a Surreal {
149 type Output = Surreal;
150
151 fn mul(self, other: &'b Surreal) -> Surreal {
152 arith::mul(self, other)
153 }
154}
155
156impl<'a> ops::Neg for &'a Surreal {
157 type Output = Surreal;
158
159 fn neg(self) -> Surreal {
160 arith::neg(self)
161 }
162}
163
164impl<'a, 'b> ops::Sub<&'b Surreal> for &'a Surreal {
165 type Output = Surreal;
166
167 fn sub(self, other: &'b Surreal) -> Surreal {
168 arith::add(self, &arith::neg(other))
169 }
170}
171
172impl fmt::Display for Surreal {
173 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
174 write!(f, "{:#?}", self) // alias to debug print
175 }
176}
177
178/// Tests if a division will produce a result with finite sets. Useful in making sure a division of
179/// surreal numbers won't panic.
180///
181/// # Examples
182///
183/// ```
184/// let zero = surreal::Surreal::new(vec![], vec![]);
185/// let one = surreal::Surreal::new(vec![], vec![&zero]);
186///
187/// if surreal::is_divisible(&zero, &one) {
188/// println!("{}", &zero / &one);
189/// }
190pub fn is_divisible(x: &Surreal, y: &Surreal) -> bool {
191 (super::stof(&x) / super::stof(&y)).fract() * 256.0 % 1.0 == 0.0
192}
193
194/// Tests if a given input is a pseudo-surreal number (created with `surreal::Surreal::pseudo`).
195///
196/// # Examples
197///
198/// ```
199/// let zero = surreal::Surreal::new(vec![], vec![]);
200/// assert!(!surreal::is_pseudo(&zero));
201///
202/// let some_pseudo = surreal::Surreal::pseudo(vec![&zero], vec![&zero]);
203/// assert!(surreal::is_pseudo(&some_pseudo));
204/// ```
205pub fn is_pseudo(sur: &Surreal) -> bool {
206 let mut res = false;
207
208 for xl in sur.left() {
209 for xr in sur.right() {
210 if xl >= xr {
211 res = true;
212 }
213 }
214 }
215
216 res
217}