Skip to main content

oxinum_float/native/
core_traits.rs

1//! `OxiNum` and `OxiSigned` trait implementations for native [`BigFloat`].
2//!
3//! These impls integrate `BigFloat` into the OxiNum trait hierarchy, letting
4//! generic code use [`OxiNum::is_zero`], [`OxiNum::is_one`],
5//! [`OxiSigned::signum`], and [`OxiSigned::abs`] uniformly over all numeric
6//! types in the ecosystem.
7
8use oxinum_core::{OxiNum, OxiSigned, Sign};
9
10use super::float::{BigFloat, RoundingMode};
11
12impl OxiNum for BigFloat {
13    /// Returns `true` if this value is the canonical zero.
14    ///
15    /// Delegates to the inherent [`BigFloat::is_zero`] to avoid any
16    /// trait-method ambiguity.
17    fn is_zero(&self) -> bool {
18        BigFloat::is_zero(self)
19    }
20
21    /// Returns `true` if this value is exactly `1`.
22    ///
23    /// Uses normalized equality: a `BigFloat` at precision `P` represents `1`
24    /// when its mantissa encodes `2^(P-1)` and its exponent is `-(P-1)` (the
25    /// normalization invariant pins `mantissa.bit_length() == P`).  This is
26    /// equivalent to comparing against `BigFloat::from_i64(1, P, HalfEven)`,
27    /// which produces the identical normalized representation.
28    ///
29    /// The comparison must use `self.precision()` so that the constructed `1`
30    /// has the same number of mantissa bits — two `BigFloat`s with different
31    /// precisions representing the value `1` have different mantissa/exponent
32    /// pairs and would compare unequal (precision is excluded from `PartialEq`
33    /// on the struct fields, but the mathematical value is the same; the
34    /// normalized encoding, however, pins the high bit, so the bit widths must
35    /// agree for field-level equality).
36    fn is_one(&self) -> bool {
37        if BigFloat::is_zero(self) {
38            return false;
39        }
40        self == &BigFloat::from_i64(1, self.precision(), RoundingMode::HalfEven)
41    }
42}
43
44impl OxiSigned for BigFloat {
45    /// Returns the sign of this value as [`Sign::Positive`] or
46    /// [`Sign::Negative`].
47    ///
48    /// Delegates to the inherent `sign()` method (returns `Sign` directly)
49    /// rather than the inherent `signum()` (returns `i32`) to avoid any
50    /// implicit coercion and to satisfy the trait's `-> Sign` return type.
51    fn signum(&self) -> Sign {
52        BigFloat::sign(self)
53    }
54
55    /// Returns the absolute value (sign forced to [`Sign::Positive`]).
56    ///
57    /// Delegates to the inherent [`BigFloat::abs`].
58    fn abs(&self) -> Self {
59        BigFloat::abs(self)
60    }
61}