Repository: rust
Issue: f32::MAX_EXP and f64::MAX_EXP are documented incorrectly, and other associated constant woes
Labels: T-libs-api,A-floating-point

`f32::MAX_EXP` and `f64::MAX_EXP` are documented as

> Maximum possible power of 2 exponent.

This is straight up not true. They are respectively defined as `128` and `1024`, which is actually one *above* the maximum possible exponent of `f32` and `f64`. The doc comment needs to be changed.

---

In general I feel the set of associated constants for the floating point types are questionable, and should be a candidate for deprecation and replacement by a better set of constants. It is painfully obvious that the constants were copied from C's `<float.h>`, with little regard of whether these constants are useful or well-named.

I have no qualms with `MIN`, `MAX`, `NAN`, `INFINITY`, and `NEG_INFINITY` at all. They are sane and useful. However, the following set of constants are carbon copied from [`<float.h>`](https://en.cppreference.com/w/c/types/limits#Limits_of_floating_point_types):

    FLT_RADIX       = 2                => f32::RADIX
    FLT_MIN         = 1.175494e-38     => f32::MIN_POSITIVE
    FLT_EPSILON     = 1.192093e-07     => f32::EPSILON
    FLT_DIG         = 6                => f32::DIGITS
    FLT_MANT_DIG    = 24               => f32::MANTISSA_DIGITS
    FLT_MIN_EXP     = -125             => f32::MIN_EXP
    FLT_MIN_10_EXP  = -37              => f32::MIN_10_EXP
    FLT_MAX_EXP     = 128              => f32::MAX_EXP
    FLT_MAX_10_EXP  = 38               => f32::MAX_10_EXP

Going over them one by one (`f64` is entirely analogous):

- `f32::RADIX` is just plain useless. It's always 2, Rust has no support for non-binary floating point.
- `f32::MIN_POSITIVE` is badly named, because it's actually the smallest positive *normal* number. This is a useful constant, but the name is unacceptable in my opinion.
- `f32::EPSILON` is somewhat badly named (`MACHINE_EPSILON` would be better), and slightly deceptive. However this is not necessarily the fault of the constant, but due to people misunderstanding what machine epsilon means. Should my [RFC for `next_up`/`next_down`](https://github.com/rust-lang/rfcs/pull/3173) get merged, this would make this constant unnecessary. Especially if we make a [`ulp`](https://en.wikipedia.org/wiki/Unit_in_the_last_place) method in the future.
- `f32::DIGITS` is "the approximate number of significant digits in base 10". I don't know when you'd ever need this constant, or what 'approximate' here means at all. The constant is also deceptive, because one might interpret this as an upper bound on the number of digits needed to represent a `f32`.
- `f32::MANTISSA_DIGITS` includes the implied 1. Thus it is off by one from the constant you almost always want when explicitly working with a mantissa in code: the number of *bits* that the mantissa is wide.
- `f32::MIN_EXP`... I think the doc comment speaks for itself: "One greater than the minimum possible normal power of 2 exponent.". Not only is it off by one, it also ignores denormal floats.
- `f32::MAX_EXP`, see start of this issue.
- `f32::MIN_10_EXP`, also ignores denormal floats.
- `f32::MAX_10_EXP`, sanely defined but also fairly useless since you can compute `f32::MAX.log10().floor()` if
you really wanted to know this.

I honestly believe the best way forward is to deprecate all of the above constants and replace them with a couple fundamental, sane and conservative constants. For example for `f32`:
```rust
const EXPONENT_BIAS: i32 = 127;
const EXPONENT_WIDTH: i32 = 8;
const MANTISSA_WIDTH: i32 = 23;
const MIN_POS_NORMAL: f32 = f32::from_bits(1 << f32::MANTISSA_WIDTH);
```