Skip to main content

oxinum_complex/native/
core_traits.rs

1//! Core trait implementations for native [`BigComplex`]: [`Display`] and
2//! [`Debug`].
3//!
4//! [`PartialEq`] lives next to the arithmetic operators in
5//! [`super::complex_ops`]; `Eq`, `Ord`, and `Hash` are intentionally absent
6//! (see the [`super`] module docs — `BigFloat` is neither `Eq` nor `Hash`
7//! because of NaN, and the complex field has no ring-compatible order).
8//!
9//! # `Display`
10//!
11//! Renders as `<re> + <|im|>i` or `<re> - <|im|>i`, choosing the sign from
12//! [`BigFloat::is_sign_negative`] on the imaginary part and printing each
13//! component through `BigFloat`'s own `Display` (the exact `0xb…p…`
14//! hex-float form). The imaginary magnitude uses `im.abs()` so the chosen
15//! `+`/`-` separator is never duplicated by the component's own sign.
16
17use core::fmt;
18
19use super::BigComplex;
20
21impl fmt::Display for BigComplex {
22    /// Format as `a + bi` (or `a - bi` when the imaginary part is negative).
23    ///
24    /// Each component is delegated to [`BigFloat`](oxinum_float::native::BigFloat)'s
25    /// `Display`. The real part keeps its own sign; the imaginary part is shown
26    /// as a magnitude with an explicit `+`/`-` separator chosen from its sign.
27    ///
28    /// # Examples
29    ///
30    /// ```
31    /// use oxinum_complex::native::BigComplex;
32    /// let z = BigComplex::from_f64(1.0, -2.0, 53).expect("finite");
33    /// let s = format!("{z}");
34    /// assert!(s.contains('-'));
35    /// assert!(s.ends_with('i'));
36    /// ```
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        if self.im.is_sign_negative() {
39            // a - |b|i
40            write!(f, "{} - {}i", self.re, self.im.abs())
41        } else {
42            // a + bi (covers non-negative im, including the canonical zero)
43            write!(f, "{} + {}i", self.re, self.im)
44        }
45    }
46}
47
48impl fmt::Debug for BigComplex {
49    /// Structural debug view exposing the real and imaginary [`BigFloat`]s.
50    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51        f.debug_struct("BigComplex")
52            .field("re", &self.re)
53            .field("im", &self.im)
54            .finish()
55    }
56}
57
58// ---------------------------------------------------------------------------
59// Tests
60// ---------------------------------------------------------------------------
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn display_positive_imag() {
68        let z = BigComplex::from_f64(1.0, 2.0, 53).expect("finite");
69        let s = format!("{z}");
70        assert!(s.contains(" + "), "expected ' + ' in {s:?}");
71        assert!(s.ends_with('i'), "expected trailing 'i' in {s:?}");
72    }
73
74    #[test]
75    fn display_negative_imag() {
76        let z = BigComplex::from_f64(1.0, -2.0, 53).expect("finite");
77        let s = format!("{z}");
78        assert!(s.contains(" - "), "expected ' - ' in {s:?}");
79        // The imaginary magnitude must not carry its own leading '-'.
80        assert!(!s.contains("- -"), "double sign in {s:?}");
81        assert!(s.ends_with('i'), "expected trailing 'i' in {s:?}");
82    }
83
84    #[test]
85    fn debug_mentions_fields() {
86        let z = BigComplex::from_f64(1.0, 2.0, 53).expect("finite");
87        let s = format!("{z:?}");
88        assert!(s.contains("BigComplex"), "{s:?}");
89        assert!(s.contains("re"), "{s:?}");
90        assert!(s.contains("im"), "{s:?}");
91    }
92}