Float Cascade to model multi-component floats
Let’s walk through how this FloatCascade<N> building block architecture naturally extends to support adaptive precision priest. The key insight is that priest uses a variable-length cascade that can grow and shrink as needed.
Here’s how the FloatCascade<N> building block architecture supports adaptive precision priest:
Key Architectural Elements:
Section titled “Key Architectural Elements:”1. VariableCascade - Dynamic Version of FloatCascade
Section titled “1. VariableCascade - Dynamic Version of FloatCascade”-
Uses
std::vector<double>instead ofstd::array<double, N> -
Can grow/shrink during computation
-
Same component ordering principles as fixed-size cascades
-
Provides seamless conversion to/from
FloatCascade<N>
2. Bidirectional Conversion Between Fixed and Adaptive
Section titled “2. Bidirectional Conversion Between Fixed and Adaptive”// Fixed → Adaptive (promotion)dd d1(1.0);priest p1(d1); // Seamless conversion
// Adaptive → Fixed (truncation/extraction)priest result = some.complex_calculation();dd final.dd = result.to_dd(); // Extract to double-doubletd final.td = result.to_td(); // Extract to triple-double3. Adaptive Precision Control
Section titled “3. Adaptive Precision Control”The priest class uses AdaptivePrecision config to control:
- Termination criteria: When to stop iterating (1/3 problem solved!)
- Component limits: Max/min cascade length
- Tolerance: Absolute vs relative error bounds
- Performance: Early termination, auto-compression
4. The 1/3 Solution in Action
Section titled “4. The 1/3 Solution in Action”struct AdaptivePrecision { double relative_tolerance; unsigned max_components; unsigned max_iterations;};
AdaptivePrecision high_precision{ .relative_tolerance = 1e-25, // Very tight tolerance .max_components = 20, // Allow up to 20 components .max_iterations = 50 // Limit iterations};
priest one(1.0, high.precision);priest three(3.0, high.precision);priest one.third = one / three; // Adapts precision automatically!The division algorithm:
- Starts with hardware precision estimate
- Iterates using Newton-Raphson refinement
- Terminates when error tolerance is met OR max iterations reached
- Controls component growth to prevent explosion
- Compresses result to remove unnecessary precision
5. Seamless Workflow
Section titled “5. Seamless Workflow”// Start with fixed precision (fast)dd quick.calc = dd(1.0) / dd(3.0); // Limited precision
// Need more precision? Promote seamlesslypriest precise.calc = priest(quick_calc);precise.calc = priest(1.0) / priest(3.0); // Now adaptive!
// Back to fixed for performance-critical codetd final.result = precise_calc.to_td();6. Shared ExpansionOps Engine
Section titled “6. Shared ExpansionOps Engine”All types (dd, td, qd, priest) use the same core algorithms:
two_sum,fast_two_sumfor basic operations- Expansion addition/multiplication algorithms
- Same mathematical foundations, different precision strategies
Benefits of This Architecture:
Section titled “Benefits of This Architecture:”- No Precision Walls: Smooth upgrade path from
dd→td→qd→priest - Performance Flexibility: Use fixed precision when speed matters, adaptive when accuracy matters
- Building Block Reuse: Same
FloatCascadeprinciples throughout - Controlled Iteration: Solves the “infinite 1/3” problem with configurable termination
- Universal Compatibility: All types can interchange via
FloatCascadeextraction
This design gives us what Priest intended: adaptive precision that does only as much work as necessary to guarantee a correct result, while maintaining Universal’s principle of independent, interoperable number systems!