1 //! based on algorithms from:
2 //!
3 //! Mioara Joldes, Jean-Michel Muller, and Valentina Popescu. 2017. Tight and Rigorous Error Bounds for Basic
4 //! Building Blocks of Double-Word Arithmetic. ACM Trans. Math. Softw. 44, 2, Article 15res (October 2017),
5 //! 27 pages.
6 //!
7 //! https://doi.org/10.1145/3121432
9 use crate::traits::{Context, ConvertTo, Float};
11 /// a higher-precision float represented as the exact sum of two floats `F`
12 #[derive(Copy, Clone, Debug)]
13 pub struct FloatFloat<F> {
14 high: F,
15 low: F,
16 }
18 impl<F: Float> FloatFloat<F> {
19 pub fn new(high: F, low: F) -> Self {
20 Self { high, low }
21 }
22 pub fn from_float(high: F) -> Self {
23 Self {
24 high,
25 low: high.ctx().make(0.to()),
26 }
27 }
28 pub fn to_float(self) -> F {
29 self.high + self.low
30 }
31 /// create a `FloatFloat` from a sum of two floats, where `big.abs() >= small.abs()`
32 ///
33 /// based on Algorithm #1 from Joldes et al. (2017)
34 pub fn from_ordered_sum(big: F, small: F) -> Self {
35 let high = big + small;
36 let low = small - (high - big);
37 Self { high, low }
38 }
39 /// create a `FloatFloat` from a sum of two floats
40 ///
41 /// based on Algorithm #2 from Joldes et al. (2017)
42 pub fn from_sum(a: F, b: F) -> Self {
43 let high = a + b;
44 let a_prime = high - b;
45 let b_prime = high - a;
46 let low = (a - a_prime) + (b - b_prime);
47 Self { high, low }
48 }
49 /// create a `FloatFloat` from a sum of two floats
50 ///
51 /// based on Algorithm #3 from Joldes et al. (2017)
52 #[cfg(feature = "fma")]
53 pub fn from_product(a: F, b: F) -> Self {
54 let high = a * b;
55 let low = a.fma(b, -high);
56 Self { high, low }
57 }
58 }