|
1 | | -use core::cmp::Ordering; |
2 | | -use core::num::FpCategory; |
| 1 | +use core::{cmp::Ordering, fmt, num::FpCategory}; |
3 | 2 |
|
4 | 3 | use hexf::hexf64; |
5 | 4 |
|
@@ -265,6 +264,109 @@ impl TwoFloat { |
265 | 264 | } |
266 | 265 | } |
267 | 266 |
|
| 267 | +impl fmt::Display for TwoFloat { |
| 268 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 269 | + let sign_char = if self.lo().is_sign_positive() { |
| 270 | + '+' |
| 271 | + } else { |
| 272 | + '-' |
| 273 | + }; |
| 274 | + if f.sign_plus() { |
| 275 | + match f.precision() { |
| 276 | + Some(p) => write!( |
| 277 | + f, |
| 278 | + "{:+.*} {} {:.*}", |
| 279 | + p, |
| 280 | + self.hi, |
| 281 | + sign_char, |
| 282 | + p, |
| 283 | + self.lo.abs() |
| 284 | + ), |
| 285 | + None => write!(f, "{:+} {} {}", self.hi, sign_char, self.lo.abs()), |
| 286 | + } |
| 287 | + } else { |
| 288 | + match f.precision() { |
| 289 | + Some(p) => write!(f, "{:.*} {} {:.*}", p, self.hi, sign_char, p, self.lo.abs()), |
| 290 | + None => write!(f, "{} {} {}", self.hi, sign_char, self.lo.abs()), |
| 291 | + } |
| 292 | + } |
| 293 | + } |
| 294 | +} |
| 295 | + |
| 296 | +impl fmt::LowerExp for TwoFloat { |
| 297 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 298 | + let sign_char = if self.lo().is_sign_positive() { |
| 299 | + '+' |
| 300 | + } else { |
| 301 | + '-' |
| 302 | + }; |
| 303 | + if f.sign_plus() { |
| 304 | + match f.precision() { |
| 305 | + Some(p) => write!( |
| 306 | + f, |
| 307 | + "{:+.*e} {} {:.*e}", |
| 308 | + p, |
| 309 | + self.hi, |
| 310 | + sign_char, |
| 311 | + p, |
| 312 | + self.lo.abs() |
| 313 | + ), |
| 314 | + None => write!(f, "{:+e} {} {:e}", self.hi, sign_char, self.lo.abs()), |
| 315 | + } |
| 316 | + } else { |
| 317 | + match f.precision() { |
| 318 | + Some(p) => write!( |
| 319 | + f, |
| 320 | + "{:.*e} {} {:.*e}", |
| 321 | + p, |
| 322 | + self.hi, |
| 323 | + sign_char, |
| 324 | + p, |
| 325 | + self.lo.abs() |
| 326 | + ), |
| 327 | + None => write!(f, "{:e} {} {:e}", self.hi, sign_char, self.lo.abs()), |
| 328 | + } |
| 329 | + } |
| 330 | + } |
| 331 | +} |
| 332 | + |
| 333 | +impl fmt::UpperExp for TwoFloat { |
| 334 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 335 | + let sign_char = if self.lo().is_sign_positive() { |
| 336 | + '+' |
| 337 | + } else { |
| 338 | + '-' |
| 339 | + }; |
| 340 | + if f.sign_plus() { |
| 341 | + match f.precision() { |
| 342 | + Some(p) => write!( |
| 343 | + f, |
| 344 | + "{:+.*E} {} {:.*E}", |
| 345 | + p, |
| 346 | + self.hi, |
| 347 | + sign_char, |
| 348 | + p, |
| 349 | + self.lo.abs() |
| 350 | + ), |
| 351 | + None => write!(f, "{:+E} {} {:E}", self.hi, sign_char, self.lo.abs()), |
| 352 | + } |
| 353 | + } else { |
| 354 | + match f.precision() { |
| 355 | + Some(p) => write!( |
| 356 | + f, |
| 357 | + "{:.*E} {} {:.*E}", |
| 358 | + p, |
| 359 | + self.hi, |
| 360 | + sign_char, |
| 361 | + p, |
| 362 | + self.lo.abs() |
| 363 | + ), |
| 364 | + None => write!(f, "{:E} {} {:E}", self.hi, sign_char, self.lo.abs()), |
| 365 | + } |
| 366 | + } |
| 367 | + } |
| 368 | +} |
| 369 | + |
268 | 370 | impl PartialEq<f64> for TwoFloat { |
269 | 371 | fn eq(&self, other: &f64) -> bool { |
270 | 372 | self.hi.eq(other) && self.lo == 0.0 |
@@ -370,6 +472,39 @@ mod tests { |
370 | 472 | assert!(no_overlap(0.0, 0.0)); |
371 | 473 | } |
372 | 474 |
|
| 475 | + #[test] |
| 476 | + fn display_test() { |
| 477 | + let value = TwoFloat { hi: 1.0, lo: 0.3 }; |
| 478 | + assert_eq!(format!("{}", value), "1 + 0.3"); |
| 479 | + assert_eq!(format!("{}", -value), "-1 - 0.3"); |
| 480 | + assert_eq!(format!("{:+}", value), "+1 + 0.3"); |
| 481 | + assert_eq!(format!("{:.2}", value), "1.00 + 0.30"); |
| 482 | + assert_eq!(format!("{:.2}", -value), "-1.00 - 0.30"); |
| 483 | + assert_eq!(format!("{:+.2}", value), "+1.00 + 0.30"); |
| 484 | + } |
| 485 | + |
| 486 | + #[test] |
| 487 | + fn lowerexp_test() { |
| 488 | + let value = TwoFloat { hi: 1.0, lo: -0.3 }; |
| 489 | + assert_eq!(format!("{:e}", value), "1e0 - 3e-1"); |
| 490 | + assert_eq!(format!("{:e}", -value), "-1e0 + 3e-1"); |
| 491 | + assert_eq!(format!("{:+e}", value), "+1e0 - 3e-1"); |
| 492 | + assert_eq!(format!("{:.2e}", value), "1.00e0 - 3.00e-1"); |
| 493 | + assert_eq!(format!("{:.2e}", -value), "-1.00e0 + 3.00e-1"); |
| 494 | + assert_eq!(format!("{:+.2e}", value), "+1.00e0 - 3.00e-1"); |
| 495 | + } |
| 496 | + |
| 497 | + #[test] |
| 498 | + fn upperexp_test() { |
| 499 | + let value = TwoFloat { hi: 1.0, lo: 0.3 }; |
| 500 | + assert_eq!(format!("{:E}", value), "1E0 + 3E-1"); |
| 501 | + assert_eq!(format!("{:E}", -value), "-1E0 - 3E-1"); |
| 502 | + assert_eq!(format!("{:+E}", value), "+1E0 + 3E-1"); |
| 503 | + assert_eq!(format!("{:.2E}", value), "1.00E0 + 3.00E-1"); |
| 504 | + assert_eq!(format!("{:.2E}", -value), "-1.00E0 - 3.00E-1"); |
| 505 | + assert_eq!(format!("{:+.2E}", value), "+1.00E0 + 3.00E-1"); |
| 506 | + } |
| 507 | + |
373 | 508 | #[test] |
374 | 509 | fn default_test() { |
375 | 510 | let value: TwoFloat = Default::default(); |
|
0 commit comments