### IBM FPgen .fptest Example Cases Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Illustrative examples of lines from IBM FPgen `.fptest` files. These examples showcase different operations (addition, multiplication, FMA, comparison) and rounding modes, providing practical context for the file format. ```plaintext b32+ =0 +1.000000P+0 +1.000000P+0 -> +1.000000P+1 # Add, TiesToEven b32* > +1.000001P+0 +1.000001P+0 -> +1.000003P+0 # Mul, TowardPositive b64*+ =0 +1.0P+0 +1.0P+0 +1.0P+0 -> +1.0P+1 # FMA, TiesToEven b32=? +1.0P+0 +1.0P+0 -> 1 # Compare equal ``` -------------------------------- ### Noir: ZK Proof for Quadratic Equation Roots Source: https://context7.com/jeswr/noir_ieee754/llms.txt Demonstrates how to use the `ieee754` crate within a Noir ZK circuit to verify that a quadratic equation has real roots. This example proves the roots of ax² + bx + c = 0 without revealing the coefficients themselves, leveraging floating-point arithmetic operations within the circuit. ```noir use ieee754::float::{ IEEE754Float32, float32_from_bits, float32_to_bits, add_float32, mul_float32, div_float32, sqrt_float32, float32_gt, float32_lt, abs_float32 }; // Prove that a quadratic equation ax² + bx + c = 0 has real roots // without revealing the coefficients fn main( a_bits: pub u32, // Coefficient a (public) b_bits: pub u32, // Coefficient b (public) c_bits: pub u32, // Coefficient c (public) root1_bits: u32, // First root (private witness) root2_bits: u32 // Second root (private witness) ) { // Convert inputs to floats let a = float32_from_bits(a_bits); let b = float32_from_bits(b_bits); let c = float32_from_bits(c_bits); let x1 = float32_from_bits(root1_bits); let x2 = float32_from_bits(root2_bits); // Constants let two = float32_from_bits(0x40000000); // 2.0 let four = float32_from_bits(0x40800000); // 4.0 // Compute discriminant: b² - 4ac let b_squared = mul_float32(b, b); let four_a = mul_float32(four, a); let four_ac = mul_float32(four_a, c); let discriminant = sub_float32(b_squared, four_ac); // Prove discriminant is non-negative (has real roots) assert(!float32_lt(discriminant, float32_from_bits(0x00000000))); // Compute sqrt(discriminant) let sqrt_disc = sqrt_float32(discriminant); // Verify x1 = (-b + sqrt(disc)) / (2a) let neg_b = float32_from_bits(float32_to_bits(b) ^ 0x80000000); let numerator1 = add_float32(neg_b, sqrt_disc); let denominator = mul_float32(two, a); let computed_x1 = div_float32(numerator1, denominator); // Verify x2 = (-b - sqrt(disc)) / (2a) let numerator2 = sub_float32(neg_b, sqrt_disc); let computed_x2 = div_float32(numerator2, denominator); // Check roots match (with small tolerance for rounding) let diff1 = abs_float32(sub_float32(x1, computed_x1)); let diff2 = abs_float32(sub_float32(x2, computed_x2)); let epsilon = float32_from_bits(0x34000000); // ~1.2e-7 assert(float32_lt(diff1, epsilon)); assert(float32_lt(diff2, epsilon)); } // Example: prove x² - 5x + 6 = 0 has roots x=2 and x=3 // a = 1.0 (0x3F800000) // b = -5.0 (0xC0A00000) // c = 6.0 (0x40C00000) // x1 = 2.0 (0x40000000) // x2 = 3.0 (0x40400000) ``` -------------------------------- ### IBM FPgen Rounding Mode Symbols Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md A reference guide to the symbols used in IBM FPgen `.fptest` files to denote different rounding modes. This includes 'Round to nearest, ties to even', 'Round to nearest, ties away from zero', 'Round toward +infinity', 'Round toward -infinity', and 'Round toward zero'. ```plaintext - =0 : Round to nearest, ties to even (default) - =^ : Round to nearest, ties away from zero - > : Round toward +∞ (ceiling) - < : Round toward -∞ (floor) - 0 : Round toward zero (truncation) ``` -------------------------------- ### Run Tests by Category (Bash) Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md These bash commands demonstrate how to run specific test categories during development by invoking the `run_tests.py` script with category and rounding mode flags. This allows for targeted testing of different floating-point operations. ```bash # Run by category during development python3 scripts/run_tests.py add --rounding-mode ties_to_even python3 scripts/run_tests.py mul --rounding-mode toward_positive python3 scripts/run_tests.py fma ``` -------------------------------- ### Run All Tests (Bash) Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md This bash command executes all defined tests using the `run_tests.py` script with the `--all` flag. It is recommended for Continuous Integration (CI) and full validation of the implementation. ```bash # Run all tests (CI/full validation) python3 scripts/run_tests.py --all ``` -------------------------------- ### IBM FPgen .fptest File Format Reference Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md This section describes the format of the IBM FPgen `.fptest` files, which are used for testing floating-point operations. It details the structure of a test case line, including precision, operation, rounding mode, operands, and expected result. ```plaintext [flags] [operand2] [operand3] -> [result-flags] ``` -------------------------------- ### Float Format Conversion (Float32 to Float64, Float64 to Float32) Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Handles conversion between float32 and float64 formats. Float32 to Float64 is exact, while Float64 to Float32 may require rounding. ```Noir // Placeholder for convertFloat32ToFloat64(x) implementation fn convertFloat32ToFloat64(x: Field) -> Field { /* ... */ } // Placeholder for convertFloat64ToFloat32(x, rm) implementation fn convertFloat64ToFloat32(x: Field, rm: u8) -> Field { /* ... */ } // Algorithm sketch for Float64→Float32: // 1. If x is NaN → return Float32 NaN // 2. If x is ±∞ → return Float32 ±∞ // 3. If x is ±0 → return Float32 ±0 // 4. Extract sign, exponent, mantissa // 5. Rebias exponent: new_exp = exp64 - 1023 + 127 // 6. If new_exp >= 255 → overflow, return ±∞ or MAX per rm // 7. If new_exp <= 0 → underflow to denormal or zero // 8. Truncate mantissa from 52 bits to 23 bits // 9. Apply rounding using guard/round/sticky bits // 10. Return Float32 ``` -------------------------------- ### Basic Float32 Operations (Rust) Source: https://github.com/jeswr/noir_ieee754/blob/main/README.md Demonstrates basic usage of the ieee754 crate in Rust for 32-bit floating-point numbers. It shows how to convert bit representations to floats, perform arithmetic operations (add, subtract, multiply, divide, sqrt, abs), and convert floats back to bits. It also highlights the use of predefined special value constants. ```rust use ieee754::float::{ IEEE754Float32, float32_from_bits, float32_to_bits, add_float32, sub_float32, mul_float32, div_float32, sqrt_float32, abs_float32, FLOAT32_ONE, FLOAT32_ZERO, }; fn main() { // Create floats from bit representation let a = float32_from_bits(0x40400000); // 3.0f let b = float32_from_bits(0x40000000); // 2.0f // Or use predefined constants let one = float32_from_bits(FLOAT32_ONE); let zero = float32_from_bits(FLOAT32_ZERO); // Perform arithmetic operations let sum = add_float32(a, b); // 3.0 + 2.0 = 5.0 let diff = sub_float32(a, b); // 3.0 - 2.0 = 1.0 let product = mul_float32(a, b); // 3.0 * 2.0 = 6.0 let quotient = div_float32(a, b); // 3.0 / 2.0 = 1.5 let root = sqrt_float32(a); // sqrt(3.0) ≈ 1.732 let magnitude = abs_float32(float32_from_bits(0xBF800000)); // abs(-1.0) = 1.0 // Convert back to bits let sum_bits = float32_to_bits(sum); // 0x40A00000 = 5.0f let diff_bits = float32_to_bits(diff); // 0x3F800000 = 1.0f let product_bits = float32_to_bits(product); // 0x40C00000 = 6.0f let quotient_bits = float32_to_bits(quotient); // 0x3FC00000 = 1.5f } ``` -------------------------------- ### NextUp/NextDown Operations for Float32 and Float64 Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Implements `nextUp`, `nextDown`, and `nextAfter` operations for float32 and float64. These functions find the next representable floating-point number. ```Noir // Placeholder for nextUp_float32/float64 implementation fn nextUp_float32(x: Field) -> Field { /* ... */ } fn nextUp_float64(x: Field) -> Field { /* ... */ } // Placeholder for nextDown_float32/float64 implementation fn nextDown_float32(x: Field) -> Field { /* ... */ } fn nextDown_float64(x: Field) -> Field { /* ... */ } // Placeholder for nextAfter_float32(x, y)/nextAfter_float64(x, y) implementation fn nextAfter_float32(x: Field, y: Field) -> Field { /* ... */ } fn nextAfter_float64(x: Field, y: Field) -> Field { /* ... */ } // Algorithm sketch for nextUp(x): // - If x is NaN → return x (or qNaN) // - If x is -∞ → return -MAX_FLOAT // - If x is +∞ → return +∞ // - If x is -0 → return MIN_DENORMAL // - If x is +0 → return MIN_DENORMAL // - If x > 0 → return bits(x) + 1 as float // - If x < 0 → return bits(x) - 1 as float // nextDown(x) = -nextUp(-x) ``` -------------------------------- ### Noir Complete Public API for Float Operations Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Provides a comprehensive list of re-exported public API functions for float32 and float64 operations in Noir, including arithmetic, comparisons, classification, sign manipulation, and conversions. It specifies imports for types like IEEE754Float32, IEEE754Float64, RoundingMode, and FloatClass. ```noir // Re-exports in ieee754/src/float.nr // Types pub use crate::types::{IEEE754Float32, IEEE754Float64, RoundingMode, FloatClass}; // Float32 Operations (all have Float64 equivalents) pub use crate::float32{ // Arithmetic (default rounding) add_float32, sub_float32, mul_float32, div_float32, sqrt_float32, fma_float32, remainder_float32, // Arithmetic (explicit rounding) add_float32_rm, sub_float32_rm, mul_float32_rm, div_float32_rm, sqrt_float32_rm, fma_float32_rm, // Comparisons float32_eq, float32_ne, float32_lt, float32_le, float32_gt, float32_ge, float32_unordered, float32_compare, // Min/Max minimum_float32, maximum_float32, minimumNumber_float32, maximumNumber_float32, // Round to integral roundToIntegral_float32, trunc_float32, ceil_float32, floor_float32, round_float32, // Next nextUp_float32, nextDown_float32, nextAfter_float32, // Classification float32_is_nan, float32_is_infinity, float32_is_zero, float32_is_denormal, float32_is_normal, float32_is_finite, float32_is_sign_minus, float32_class, // Sign manipulation abs_float32, negate_float32, copySign_float32, // Conversion float32_from_bits, float32_to_bits, }; // Format conversion pub use crate::convert{ convertFloat32ToFloat64, convertFloat64ToFloat32, convertToInteger32_float32, convertToInteger64_float32, convertFromInteger32_float32, convertFromInteger64_float32, // ... and Float64 versions }; ``` -------------------------------- ### Complete Public API Surface Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md An overview of all exported types and functions available in the `ieee754` crate, including arithmetic, comparisons, conversions, and classification operations. ```APIDOC ## Complete Public API ### Description This section provides a comprehensive list of all types and functions publicly exposed by the `ieee754` crate, re-exported from their respective modules. ### Types - `IEEE754Float32`: Type for 32-bit IEEE 754 floating-point numbers. - `IEEE754Float64`: Type for 64-bit IEEE 754 floating-point numbers. - `RoundingMode`: Enum for specifying rounding behavior. - `FloatClass`: Enum for classifying floating-point values. ### Float32 Operations (Float64 equivalents available) #### Arithmetic (Default Rounding) - `add_float32(a, b)` - `sub_float32(a, b)` - `mul_float32(a, b)` - `div_float32(a, b)` - `sqrt_float32(a)` - `fma_float32(a, b, c)` - `remainder_float32(a, b)` #### Arithmetic (Explicit Rounding) - `add_float32_rm(a, b, rm)` - `sub_float32_rm(a, b, rm)` - `mul_float32_rm(a, b, rm)` - `div_float32_rm(a, b, rm)` - `sqrt_float32_rm(a, rm)` - `fma_float32_rm(a, b, c, rm)` #### Comparisons - `float32_eq(a, b)` - `float32_ne(a, b)` - `float32_lt(a, b)` - `float32_le(a, b)` - `float32_gt(a, b)` - `float32_ge(a, b)` - `float32_unordered(a, b)` - `float32_compare(a, b)` #### Min/Max - `minimum_float32(a, b)` - `maximum_float32(a, b)` - `minimumNumber_float32(a, b)` - `maximumNumber_float32(a, b)` #### Round to Integral - `roundToIntegral_float32(a)` - `trunc_float32(a)` - `ceil_float32(a)` - `floor_float32(a)` - `round_float32(a)` #### Next Number - `nextUp_float32(a)` - `nextDown_float32(a)` - `nextAfter_float32(a, b)` #### Classification - `float32_is_nan(a)` - `float32_is_infinity(a)` - `float32_is_zero(a)` - `float32_is_denormal(a)` - `float32_is_normal(a)` - `float32_is_finite(a)` - `float32_is_sign_minus(a)` - `float32_class(a)` #### Sign Manipulation - `abs_float32(a)` - `negate_float32(a)` - `copySign_float32(a, b)` #### Bitwise Conversion - `float32_from_bits(bits)` - `float32_to_bits(f)` ### Format Conversion - `convertFloat32ToFloat64(f32)` - `convertFloat64ToFloat32(f64)` - `convertToInteger32_float32(f)` - `convertToInteger64_float32(f)` - `convertFromInteger32_float32(i)` - `convertFromInteger64_float32(i)` - `... and Float64 versions ...` ### Example Usage ```noir use ieee754::types::{IEEE754Float32, RoundingMode}; use ieee754::float32::*; let x: IEEE754Float32 = ...; let y: IEEE754Float32 = ...; let sum = add_float32(x, y); let diff_rm = sub_float32_rm(x, y, RoundingMode::ties_to_away()); let bits = float32_to_bits(x); let from_bits = float32_from_bits(bits); ``` ### Response - Functions return the appropriate computed value (float, boolean, integer, bits, etc.) based on their operation. ``` -------------------------------- ### Round to Integral Operations for Float32 and Float64 Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Implements various rounding modes (ties to even, ties to away, toward zero, toward positive, toward negative) for float32 and float64 types. Includes a generic wrapper function. ```Noir // Placeholder for roundToIntegralTiesToEven_float32/float64 implementation fn roundToIntegralTiesToEven_float32(x: Field) -> Field { /* ... */ } fn roundToIntegralTiesToEven_float64(x: Field) -> Field { /* ... */ } // Placeholder for roundToIntegralTiesToAway_float32/float64 implementation fn roundToIntegralTiesToAway_float32(x: Field) -> Field { /* ... */ } fn roundToIntegralTiesToAway_float64(x: Field) -> Field { /* ... */ } // Placeholder for roundToIntegralTowardZero_float32/float64 implementation (trunc) fn roundToIntegralTowardZero_float32(x: Field) -> Field { /* ... */ } fn roundToIntegralTowardZero_float64(x: Field) -> Field { /* ... */ } // Placeholder for roundToIntegralTowardPositive_float32/float64 implementation (ceil) fn roundToIntegralTowardPositive_float32(x: Field) -> Field { /* ... */ } fn roundToIntegralTowardPositive_float64(x: Field) -> Field { /* ... */ } // Placeholder for roundToIntegralTowardNegative_float32/float64 implementation (floor) fn roundToIntegralTowardNegative_float32(x: Field) -> Field { /* ... */ } fn roundToIntegralTowardNegative_float64(x: Field) -> Field { /* ... */ } // Placeholder for generic roundToIntegral_float32 wrapper fn roundToIntegral_float32(x: Field, rm: u8) -> Field { /* ... */ } // Algorithm sketch: // roundToIntegral(x, rm): // 1. If x is NaN → return NaN // 2. If x is ±∞ → return x // 3. If x is ±0 → return x // 4. If |x| >= 2^precision → return x (already integral) // 5. Extract integer and fractional parts // 6. Apply rounding mode to determine if we round up // 7. Reconstruct float with rounded integer value ``` -------------------------------- ### Extend Test Generation Script in Python Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Extends the `generate_tests.py` script to support all 5 rounding modes from the IBM FPgen format, FMA operations, and comparison operations. This enhancement is crucial for comprehensive test suite integration, allowing tests to be grouped by rounding mode. ```python def generate_tests(rounding_modes, operations): # ... implementation to generate tests based on provided modes and operations pass ``` -------------------------------- ### Implement Minimum Operation for Float64 in Noir Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Implements `minimum_float64` to find the smaller of two float64 numbers, correctly propagating NaN values as defined by IEEE 754-2019. This is a component of the Min/Max Operations phase. ```Noir fn minimum_float64(x: Field, y: Field) -> Field { // Implementation of minimum for float64, handling NaNs // ... } ``` -------------------------------- ### Noir Rounding Mode API for Float32 Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Introduces new rounding-aware functions for float32 operations in Noir, appending '_rm' to their names. It also includes backward-compatible wrappers that default to the TiesToEven rounding mode. ```noir // New rounding-aware functions (append _rm suffix) pub fn add_float32_rm(a: IEEE754Float32, b: IEEE754Float32, rm: RoundingMode) -> IEEE754Float32 pub fn sub_float32_rm(a: IEEE754Float32, b: IEEE754Float32, rm: RoundingMode) -> IEEE754Float32 pub fn mul_float32_rm(a: IEEE754Float32, b: IEEE754Float32, rm: RoundingMode) -> IEEE754Float32 pub fn div_float32_rm(a: IEEE754Float32, b: IEEE754Float32, rm: RoundingMode) -> IEEE754Float32 pub fn sqrt_float32_rm(a: IEEE754Float32, rm: RoundingMode) -> IEEE754Float32 pub fn fma_float32_rm(a: IEEE754Float32, b: IEEE754Float32, c: IEEE754Float32, rm: RoundingMode) -> IEEE754Float32 // Backward-compatible wrappers (default to TiesToEven) pub fn add_float32(a: IEEE754Float32, b: IEEE754Float32) -> IEEE754Float32 { add_float32_rm(a, b, RoundingMode::ties_to_even()) } ``` -------------------------------- ### Implement Minimum Operation for Float32 in Noir Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Implements `minimum_float32` which calculates the smaller of two float32 numbers, propagating NaN values as per IEEE 754-2019 semantics. This function is part of the Min/Max Operations phase. ```Noir fn minimum_float32(x: Field, y: Field) -> Field { // Implementation of minimum for float32, handling NaNs // ... } ``` -------------------------------- ### Python Test Generator Updates Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Extends the Python test generator script to include support for various rounding modes, fused multiply-add (FMA) operations, and comparison operations. This enhances the test suite's coverage for different floating-point behaviors. ```python ROUNDING_MODES = { '=0': 'RoundingMode::ties_to_even()', '=^': 'RoundingMode::ties_to_away()', '>': 'RoundingMode::toward_positive()', '<': 'RoundingMode::toward_negative()', '0': 'RoundingMode::toward_zero()', } OPERATIONS = { '+': ('add', 2), '-': ('sub', 2), '*': ('mul', 2), '/': ('div', 2), 'V': ('sqrt', 1), '*+': ('fma', 3), # NEW: Fused multiply-add '%': ('rem', 2), # NEW: Remainder } COMPARISON_OPS = { '=?': 'eq', '?': 'gt', '>=?': 'ge', '<>?': 'ne', } ``` -------------------------------- ### Float64 Basic Arithmetic Source: https://context7.com/jeswr/noir_ieee754/llms.txt Performs basic arithmetic operations (addition, subtraction, multiplication, division) on double-precision IEEE 754 floats with configurable rounding modes. ```APIDOC ## Float64 Basic Arithmetic ### Description Supports addition, subtraction, multiplication, and division for IEEE 754 double-precision (binary64) floating-point numbers. Operations are identical in semantics to `Float32` operations. ### Methods - `add_float64(a: IEEE754Float64, b: IEEE754Float64) -> IEEE754Float64` - `sub_float64(a: IEEE754Float64, b: IEEE754Float64) -> IEEE754Float64` - `mul_float64(a: IEEE754Float64, b: IEEE754Float64) -> IEEE754Float64` - `div_float64(a: IEEE754Float64, b: IEEE754Float64) -> IEEE754Float64` - `mul_float64_with_rounding(a: IEEE754Float64, b: IEEE754Float64, rounding_mode: u8) -> IEEE754Float64` ### Supported Rounding Modes - `ROUNDING_MODE_NEAREST_EVEN` - `ROUNDING_MODE_TOWARD_POSITIVE` - `ROUNDING_MODE_TOWARD_NEGATIVE` - `ROUNDING_MODE_TOWARD_ZERO` - `ROUNDING_MODE_NEAREST_AWAY` ### Utility Functions - `float64_from_bits(bits: u64) -> IEEE754Float64` - `float64_to_bits(f: IEEE754Float64) -> u64` ### Request Example ```noir use ieee754::float::{IEEE754Float64, float64_from_bits, float64_to_bits, add_float64, mul_float64_with_rounding, ROUNDING_MODE_NEAREST_EVEN}; fn main() { let pi = float64_from_bits(0x400921FB54442D18); // 3.14159265358979... let e = float64_from_bits(0x4005BF0A8B145769); // 2.71828182845904... // Default rounding let sum = add_float64(pi, e); // Explicit rounding let rounded_product = mul_float64_with_rounding(pi, e, ROUNDING_MODE_NEAREST_EVEN); // Verification assert(float64_to_bits(sum) == 0x4017726FEF384008); } ``` ### Response Example (The output is the `IEEE754Float64` result of the operation, typically verified by converting back to bits.) ```noir // Example verification assert(float64_to_bits(sum) == 0x4017726FEF384008); ``` ``` -------------------------------- ### Implement Minimum Number Operation for Float64 in Noir Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Implements `minimumNumber_float64`, which returns the smaller of two float64 numbers, preferring a numeric value over NaN if one operand is NaN. This adheres to IEEE 754-2019 semantics and is developed during the Min/Max Operations phase. ```Noir fn minimumNumber_float64(x: Field, y: Field) -> Field { // Implementation of minimumNumber for float64, preferring numbers over NaNs // ... } ``` -------------------------------- ### Implement Maximum Operation for Float64 in Noir Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Implements `maximum_float64` to identify the larger of two float64 numbers, propagating NaN values according to IEEE 754-2019 standards. This function is part of the Min/Max Operations phase. ```Noir fn maximum_float64(x: Field, y: Field) -> Field { // Implementation of maximum for float64, handling NaNs // ... } ``` -------------------------------- ### Add Rounding Mode to Float64 Addition in Noir Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Modifies the `add_float64` function to accept a rounding mode. This aligns with the Rounding Mode Infrastructure phase, enabling different rounding behaviors for float64 addition. Backward compatibility is preserved by defaulting to TiesToEven. ```Noir fn add_float64(a: Field, b: Field, rm: RoundingMode) -> Field { // Implementation details for adding two float64 numbers with a specified rounding mode // ... } ``` -------------------------------- ### Noir IEEE 754 Floating-Point Rounding Modes Source: https://github.com/jeswr/noir_ieee754/blob/main/README.md Demonstrates the usage of different IEEE 754 rounding modes for single-precision (float32) arithmetic operations in Noir. Supports nearest even, nearest away, toward positive, toward negative, and toward zero rounding. Default operations use ROUNDING_MODE_NEAREST_EVEN. ```noir use ieee754::float::{ float32_from_bits, float32_to_bits, add_float32_with_rounding, mul_float32_with_rounding, // Rounding mode constants ROUNDING_MODE_NEAREST_EVEN, ROUNDING_MODE_NEAREST_AWAY, ROUNDING_MODE_TOWARD_POSITIVE, ROUNDING_MODE_TOWARD_NEGATIVE, ROUNDING_MODE_TOWARD_ZERO }; fn main() { let a = float32_from_bits(0x3F800000); // 1.0 let b = float32_from_bits(0x3EAAAAAB); // 0.333... // Default rounding (round to nearest, ties to even) let result_default = add_float32(a, b); // Explicit rounding modes let result_nearest = add_float32_with_rounding(a, b, ROUNDING_MODE_NEAREST_EVEN); let result_ceiling = add_float32_with_rounding(a, b, ROUNDING_MODE_TOWARD_POSITIVE); let result_floor = add_float32_with_rounding(a, b, ROUNDING_MODE_TOWARD_NEGATIVE); let result_truncate = add_float32_with_rounding(a, b, ROUNDING_MODE_TOWARD_ZERO); // All operations have _with_rounding variants: // add_float32_with_rounding, sub_float32_with_rounding, // mul_float32_with_rounding, div_float32_with_rounding, // sqrt_float32_with_rounding // (and same for float64) } ``` -------------------------------- ### Float32 Basic Arithmetic Source: https://context7.com/jeswr/noir_ieee754/llms.txt Performs basic arithmetic operations (addition, subtraction, multiplication, division) on single-precision IEEE 754 floats with configurable rounding modes. ```APIDOC ## Float32 Basic Arithmetic ### Description Supports addition, subtraction, multiplication, and division for IEEE 754 single-precision (binary32) floating-point numbers. Operations can be performed with a default rounding mode (nearest-ties-to-even) or explicitly specified rounding modes. ### Methods - `add_float32(a: IEEE754Float32, b: IEEE754Float32) -> IEEE754Float32` - `sub_float32(a: IEEE754Float32, b: IEEE754Float32) -> IEEE754Float32` - `mul_float32(a: IEEE754Float32, b: IEEE754Float32) -> IEEE754Float32` - `div_float32(a: IEEE754Float32, b: IEEE754Float32) -> IEEE754Float32` - `add_float32_with_rounding(a: IEEE754Float32, b: IEEE754Float32, rounding_mode: u8) -> IEEE754Float32` ### Supported Rounding Modes - `ROUNDING_MODE_NEAREST_EVEN` - `ROUNDING_MODE_TOWARD_POSITIVE` - `ROUNDING_MODE_TOWARD_NEGATIVE` - `ROUNDING_MODE_TOWARD_ZERO` - `ROUNDING_MODE_NEAREST_AWAY` ### Utility Functions - `float32_from_bits(bits: u32) -> IEEE754Float32` - `float32_to_bits(f: IEEE754Float32) -> u32` ### Request Example ```noir use ieee754::float::{IEEE754Float32, float32_from_bits, float32_to_bits, add_float32, mul_float32_with_rounding, ROUNDING_MODE_NEAREST_EVEN}; fn main() { let a = float32_from_bits(0x40400000); // 3.0 let b = float32_from_bits(0x40000000); // 2.0 // Default rounding let sum = add_float32(a, b); assert(float32_to_bits(sum) == 0x40A00000); // Explicit rounding let x = float32_from_bits(0x3F800000); // 1.0 let y = float32_from_bits(0x3EAAAAAB); // 0.333... let rounded_sum = mul_float32_with_rounding(x, y, ROUNDING_MODE_NEAREST_EVEN); } ``` ### Response Example (The output is the `IEEE754Float32` result of the operation, typically verified by converting back to bits.) ```noir // Example verification assert(float32_to_bits(sum) == 0x40A00000); // 5.0f ``` ``` -------------------------------- ### Arithmetic Operations with Rounding API Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md API endpoints for standard arithmetic operations (add, subtract, multiply, divide, sqrt, fma) that allow explicit control over the rounding mode. ```APIDOC ## Arithmetic Operations with Rounding ### Description These functions perform standard arithmetic operations on floating-point numbers, allowing the specification of a rounding mode for precise control over results. ### Rounding Modes ```noir pub enum RoundingMode { ties_to_even(), // Rounds to the nearest representable value, with ties rounding to the even digit. ties_to_away(), // Rounds to the nearest representable value, with ties rounding away from zero. toward_positive(), // Rounds towards positive infinity. toward_negative(), // Rounds towards negative infinity. toward_zero(), // Rounds towards zero. } ``` ### Functions (Float32) - `add_float32_rm(a: IEEE754Float32, b: IEEE754Float32, rm: RoundingMode)`: Adds two float32 numbers with specified rounding. - `sub_float32_rm(a: IEEE754Float32, b: IEEE754Float32, rm: RoundingMode)`: Subtracts `b` from `a` with specified rounding. - `mul_float32_rm(a: IEEE754Float32, b: IEEE754Float32, rm: RoundingMode)`: Multiplies two float32 numbers with specified rounding. - `div_float32_rm(a: IEEE754Float32, b: IEEE754Float32, rm: RoundingMode)`: Divides `a` by `b` with specified rounding. - `sqrt_float32_rm(a: IEEE754Float32, rm: RoundingMode)`: Computes the square root of `a` with specified rounding. - `fma_float32_rm(a: IEEE754Float32, b: IEEE754Float32, c: IEEE754Float32, rm: RoundingMode)`: Fused multiply-add operation (`a * b + c`) with specified rounding. ### Functions (Float64) Equivalent functions exist for `float64` (e.g., `add_float64_rm`). ### Backward-Compatible Wrappers Functions without `_rm` (e.g., `add_float32`) use `RoundingMode::ties_to_even()` by default. ### Example Usage ```noir let x: IEEE754Float32 = ...; let y: IEEE754Float32 = ...; let result = add_float32_rm(x, y, RoundingMode::toward_positive()); let default_result = add_float32(x, y); // Uses ties_to_even ``` ### Response - Returns the computed `IEEE754Float32` or `IEEE754Float64` result according to the specified rounding mode. ``` -------------------------------- ### Noir IEEE 754 Floating-Point Helper Functions Source: https://github.com/jeswr/noir_ieee754/blob/main/README.md Provides essential helper functions for float32 operations in Noir, including checks for special values (NaN, infinity, zero, denormal), creation of special values, square root, absolute value, and comprehensive comparison functions that adhere to IEEE 754 standards. Similar functions exist for float64. ```noir // Special value checks float32_is_nan(x) // Check if NaN float32_is_infinity(x) // Check if ±Infinity float32_is_zero(x) // Check if ±0 float32_is_denormal(x) // Check if denormalized // Create special values float32_nan() // Returns NaN float32_infinity(sign) // Returns ±Infinity float32_zero(sign) // Returns ±0 // Square root (IEEE 754 compliant) sqrt_float32(x) // sqrt(x), returns NaN for negative inputs (except -0) // Absolute value (IEEE 754 compliant) abs_float32(x) // |x|, returns magnitude with sign bit cleared // Comparison functions (IEEE 754 compliant) float32_eq(a, b) // a == b (NaN != NaN, +0 == -0) float32_ne(a, b) // a != b float32_lt(a, b) // a < b (false if either is NaN) float32_le(a, b) // a <= b (false if either is NaN) float32_gt(a, b) // a > b (false if either is NaN) float32_ge(a, b) // a >= b (false if either is NaN) float32_unordered(a, b) // true if either is NaN float32_compare(a, b) // -1, 0, or 1 (total ordering including NaN) // Same functions available for float64 with float64_ prefix (except sqrt uses sqrt_float64) ``` -------------------------------- ### Comparison Operations in Noir Source: https://context7.com/jeswr/noir_ieee754/llms.txt Implements IEEE 754 compliant comparison functions for float32 numbers. This includes standard equality, inequality, less than, greater than, less than or equal to, and greater than or equal to operations. It also correctly handles NaN and the sign of zero, along with a total ordering comparison. ```noir use ieee754::float::{ float32_from_bits, float32_eq, float32_ne, float32_lt, float32_le, float32_gt, float32_ge, float32_unordered, float32_compare, float32_is_nan, FLOAT32_ZERO, FLOAT32_NEG_ZERO, FLOAT32_NAN }; fn main() { let a = float32_from_bits(0x40400000); // 3.0 let b = float32_from_bits(0x40000000); // 2.0 let pos_zero = float32_from_bits(FLOAT32_ZERO); let neg_zero = float32_from_bits(FLOAT32_NEG_ZERO); let nan = float32_from_bits(FLOAT32_NAN); // Standard comparisons assert(float32_gt(a, b)); // 3.0 > 2.0 assert(float32_lt(b, a)); // 2.0 < 3.0 assert(!float32_eq(a, b)); // 3.0 != 2.0 assert(float32_ne(a, b)); // 3.0 != 2.0 assert(float32_ge(a, b)); // 3.0 >= 2.0 assert(float32_le(b, a)); // 2.0 <= 3.0 // IEEE 754 zero sign handling: +0 == -0 assert(float32_eq(pos_zero, neg_zero)); // NaN comparisons always return false (except unordered) assert(!float32_eq(nan, nan)); // NaN != NaN assert(!float32_lt(nan, a)); // false if either is NaN assert(!float32_gt(a, nan)); // false if either is NaN assert(float32_unordered(nan, a)); // true if either is NaN // Total ordering comparison (returns -1, 0, or 1) assert(float32_compare(a, b) == 1); // 3.0 > 2.0: returns 1 assert(float32_compare(b, a) == -1); // 2.0 < 3.0: returns -1 assert(float32_compare(a, a) == 0); // 3.0 == 3.0: returns 0 } ``` -------------------------------- ### Implement Fused Multiply-Add for Float64 in Noir Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Provides the `fma_float64` function for Fused Multiply-Add operations on float64 numbers. As part of the FMA Implementation phase, this function accurately computes `a * b + c` considering the specified rounding mode. Backward-compatible wrappers are included. ```Noir fn fma_float64(a: Field, b: Field, c: Field, rm: RoundingMode) -> Field { // Implementation details for Fused Multiply-Add on float64 // ... } ``` -------------------------------- ### Noir Rounding-Aware Float32 Arithmetic Operations Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Declares function signatures for rounding-aware single-precision (float32) arithmetic operations in Noir. These functions accept two IEEE754Float32 operands and a RoundingMode, returning the result with the specified rounding applied. ```noir pub fn add_float32_rm(a: IEEE754Float32, b: IEEE754Float32, rm: RoundingMode) -> IEEE754Float32 pub fn mul_float32_rm(a: IEEE754Float32, b: IEEE754Float32, rm: RoundingMode) -> IEEE754Float32 ``` -------------------------------- ### Integer Conversion Operations for Float32/Float64 Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Converts float32 and float64 values to various integer types (i32, u32, i64, u64) using specified rounding modes. Also converts integers to float32 and float64. ```Noir // Placeholder for convertToInteger32_float32(x, rm) → i32/u32 fn convertToInteger32_float32(x: Field, rm: u8) -> Field { /* ... */ } // Placeholder for convertToInteger64_float32(x, rm) → i64/u64 fn convertToInteger64_float32(x: Field, rm: u8) -> Field { /* ... */ } // Placeholder for convertToInteger32_float64(x, rm) → i32/u32 fn convertToInteger32_float64(x: Field, rm: u8) -> Field { /* ... */ } // Placeholder for convertToInteger64_float64(x, rm) → i64/u64 fn convertToInteger64_float64(x: Field, rm: u8) -> Field { /* ... */ } // Placeholder for convertFromInteger32_float32(n) → Float32 fn convertFromInteger32_float32(n: Field) -> Field { /* ... */ } // Placeholder for convertFromInteger64_float32(n) → Float32 fn convertFromInteger64_float32(n: Field) -> Field { /* ... */ } // Placeholder for convertFromInteger32_float64(n) → Float64 fn convertFromInteger32_float64(n: Field) -> Field { /* ... */ } // Placeholder for convertFromInteger64_float64(n) → Float64 fn convertFromInteger64_float64(n: Field) -> Field { /* ... */ } // Edge cases: // - NaN → invalid operation exception, return 0 or max int // - Overflow → return max/min int // - Inexact → signal inexact, round per mode ``` -------------------------------- ### Float32 Basic Arithmetic in Noir Source: https://context7.com/jeswr/noir_ieee754/llms.txt Performs basic arithmetic operations (addition, subtraction, multiplication, division) on single-precision IEEE 754 floating-point numbers within Noir. Supports conversion from bits, standard operations with default rounding (nearest-even), and explicit rounding modes. ```Noir use ieee754::float::{ IEEE754Float32, float32_from_bits, float32_to_bits, add_float32, sub_float32, mul_float32, div_float32, add_float32_with_rounding, ROUNDING_MODE_NEAREST_EVEN, ROUNDING_MODE_TOWARD_POSITIVE, ROUNDING_MODE_TOWARD_NEGATIVE, ROUNDING_MODE_TOWARD_ZERO, ROUNDING_MODE_NEAREST_AWAY }; fn main() { // Create floats from bit representations let a = float32_from_bits(0x40400000); // 3.0 let b = float32_from_bits(0x40000000); // 2.0 // Default rounding (nearest even) let sum = add_float32(a, b); // 5.0 let diff = sub_float32(a, b); // 1.0 let product = mul_float32(a, b); // 6.0 let quotient = div_float32(a, b); // 1.5 assert(float32_to_bits(sum) == 0x40A00000); // 5.0f assert(float32_to_bits(diff) == 0x3F800000); // 1.0f assert(float32_to_bits(product) == 0x40C00000); // 6.0f assert(float32_to_bits(quotient) == 0x3FC00000); // 1.5f // Explicit rounding modes let x = float32_from_bits(0x3F800000); // 1.0 let y = float32_from_bits(0x3EAAAAAB); // 0.333... let round_nearest = add_float32_with_rounding(x, y, ROUNDING_MODE_NEAREST_EVEN); let round_ceiling = add_float32_with_rounding(x, y, ROUNDING_MODE_TOWARD_POSITIVE); let round_floor = add_float32_with_rounding(x, y, ROUNDING_MODE_TOWARD_NEGATIVE); let round_truncate = add_float32_with_rounding(x, y, ROUNDING_MODE_TOWARD_ZERO); let round_away = add_float32_with_rounding(x, y, ROUNDING_MODE_NEAREST_AWAY); // All operations support rounding: sub_float32_with_rounding, // mul_float32_with_rounding, div_float32_with_rounding } ``` -------------------------------- ### Implement Fused Multiply-Add for Float32 in Noir Source: https://github.com/jeswr/noir_ieee754/blob/main/IMPLEMENTATION_PLAN.md Implements the `fma_float32` function for Fused Multiply-Add operations on float32 numbers. This is a key part of the FMA Implementation phase, handling the precise calculation of `a * b + c` with a specified rounding mode. It includes backward-compatible wrappers. ```Noir fn fma_float32(a: Field, b: Field, c: Field, rm: RoundingMode) -> Field { // Implementation details for Fused Multiply-Add on float32 // ... } ```