1use crate::cbig::CBig;
7use core::fmt::{self, Debug, Display, Formatter, Write};
8use dashu_float::round::Round;
9use dashu_float::{FBig, Repr};
10use dashu_int::{IBig, Word};
11
12fn is_unit<const B: Word>(repr: &Repr<B>) -> bool {
14 repr.exponent() == 0 && {
15 let s = repr.significand();
16 *s == IBig::ONE || *s == IBig::NEG_ONE
17 }
18}
19
20impl<R: Round, const B: Word> Display for CBig<R, B> {
21 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
26 let fctx = self.context.float();
27 let re_zero = self.re.is_pos_zero() || self.re.is_neg_zero();
28 let im_zero = self.im.is_pos_zero() || self.im.is_neg_zero();
29 let im_neg = self.im.sign() == dashu_base::Sign::Negative;
30 let im_unit = is_unit(&self.im);
31
32 if im_zero {
33 let re = FBig::from_repr(self.re.clone(), fctx);
35 return Display::fmt(&re, f);
36 }
37
38 if !re_zero {
40 let re = FBig::from_repr(self.re.clone(), fctx);
41 Display::fmt(&re, f)?;
42 f.write_char(if im_neg { '-' } else { '+' })?;
43 } else if im_neg {
44 f.write_char('-')?;
45 }
46 if !im_unit {
47 let im_abs_repr = if im_neg {
48 -self.im.clone()
49 } else {
50 self.im.clone()
51 };
52 let im_abs = FBig::from_repr(im_abs_repr, fctx);
53 Display::fmt(&im_abs, f)?;
54 }
55 f.write_char('i')
56 }
57}
58
59impl<R: Round, const B: Word> Debug for CBig<R, B> {
60 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
64 let fctx = self.context.float();
65 let re = FBig::from_repr(self.re.clone(), fctx);
66 let im = FBig::from_repr(self.im.clone(), fctx);
67 if f.alternate() {
68 f.debug_struct("CBig")
69 .field("re", &re)
70 .field("im", &im)
71 .field("precision", &self.context.precision())
72 .finish()
73 } else {
74 f.write_str("re:")?;
75 Display::fmt(&re, f)?;
76 f.write_str(" im:")?;
77 Display::fmt(&im, f)?;
78 f.write_fmt(format_args!(" (prec: {})", self.context.precision()))
79 }
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86 use alloc::format;
87 use dashu_float::round::mode;
88
89 type C = CBig<mode::HalfAway, 10>;
90
91 fn c(re: i32, im: i32) -> C {
92 C::from_parts(re.into(), im.into())
93 }
94
95 #[test]
96 fn display_algebraic() {
97 assert_eq!(format!("{}", c(0, 0)), "0");
98 assert_eq!(format!("{}", c(5, 0)), "5");
99 assert_eq!(format!("{}", c(0, 1)), "i");
100 assert_eq!(format!("{}", c(0, -1)), "-i");
101 assert_eq!(format!("{}", c(0, 4)), "4i");
102 assert_eq!(format!("{}", c(0, -4)), "-4i");
103 assert_eq!(format!("{}", c(1, 2)), "1+2i");
104 assert_eq!(format!("{}", c(-3, -4)), "-3-4i");
105 assert_eq!(format!("{}", c(1, 1)), "1+i");
106 assert_eq!(format!("{}", c(2, -1)), "2-i");
107 }
108
109 #[test]
110 fn display_constants() {
111 assert_eq!(format!("{}", C::I), "i");
112 assert_eq!(format!("{}", C::ONE), "1");
113 assert_eq!(format!("{}", C::ZERO), "0");
114 }
115
116 #[test]
117 fn debug_structured() {
118 let z = C::from_parts(FBig::from(3), FBig::from(4));
119 let s = format!("{:?}", z);
120 assert!(s.starts_with("re:3 im:4 (prec:"));
121 }
122}