author Jacob Lifshay Tue, 25 May 2021 01:02:51 +0000 (18:02 -0700) committer Jacob Lifshay Tue, 25 May 2021 01:02:51 +0000 (18:02 -0700)
 src/algorithms.rs patch | blob | history src/algorithms/float_float.rs [new file with mode: 0644] patch | blob

index 4c2aa82803b16bc11c84784d49466cf4d551fd0f..b2c7a20739cb3aec049ae14af3177576c87a2b1d 100644 (file)
@@ -1,4 +1,5 @@
pub mod base;
+pub mod float_float;
pub mod ilogb;
pub mod integer;
pub mod roots;
diff --git a/src/algorithms/float_float.rs b/src/algorithms/float_float.rs
new file mode 100644 (file)
index 0000000..8676f1d
--- /dev/null
@@ -0,0 +1,58 @@
+//! 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<F> {
+    high: F,
+    low: F,
+}
+
+impl<F: Float> FloatFloat<F> {
+    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 }
+    }
+}