rust-lang / rust-lang/libs-team

ACP: Add floating point representation conversions

Open
#501 21 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

api-change-proposal
Dominant language
Rust
Stars
178
Forks
28
Avg merge
15m
Merged PRs (30d)
1

Description

Proposal

Problem statement

There is currently no easy way to:

  • get an exponent and mantissa from a floating point number
  • construct a floating point number from an exponent and mantissa

Even creating a power of 2 in floating point is not easy even though it is a reasonably useful operation that can be computed exactly. powi can't be used because it has unspecified precision.

The only way is to directly deal with the internal bit representation and use to_bits and from_bits to convert.

Motivating examples or use cases

This would essentially be a replacement for f32::classify that keeps all the information about the number. f32::classify can be implemented in terms of to_repr.

Converting floating point to and from bignums (e.g. UBig::to_f32) could use this.

Implementing f32::div_euclid in std using integral division could use this.

Users could use this to inspect their floating point numbers, understand their behavior, debug their code, etc.

Solution sketch

pub enum FpRepresentation<Mantissa> {
    // number = 2^exponent * mantissa
    Finite {
        exponent: i32,
        mantissa: Mantissa,
        // This is redundant with the sign of `mantissa` except for negative zero
        sign: Sign,
    },
    Infinity { sign: Sign },
    Nan { nan_type: NanType, payload: Mantissa,  sign: Sign },
}

pub enum Sign {
    Positive,
    Negative,
}

pub enum NanType {
    Signaling,
    Quiet,
}

impl f32 {
    pub fn to_repr(self) -> FpRepresentation<i32> { ... }

    // Rounds the representation to the nearest representable number.
    // This will ignore the `sign` field for `Finite` numbers except when `mantissa` is 0.
    pub fn from_repr(repr: FpRepresentation<i32>) -> Self { ... }

    // Returns `None` if the number cannot be represented exactly
    pub fn from_repr_exact(repr: FpRepresentation<i32>) -> Option<Self> { ... }
}

Alternatives

Existing API (to_bits, from_bits) can be used to have this implemented as an external crate. It seems like it belongs to core because it deals with the essence of how floating point numbers are represented.

impl From<f32> for FpRepresentation could be implemented instead of to_repr.

impl TryFrom<FpRepresentation<i32>> for f32 could be implemented instead of from_repr_exact.

An equivalent of C functions ldexp and frexp could be implemented instead. The advantages of the proposed solution over these:

  • Enums are clearer than what these functions do for special values (NaN, infinities)
  • frexp returns mantissa as a floating point number but you typically want to deal with it as an integer (otherwise why convert?), which requires another conversion step

For ldexp the extra conversion step (integer -> fp) is less of a problem because it might be necessary anyway when the mantissa has more bits than can be represented. For example if you want to convert a 64-bit mantissa + exponent into f32 you would have to first convert the 64-bit number into f32 either way.

There could be a separate enum variant for subnormal numbers. This is an unnecessary complication. Subnormal numbers can be distinguished with the proposed API by the fact that they have a small mantissa (mantissa.abs() < 1 << (MANTISSA_DIGITS - 1)) and often don't need separate logic.

Links and related work

internals.rust-lang.org thread

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the proposal's FpRepresentation, Sign, and NanType sketch, then review the referenced f32::classify, to_bits, from_bits, and internals.rust-lang.org discussion. Compare the proposed methods with the listed alternatives and determine the API design the library team should adopt; done means the representation and conversion behavior are agreed.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.