computable_real/
traits.rs1use super::{Primitive, Real};
2use num::bigint::ParseBigIntError;
3use num::{BigInt, BigRational, Num, One, Signed, ToPrimitive, Zero};
4use std::cmp::Ordering;
5use std::convert::{From, Into};
6use std::ops::{Add, Div, Mul, Neg, Rem, Sub};
7use std::str::FromStr;
8
9impl PartialEq for Real {
10 fn eq(&self, other: &Self) -> bool {
11 self.cmp(other) == Ordering::Equal
12 }
13}
14
15impl Eq for Real {}
16
17impl PartialOrd for Real {
18 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
19 Some(self.cmp(other))
20 }
21}
22
23impl Ord for Real {
24 fn cmp(&self, other: &Self) -> Ordering {
25 self.cmp_until(other, super::CMP_MIN_PRECISION)
26 }
27}
28
29impl Add for Real {
30 type Output = Self;
31
32 fn add(self, rhs: Self) -> Self {
33 Self::new(Primitive::Add(self, rhs))
34 }
35}
36
37impl Neg for Real {
38 type Output = Self;
39
40 fn neg(self) -> Self {
41 Self::new(Primitive::Neg(self))
42 }
43}
44
45impl Sub for Real {
46 type Output = Self;
47
48 fn sub(self, rhs: Self) -> Self {
49 self + -rhs
50 }
51}
52
53impl Mul for Real {
54 type Output = Self;
55
56 fn mul(self, rhs: Self) -> Self {
57 Self::new(Primitive::Mul(self, rhs))
58 }
59}
60
61impl Div for Real {
62 type Output = Self;
63
64 fn div(self, rhs: Self) -> Self {
65 self * Real::new(Primitive::Inv(rhs))
66 }
67}
68
69impl Rem for Real {
70 type Output = Self;
71
72 fn rem(self, rhs: Self) -> Self {
73 let lhs: BigInt = self.into();
74 let rhs: BigInt = rhs.into();
75 Real::int(lhs % rhs)
76 }
77}
78
79impl From<BigInt> for Real {
80 fn from(value: BigInt) -> Self {
81 Real::int(value)
82 }
83}
84
85impl From<i32> for Real {
86 fn from(value: i32) -> Self {
87 Real::int(value.into())
88 }
89}
90
91impl From<BigRational> for Real {
92 fn from(value: BigRational) -> Self {
93 Real::int(value.numer().clone()) / Real::int(value.denom().clone())
94 }
95}
96
97impl From<f64> for Real {
98 fn from(value: f64) -> Self {
99 let bits = value.abs().to_bits() as i64;
100 let mut mantissa = bits & ((1 << 52) - 1);
101 let biased_exponent = (bits >> 52) as i32;
102 let exponent = biased_exponent - 1075;
105 match biased_exponent {
106 0 => {
107 mantissa <<= 1;
108 }
109 _ => {
110 mantissa += 1 << 52;
111 }
112 }
113 let res = Real::int(mantissa.into()).shifted(exponent);
114 if value < 0.0 {
115 -res
116 } else {
117 res
118 }
119 }
120}
121
122impl Into<f64> for Real {
123 fn into(mut self) -> f64 {
124 let msd = self.iter_msd_n(-1080);
126 if msd.is_none() {
127 return 0.0;
129 }
130 let prec = msd.unwrap() - 60;
131 let value = self.appr(prec).value.to_f64().unwrap();
132 let may_underflow = prec < -1000;
133 let mut bits = value.to_bits() as i64;
134 let exp_adj = (if may_underflow { prec + 96 } else { prec }) as i64;
135 let exp = (bits >> 52) & 0x7ff;
136
137 if exp + exp_adj >= 0x7ff {
138 return if value.is_sign_positive() {
139 f64::INFINITY
140 } else {
141 f64::NEG_INFINITY
142 };
143 }
144
145 bits += exp_adj << 52;
146 let res = f64::from_bits(bits as u64);
147
148 if may_underflow {
149 let two_48 = (1_u64 << 48) as f64;
152 res / two_48 / two_48
153 } else {
154 res
155 }
156 }
157}
158
159impl Into<BigInt> for Real {
160 fn into(mut self) -> BigInt {
161 self.appr(0).value
162 }
163}
164
165impl One for Real {
166 fn one() -> Self {
167 1.into()
168 }
169}
170
171impl Zero for Real {
172 fn zero() -> Self {
173 0.into()
174 }
175
176 fn is_zero(&self) -> bool {
177 self == &Real::zero()
178 }
179}
180
181impl Num for Real {
182 type FromStrRadixErr = ParseBigIntError;
183
184 fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
185 let len = str.trim().len();
186 let frac_len = match str.find('.') {
187 Some(i) => len - i - 1,
188 None => 0,
189 };
190 let removed_dot = str.replace(".", "");
191 let int = BigInt::from_str_radix(&removed_dot, radix)?;
192 let div = BigInt::from(radix).pow(frac_len as u32);
193 Ok(Real::int(int) / Real::int(div))
194 }
195}
196
197impl FromStr for Real {
198 type Err = ParseBigIntError;
199
200 fn from_str(str: &str) -> Result<Self, Self::Err> {
201 Real::from_str_radix(str, 10)
202 }
203}
204
205impl Signed for Real {
206 fn abs(&self) -> Self {
207 self.clone() * self.signum()
208 }
209
210 fn abs_sub(&self, other: &Self) -> Self {
211 if self < other {
212 Real::zero()
213 } else {
214 self.clone() - other.clone()
215 }
216 }
217
218 fn signum(&self) -> Self {
219 let mut a = -16;
220 loop {
221 let sign = self.signum_a(a);
222 if sign != 0 || a < super::CMP_MIN_PRECISION {
223 return sign.into();
224 }
225 a *= 2;
226 }
227 }
228
229 fn is_positive(&self) -> bool {
230 self > &Real::zero()
231 }
232
233 fn is_negative(&self) -> bool {
234 self < &Real::zero()
235 }
236}