computable_real/
approx.rs

1use std::ops::{Add, Mul};
2
3use num::BigInt;
4
5/// An approximation of a real number to a certain precision.
6///
7/// If the underlying value is `x`, then it is guaranteed that
8/// `|x - value*2^precision| < 2^precision`.
9#[derive(Clone, Debug)]
10pub struct Approx {
11    pub value: BigInt,
12    pub precision: i32,
13}
14
15impl Approx {
16    pub(crate) fn new(value: &BigInt) -> Self {
17        Self {
18            value: value.clone(),
19            precision: 0,
20        }
21    }
22
23    pub(crate) fn prec(&self, precision: i32) -> Self {
24        Self {
25            value: self.value.clone(),
26            precision,
27        }
28    }
29
30    fn scale_by(&self, size: i32) -> Self {
31        Approx {
32            value: super::scale(self.value.clone(), size),
33            precision: self.precision - size,
34        }
35    }
36
37    pub(crate) fn scale_to(&self, target: i32) -> Self {
38        self.scale_by(self.precision - target)
39    }
40}
41
42impl Add for Approx {
43    type Output = Self;
44
45    fn add(self, rhs: Self) -> Self {
46        let precision = self.precision.max(rhs.precision);
47        let v1 = self.scale_to(precision).value;
48        let v2 = rhs.scale_to(precision).value;
49        Approx {
50            value: v1 + v2,
51            precision,
52        }
53    }
54}
55
56impl Mul for Approx {
57    type Output = Self;
58
59    fn mul(self, rhs: Self) -> Self {
60        Approx {
61            value: self.value * rhs.value,
62            precision: self.precision + rhs.precision,
63        }
64    }
65}
66
67impl Mul<i32> for Approx {
68    type Output = Self;
69
70    fn mul(self, rhs: i32) -> Self {
71        Approx {
72            value: self.value * rhs,
73            precision: self.precision,
74        }
75    }
76}