1use super::{Approx, Primitive};
2use num::bigint::Sign;
3use num::{BigInt, One, Signed, ToPrimitive};
4use std::cmp::Ordering;
5use std::fmt::{self, Debug, Formatter};
6
7#[derive(Clone)]
14pub struct Real {
15 pub prim: Box<Primitive>,
16 pub approx: Option<Approx>,
17}
18
19impl Debug for Real {
20 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
21 write!(f, "{:?}", self.prim)
22 }
23}
24
25const LN_MIN: i32 = 8; const LN_MAX: i32 = 24; impl Real {
29 pub fn new(prim: Primitive) -> Self {
30 Real {
31 prim: Box::new(prim),
32 approx: None,
33 }
34 }
35
36 pub fn known_msd(&self) -> Option<i32> {
40 let res = self.approx.as_ref()?;
41 let size = res.value.abs().bits() as i32;
42 Some(res.precision + size - 1)
43 }
44
45 pub fn msd(&mut self, precision: i32) -> Option<i32> {
49 if let Some(res) = &self.approx {
50 if res.value.abs() > BigInt::one() {
51 return self.known_msd();
52 }
53 }
54 let res = self.appr(precision - 1);
55 if res.value.abs() <= BigInt::one() {
56 None
58 } else {
59 self.known_msd()
60 }
61 }
62
63 pub fn iter_msd_n(&mut self, min_precision: i32) -> Option<i32> {
66 let mut curr = 0;
67 loop {
68 let msd = self.msd(curr);
69 if msd.is_some() {
70 return msd;
71 }
72 curr = (curr * 3) / 2 - 16;
73 if curr <= min_precision + 30 {
74 break;
75 }
76 }
77 self.msd(min_precision)
78 }
79
80 pub fn iter_msd(&mut self) -> Option<i32> {
83 self.iter_msd_n(i32::MIN)
84 }
85
86 pub fn appr(&mut self, precision: i32) -> Approx {
91 if let Some(res) = &self.approx {
92 if precision >= res.precision {
93 return res.scale_to(precision);
94 }
95 }
96 let res = self.prim.approximate(precision, self.clone());
97 self.approx = Some(res.clone());
98 res
99 }
100
101 pub fn render_base(&self, n: u32, base: u32) -> String {
102 let scaled = match base {
103 16 => self.clone().shifted(n as i32 * 4),
104 _ => self.clone() * Real::int(BigInt::from(base).pow(n)),
105 }
106 .appr(0);
107
108 let value_str = scaled.value.abs().to_str_radix(base);
109
110 let padded_str = match value_str.len() as u32 {
111 len if len <= n => format!("{}{}", "0".repeat((n - len + 1) as usize), value_str),
112 _ => value_str,
113 };
114
115 let len = padded_str.len() as u32;
116 let (whole, frac) = padded_str.split_at((len - n) as usize);
117
118 let sign = if scaled.value.sign() == Sign::Minus {
119 "-"
120 } else {
121 ""
122 };
123 let dot = if n == 0 { "" } else { "." };
124 format!("{}{}{}{}", sign, whole, dot, frac)
125 }
126
127 pub fn render(&self, n: u32) -> String {
128 self.render_base(n, 10)
129 }
130
131 pub fn cmp_ra(&mut self, other: &mut Real, rel_tol: i32, abs_tol: i32) -> Ordering {
132 let msd1 = self.iter_msd_n(abs_tol).unwrap_or(i32::MIN);
133 let msd2 = other
134 .iter_msd_n(if msd1 > abs_tol { msd1 } else { abs_tol })
135 .unwrap_or(i32::MIN);
136 let msd = msd1.max(msd2);
137 if msd == i32::MIN {
138 return Ordering::Equal;
139 }
140 let rel = msd + rel_tol;
141 self.cmp_a(other, rel.max(abs_tol))
142 }
143
144 pub fn cmp_a(&mut self, other: &mut Real, abs_tol: i32) -> Ordering {
145 let prec = abs_tol - 1;
146 let a = self.appr(prec).value;
147 let b = other.appr(prec).value;
148 a.cmp(&b)
149 }
150
151 pub fn cmp_until(&self, other: &Real, min_precision: i32) -> Ordering {
152 let mut a = -16;
153 let mut clone = self.clone();
154 let mut other = other.clone();
155 loop {
156 let cmp = clone.cmp_a(&mut other, a);
157 if cmp != Ordering::Equal || a < min_precision {
158 return cmp;
159 }
160 a *= 2;
161 }
162 }
163
164 pub fn signum_a(&self, a: i32) -> i32 {
165 if let Some(res) = &self.approx {
166 if res.value.signum() != BigInt::ZERO {
167 return res.value.signum().to_i32().unwrap();
168 }
169 }
170 let prec = a - 1;
171 self.clone().appr(prec).value.signum().to_i32().unwrap()
172 }
173}
174
175impl Real {
176 pub fn int(value: BigInt) -> Self {
177 Self::new(Primitive::Int(value))
178 }
179
180 pub fn squared(self) -> Self {
181 Self::new(Primitive::Square(self))
182 }
183
184 pub fn atan(value: BigInt) -> Self {
185 Self::new(Primitive::Atan(value))
186 }
187
188 pub fn exp(mut self) -> Self {
189 let rough_appr = self.appr(-10).value;
190 let two = BigInt::from(2);
191 if rough_appr.abs() > two {
192 self.shifted(-1).exp().squared()
193 } else {
194 Self::new(Primitive::Exp(self))
195 }
196 }
197
198 pub fn cos(mut self) -> Self {
199 let half_pi_multiples = (self.clone() / Self::pi()).appr(-1).value;
200 let two = BigInt::from(2);
201
202 if half_pi_multiples.abs() >= two {
203 let pi_multiples: BigInt = (half_pi_multiples + 1) / 2;
204 let adj = Self::pi() * Real::int(pi_multiples.clone());
205 if (pi_multiples & BigInt::one()).signum() != BigInt::ZERO {
206 -(self - adj).cos()
207 } else {
208 (self - adj).cos()
209 }
210 } else if self.appr(-1).value.abs() >= two {
211 self.shifted(-1).cos().squared().shifted(1) - Self::one()
212 } else {
213 Self::new(Primitive::Cos(self))
214 }
215 }
216
217 pub fn sin(self) -> Self {
218 (Self::pi().shifted(-1) - self).cos()
219 }
220
221 pub fn asin(mut self) -> Self {
222 let rough_appr = self.appr(-10).value;
223 if rough_appr > 750.into() {
224 Self::one() - self.squared().sqrt().acos()
225 } else if rough_appr < (-750).into() {
226 -(-self.asin())
227 } else {
228 Self::new(Primitive::Asin(self))
229 }
230 }
231
232 pub fn acos(self) -> Self {
233 Self::pi().shifted(-1) - self.asin()
234 }
235
236 pub fn ln2(self) -> Self {
237 Self::new(Primitive::Ln(self - Self::one()))
238 }
239
240 pub fn ln(mut self) -> Self {
241 let rough_appr = self.appr(-4).value;
242 if rough_appr <= LN_MIN.into() {
243 -((Self::one() / self).ln())
244 } else if rough_appr >= LN_MAX.into() {
245 if rough_appr <= 64.into() {
246 self.sqrt().sqrt().ln().shifted(2)
247 } else {
248 let ln2_1 =
249 Real::int(7.into()) * (Real::int(10.into()) / Real::int(9.into())).ln2();
250 let ln2_2 =
251 Real::int(2.into()) * (Real::int(25.into()) / Real::int(24.into())).ln2();
252 let ln2_3 =
253 Real::int(3.into()) * (Real::int(81.into()) / Real::int(80.into())).ln2();
254 let ln2 = ln2_1 - ln2_2 + ln2_3;
255 let extra_bits = rough_appr.bits() as i32 - 3;
256 self.shifted(-extra_bits).ln() + Real::int(extra_bits.into()) * ln2
257 }
258 } else {
259 self.ln2()
260 }
261 }
262
263 pub fn sqrt(self) -> Self {
264 Self::new(Primitive::Sqrt(self))
265 }
266
267 pub fn shifted(self, bits: i32) -> Self {
268 Self::new(Primitive::Shift(self, bits))
269 }
270
271 pub fn pi() -> Self {
274 let atan5 = Real::atan(BigInt::from(5));
275 let atan239 = Real::atan(BigInt::from(239));
276 let four = Real::int(BigInt::from(4));
277 let four_atan5 = four.clone() * atan5;
278 let diff = four_atan5 - atan239;
279 diff * four
280 }
281
282 pub fn inv(self) -> Self {
283 Self::new(Primitive::Inv(self))
284 }
285}