|
1 | 1 | //! Utilities for working with hex float formats.
|
2 | 2 |
|
3 |
| -use core::fmt; |
4 |
| - |
5 |
| -use super::{Float, Round, Status, f32_from_bits, f64_from_bits}; |
| 3 | +use super::{Round, Status, f32_from_bits, f64_from_bits}; |
6 | 4 |
|
7 | 5 | /// Construct a 16-bit float from hex float representation (C-style)
|
8 | 6 | #[cfg(f16_enabled)]
|
@@ -352,133 +350,143 @@ const fn u128_ilog2(v: u128) -> u32 {
|
352 | 350 | u128::BITS - 1 - v.leading_zeros()
|
353 | 351 | }
|
354 | 352 |
|
355 |
| -/// Format a floating point number as its IEEE hex (`%a`) representation. |
356 |
| -pub struct Hexf<F>(pub F); |
| 353 | +#[cfg(any(test, feature = "unstable-public-internals"))] |
| 354 | +mod hex_fmt { |
| 355 | + use core::fmt; |
357 | 356 |
|
358 |
| -// Adapted from https://github.com/ericseppanen/hexfloat2/blob/a5c27932f0ff/src/format.rs |
359 |
| -#[cfg(not(feature = "compiler-builtins"))] |
360 |
| -fn fmt_any_hex<F: Float>(x: &F, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
361 |
| - if x.is_sign_negative() { |
362 |
| - write!(f, "-")?; |
363 |
| - } |
| 357 | + use crate::support::Float; |
364 | 358 |
|
365 |
| - if x.is_nan() { |
366 |
| - return write!(f, "NaN"); |
367 |
| - } else if x.is_infinite() { |
368 |
| - return write!(f, "inf"); |
369 |
| - } else if *x == F::ZERO { |
370 |
| - return write!(f, "0x0p+0"); |
371 |
| - } |
| 359 | + /// Format a floating point number as its IEEE hex (`%a`) representation. |
| 360 | + pub struct Hexf<F>(pub F); |
372 | 361 |
|
373 |
| - let mut exponent = x.exp_unbiased(); |
374 |
| - let sig = x.to_bits() & F::SIG_MASK; |
375 |
| - |
376 |
| - let bias = F::EXP_BIAS as i32; |
377 |
| - // The mantissa MSB needs to be shifted up to the nearest nibble. |
378 |
| - let mshift = (4 - (F::SIG_BITS % 4)) % 4; |
379 |
| - let sig = sig << mshift; |
380 |
| - // The width is rounded up to the nearest char (4 bits) |
381 |
| - let mwidth = (F::SIG_BITS as usize + 3) / 4; |
382 |
| - let leading = if exponent == -bias { |
383 |
| - // subnormal number means we shift our output by 1 bit. |
384 |
| - exponent += 1; |
385 |
| - "0." |
386 |
| - } else { |
387 |
| - "1." |
388 |
| - }; |
| 362 | + // Adapted from https://github.com/ericseppanen/hexfloat2/blob/a5c27932f0ff/src/format.rs |
| 363 | + #[cfg(not(feature = "compiler-builtins"))] |
| 364 | + pub(super) fn fmt_any_hex<F: Float>(x: &F, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 365 | + if x.is_sign_negative() { |
| 366 | + write!(f, "-")?; |
| 367 | + } |
389 | 368 |
|
390 |
| - write!(f, "0x{leading}{sig:0mwidth$x}p{exponent:+}") |
391 |
| -} |
| 369 | + if x.is_nan() { |
| 370 | + return write!(f, "NaN"); |
| 371 | + } else if x.is_infinite() { |
| 372 | + return write!(f, "inf"); |
| 373 | + } else if *x == F::ZERO { |
| 374 | + return write!(f, "0x0p+0"); |
| 375 | + } |
392 | 376 |
|
393 |
| -#[cfg(feature = "compiler-builtins")] |
394 |
| -fn fmt_any_hex<F: Float>(_x: &F, _f: &mut fmt::Formatter<'_>) -> fmt::Result { |
395 |
| - unimplemented!() |
396 |
| -} |
| 377 | + let mut exponent = x.exp_unbiased(); |
| 378 | + let sig = x.to_bits() & F::SIG_MASK; |
| 379 | + |
| 380 | + let bias = F::EXP_BIAS as i32; |
| 381 | + // The mantissa MSB needs to be shifted up to the nearest nibble. |
| 382 | + let mshift = (4 - (F::SIG_BITS % 4)) % 4; |
| 383 | + let sig = sig << mshift; |
| 384 | + // The width is rounded up to the nearest char (4 bits) |
| 385 | + let mwidth = (F::SIG_BITS as usize + 3) / 4; |
| 386 | + let leading = if exponent == -bias { |
| 387 | + // subnormal number means we shift our output by 1 bit. |
| 388 | + exponent += 1; |
| 389 | + "0." |
| 390 | + } else { |
| 391 | + "1." |
| 392 | + }; |
397 | 393 |
|
398 |
| -impl<F: Float> fmt::LowerHex for Hexf<F> { |
399 |
| - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
400 |
| - cfg_if! { |
401 |
| - if #[cfg(feature = "compiler-builtins")] { |
402 |
| - let _ = f; |
403 |
| - unimplemented!() |
404 |
| - } else { |
405 |
| - fmt_any_hex(&self.0, f) |
| 394 | + write!(f, "0x{leading}{sig:0mwidth$x}p{exponent:+}") |
| 395 | + } |
| 396 | + |
| 397 | + #[cfg(feature = "compiler-builtins")] |
| 398 | + pub(super) fn fmt_any_hex<F: Float>(_x: &F, _f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 399 | + unimplemented!() |
| 400 | + } |
| 401 | + |
| 402 | + impl<F: Float> fmt::LowerHex for Hexf<F> { |
| 403 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 404 | + cfg_if! { |
| 405 | + if #[cfg(feature = "compiler-builtins")] { |
| 406 | + let _ = f; |
| 407 | + unimplemented!() |
| 408 | + } else { |
| 409 | + fmt_any_hex(&self.0, f) |
| 410 | + } |
406 | 411 | }
|
407 | 412 | }
|
408 | 413 | }
|
409 |
| -} |
410 | 414 |
|
411 |
| -impl<F: Float> fmt::LowerHex for Hexf<(F, F)> { |
412 |
| - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
413 |
| - cfg_if! { |
414 |
| - if #[cfg(feature = "compiler-builtins")] { |
415 |
| - let _ = f; |
416 |
| - unimplemented!() |
417 |
| - } else { |
418 |
| - write!(f, "({:x}, {:x})", Hexf(self.0.0), Hexf(self.0.1)) |
| 415 | + impl<F: Float> fmt::LowerHex for Hexf<(F, F)> { |
| 416 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 417 | + cfg_if! { |
| 418 | + if #[cfg(feature = "compiler-builtins")] { |
| 419 | + let _ = f; |
| 420 | + unimplemented!() |
| 421 | + } else { |
| 422 | + write!(f, "({:x}, {:x})", Hexf(self.0.0), Hexf(self.0.1)) |
| 423 | + } |
419 | 424 | }
|
420 | 425 | }
|
421 | 426 | }
|
422 |
| -} |
423 | 427 |
|
424 |
| -impl<F: Float> fmt::LowerHex for Hexf<(F, i32)> { |
425 |
| - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
426 |
| - cfg_if! { |
427 |
| - if #[cfg(feature = "compiler-builtins")] { |
428 |
| - let _ = f; |
429 |
| - unimplemented!() |
430 |
| - } else { |
431 |
| - write!(f, "({:x}, {:x})", Hexf(self.0.0), Hexf(self.0.1)) |
| 428 | + impl<F: Float> fmt::LowerHex for Hexf<(F, i32)> { |
| 429 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 430 | + cfg_if! { |
| 431 | + if #[cfg(feature = "compiler-builtins")] { |
| 432 | + let _ = f; |
| 433 | + unimplemented!() |
| 434 | + } else { |
| 435 | + write!(f, "({:x}, {:x})", Hexf(self.0.0), Hexf(self.0.1)) |
| 436 | + } |
432 | 437 | }
|
433 | 438 | }
|
434 | 439 | }
|
435 |
| -} |
436 | 440 |
|
437 |
| -impl fmt::LowerHex for Hexf<i32> { |
438 |
| - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
439 |
| - cfg_if! { |
440 |
| - if #[cfg(feature = "compiler-builtins")] { |
441 |
| - let _ = f; |
442 |
| - unimplemented!() |
443 |
| - } else { |
444 |
| - fmt::LowerHex::fmt(&self.0, f) |
| 441 | + impl fmt::LowerHex for Hexf<i32> { |
| 442 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 443 | + cfg_if! { |
| 444 | + if #[cfg(feature = "compiler-builtins")] { |
| 445 | + let _ = f; |
| 446 | + unimplemented!() |
| 447 | + } else { |
| 448 | + fmt::LowerHex::fmt(&self.0, f) |
| 449 | + } |
445 | 450 | }
|
446 | 451 | }
|
447 | 452 | }
|
448 |
| -} |
449 | 453 |
|
450 |
| -impl<T> fmt::Debug for Hexf<T> |
451 |
| -where |
452 |
| - Hexf<T>: fmt::LowerHex, |
453 |
| -{ |
454 |
| - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
455 |
| - cfg_if! { |
456 |
| - if #[cfg(feature = "compiler-builtins")] { |
457 |
| - let _ = f; |
458 |
| - unimplemented!() |
459 |
| - } else { |
460 |
| - fmt::LowerHex::fmt(self, f) |
| 454 | + impl<T> fmt::Debug for Hexf<T> |
| 455 | + where |
| 456 | + Hexf<T>: fmt::LowerHex, |
| 457 | + { |
| 458 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 459 | + cfg_if! { |
| 460 | + if #[cfg(feature = "compiler-builtins")] { |
| 461 | + let _ = f; |
| 462 | + unimplemented!() |
| 463 | + } else { |
| 464 | + fmt::LowerHex::fmt(self, f) |
| 465 | + } |
461 | 466 | }
|
462 | 467 | }
|
463 | 468 | }
|
464 |
| -} |
465 | 469 |
|
466 |
| -impl<T> fmt::Display for Hexf<T> |
467 |
| -where |
468 |
| - Hexf<T>: fmt::LowerHex, |
469 |
| -{ |
470 |
| - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
471 |
| - cfg_if! { |
472 |
| - if #[cfg(feature = "compiler-builtins")] { |
473 |
| - let _ = f; |
474 |
| - unimplemented!() |
475 |
| - } else { |
476 |
| - fmt::LowerHex::fmt(self, f) |
| 470 | + impl<T> fmt::Display for Hexf<T> |
| 471 | + where |
| 472 | + Hexf<T>: fmt::LowerHex, |
| 473 | + { |
| 474 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 475 | + cfg_if! { |
| 476 | + if #[cfg(feature = "compiler-builtins")] { |
| 477 | + let _ = f; |
| 478 | + unimplemented!() |
| 479 | + } else { |
| 480 | + fmt::LowerHex::fmt(self, f) |
| 481 | + } |
477 | 482 | }
|
478 | 483 | }
|
479 | 484 | }
|
480 | 485 | }
|
481 | 486 |
|
| 487 | +#[cfg(any(test, feature = "unstable-public-internals"))] |
| 488 | +pub use hex_fmt::*; |
| 489 | + |
482 | 490 | #[cfg(test)]
|
483 | 491 | mod parse_tests {
|
484 | 492 | extern crate std;
|
@@ -1064,6 +1072,7 @@ mod print_tests {
|
1064 | 1072 | use std::string::ToString;
|
1065 | 1073 |
|
1066 | 1074 | use super::*;
|
| 1075 | + use crate::support::Float; |
1067 | 1076 |
|
1068 | 1077 | #[test]
|
1069 | 1078 | #[cfg(f16_enabled)]
|
|
0 commit comments