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}