//! based on algorithms from: //! //! Mioara Joldes, Jean-Michel Muller, and Valentina Popescu. 2017. Tight and Rigorous Error Bounds for Basic //! Building Blocks of Double-Word Arithmetic. ACM Trans. Math. Softw. 44, 2, Article 15res (October 2017), //! 27 pages. //! //! https://doi.org/10.1145/3121432 use crate::traits::{Context, ConvertTo, Float}; /// a higher-precision float represented as the exact sum of two floats `F` #[derive(Copy, Clone, Debug)] pub struct FloatFloat { high: F, low: F, } impl FloatFloat { pub fn new(high: F, low: F) -> Self { Self { high, low } } pub fn from_float(high: F) -> Self { Self { high, low: high.ctx().make(0.to()), } } pub fn to_float(self) -> F { self.high + self.low } /// create a `FloatFloat` from a sum of two floats, where `big.abs() >= small.abs()` /// /// based on Algorithm #1 from Joldes et al. (2017) pub fn from_ordered_sum(big: F, small: F) -> Self { let high = big + small; let low = small - (high - big); Self { high, low } } /// create a `FloatFloat` from a sum of two floats /// /// based on Algorithm #2 from Joldes et al. (2017) pub fn from_sum(a: F, b: F) -> Self { let high = a + b; let a_prime = high - b; let b_prime = high - a; let low = (a - a_prime) + (b - b_prime); Self { high, low } } /// create a `FloatFloat` from a sum of two floats /// /// based on Algorithm #3 from Joldes et al. (2017) #[cfg(feature = "fma")] pub fn from_product(a: F, b: F) -> Self { let high = a * b; let low = a.fma(b, -high); Self { high, low } } }