decimal_scaled/equalities.rs
1//! `PartialEq` impls between every decimal width and primitive numeric
2//! types. Wires the macro emissions in `src/macros/equalities.rs` to
3//! each concrete width.
4//!
5//! # Semantics
6//!
7//! - **Integers** (`i8`-`i128`, `u8`-`u128`, `isize`, `usize`): exact
8//! mathematical equality. `d == n` holds iff `d.to_bits() == n * 10^SCALE`,
9//! i.e. `d` represents the integer `n` with no fractional part. The
10//! comparison is computed without overflow by splitting `d.to_bits()` into
11//! quotient and remainder modulo `10^SCALE`; the value is equal to `n` iff
12//! the remainder is zero and the quotient equals `n`.
13//!
14//! Examples:
15//! - `D38s12::from_int(5) == 5_i32` -> `true`
16//! - `D38s12::from_bits(5_500_000_000_000) == 5_i32` -> `false` (5.5 != 5)
17//! - `D38s12::from_bits(-1) == 0_u32` -> `false` (negative value)
18//!
19//! - **Floats** (`f32`, `f64`): equality holds iff `f` is finite and converts
20//! to and from `D38` losslessly relative to the f64 representation. NaN and
21//! ±inf always compare unequal. A `D38` value larger than `2^53` cannot
22//! match any `f64` exactly and will compare unequal except when the float's
23//! stored value happens to round-trip.
24//!
25//! Note that f64 cannot represent decimals like `1.1` exactly; the nearest
26//! f64 to `1.1` is `1.1000000000000000888...`. The implementation treats
27//! that nearest f64 as equal to `D38s12::from_bits(1_100_000_000_000)`
28//! because the round-trip through `from_f64`/`to_f64` agrees.
29//! Callers who need true rational equality should convert and compare
30//! explicitly.
31//!
32//! Each impl provides both directions (`D38<S> == T` and `T == D38<S>`) so
33//! comparisons are symmetric at the call site.
34
35use crate::core_type::{D38, D9, D18};
36
37// Cross-equality with primitive integer types is emitted by the
38// `decl_eq_all_integers!` macro family in `src/macros/equalities.rs`.
39// The same surface is generated for every decimal width.
40crate::macros::equalities::decl_eq_all_integers!(D38);
41crate::macros::equalities::decl_eq_all_integers!(D18);
42crate::macros::equalities::decl_eq_all_integers!(D9);
43
44#[cfg(any(feature = "d76", feature = "wide"))]
45use crate::core_type::D76;
46#[cfg(any(feature = "d153", feature = "wide"))]
47use crate::core_type::D153;
48#[cfg(any(feature = "d307", feature = "wide"))]
49use crate::core_type::D307;
50
51#[cfg(any(feature = "d76", feature = "wide"))]
52crate::macros::equalities::decl_eq_all_integers!(wide D76);
53#[cfg(any(feature = "d153", feature = "wide"))]
54crate::macros::equalities::decl_eq_all_integers!(wide D153);
55#[cfg(any(feature = "d307", feature = "wide"))]
56crate::macros::equalities::decl_eq_all_integers!(wide D307);
57
58// Float equality requires the f64 bridge (`from_f64` / `to_f64`),
59// which is gated on `std`. Float impls are emitted for every width
60// below.
61#[cfg(feature = "std")]
62crate::macros::equalities::decl_eq_float!(D38, f32);
63#[cfg(feature = "std")]
64crate::macros::equalities::decl_eq_float!(D38, f64);
65#[cfg(feature = "std")]
66crate::macros::equalities::decl_eq_float!(D18, f32);
67#[cfg(feature = "std")]
68crate::macros::equalities::decl_eq_float!(D18, f64);
69#[cfg(feature = "std")]
70crate::macros::equalities::decl_eq_float!(D9, f32);
71#[cfg(feature = "std")]
72crate::macros::equalities::decl_eq_float!(D9, f64);
73
74// Wide tiers share the same float-bridge surface, so the same macro
75// applies unchanged.
76#[cfg(all(feature = "std", any(feature = "d76", feature = "wide")))]
77crate::macros::equalities::decl_eq_float!(D76, f32);
78#[cfg(all(feature = "std", any(feature = "d76", feature = "wide")))]
79crate::macros::equalities::decl_eq_float!(D76, f64);
80#[cfg(all(feature = "std", any(feature = "d153", feature = "wide")))]
81crate::macros::equalities::decl_eq_float!(D153, f32);
82#[cfg(all(feature = "std", any(feature = "d153", feature = "wide")))]
83crate::macros::equalities::decl_eq_float!(D153, f64);
84#[cfg(all(feature = "std", any(feature = "d307", feature = "wide")))]
85crate::macros::equalities::decl_eq_float!(D307, f32);
86#[cfg(all(feature = "std", any(feature = "d307", feature = "wide")))]
87crate::macros::equalities::decl_eq_float!(D307, f64);
88