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}