Skip to content

Initial implementation of core_float_math #138087

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 17, 2025
Merged

Conversation

tgross35
Copy link
Contributor

@tgross35 tgross35 commented Mar 6, 2025

Since 1, compiler-builtins makes a certain set of math symbols
weakly available on all platforms. This means we can begin exposing some
of the related functions in core, so begin this process here.

It is not possible to provide inherent methods in both core and std
while giving them different stability gates, so standalone functions are
added instead. This provides a way to experiment with the functionality
while unstable; once it is time to stabilize, they can be converted to
inherent.

For f16 and f128, everything is unstable so we can move the inherent
methods.

The following are included to start:

  • floor
  • ceil
  • round
  • round_ties_even
  • trunc
  • fract
  • mul_add
  • div_euclid
  • rem_euclid
  • powi
  • sqrt
  • abs_sub
  • cbrt

These mirror the set of functions that we have in compiler-builtins
since 1, with the exception of powi that has been there longer.

Details for each of the changes is in the commit messages.

Tracking issue: #137578

try-job: aarch64-gnu
tru-job: armhf-gnu
try-job: i686-msvc-1
try-job: test-various
try-job: x86_64-mingw-1
try-job: x86_64-mingw-2

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Mar 6, 2025
@rust-log-analyzer

This comment has been minimized.

@tgross35

This comment was marked as outdated.

bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 6, 2025
Initial implementation of `core_float_math`

Since [1], `compiler-builtins` makes a certain set of math symbols
weakly available on all platforms. This means we can begin exposing some
of the related functions in `core`, so begin this process here.

It is not possible to provide inherent methods in both `core` and `std`
while giving them different stability gates, so standalone functions are
added instead. This provides a way to experiment with the functionality
while unstable; once it is time to stabilize, they can be converted to
inherent.

For `f16` and `f128`, everything is unstable so we can move the inherent
methods.

The following are included to start:

* floor
* ceil
* round
* round_ties_even
* trunc
* fract
* mul_add
* div_euclid
* rem_euclid
* powi
* sqrt
* abs_sub
* cbrt

These mirror the set of functions that we have in `compiler-builtins`
since [1].

Tracking issue: rust-lang#137578

[1]: rust-lang/compiler-builtins#763

r? `@ghost`

try-job: aarch64-gnu
try-job: arm-android
tru-job: armhf-gnu
try-job: test-various
try-job: x86_64-apple-1
try-job: aarch64-apple
try-job: i686-msvc-1
try-job: x86_64-msvc-ext2
@bors

This comment was marked as outdated.

@tgross35

This comment was marked as outdated.

bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 6, 2025
Initial implementation of `core_float_math`

Since [1], `compiler-builtins` makes a certain set of math symbols
weakly available on all platforms. This means we can begin exposing some
of the related functions in `core`, so begin this process here.

It is not possible to provide inherent methods in both `core` and `std`
while giving them different stability gates, so standalone functions are
added instead. This provides a way to experiment with the functionality
while unstable; once it is time to stabilize, they can be converted to
inherent.

For `f16` and `f128`, everything is unstable so we can move the inherent
methods.

The following are included to start:

* floor
* ceil
* round
* round_ties_even
* trunc
* fract
* mul_add
* div_euclid
* rem_euclid
* powi
* sqrt
* abs_sub
* cbrt

These mirror the set of functions that we have in `compiler-builtins`
since [1].

Tracking issue: rust-lang#137578

[1]: rust-lang/compiler-builtins#763

r? `@ghost`

try-job: aarch64-apple
try-job: aarch64-gnu
try-job: arm-android
tru-job: armhf-gnu
try-job: dist-various-1
try-job: dist-various-2
try-job: i686-msvc-1
try-job: test-various
try-job: x86_64-apple-1
try-job: x86_64-msvc-ext2
@bors

This comment was marked as outdated.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@tgross35

This comment was marked as outdated.

bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 6, 2025
Initial implementation of `core_float_math`

Since [1], `compiler-builtins` makes a certain set of math symbols
weakly available on all platforms. This means we can begin exposing some
of the related functions in `core`, so begin this process here.

It is not possible to provide inherent methods in both `core` and `std`
while giving them different stability gates, so standalone functions are
added instead. This provides a way to experiment with the functionality
while unstable; once it is time to stabilize, they can be converted to
inherent.

For `f16` and `f128`, everything is unstable so we can move the inherent
methods.

The following are included to start:

* floor
* ceil
* round
* round_ties_even
* trunc
* fract
* mul_add
* div_euclid
* rem_euclid
* powi
* sqrt
* abs_sub
* cbrt

These mirror the set of functions that we have in `compiler-builtins`
since [1], with the exception of `powi` that has been there longer.

Tracking issue: rust-lang#137578

[1]: rust-lang/compiler-builtins#763

r? `@ghost`

try-job: aarch64-apple
try-job: aarch64-gnu
try-job: arm-android
tru-job: armhf-gnu
try-job: dist-various-1
try-job: dist-various-2
try-job: i686-msvc-1
try-job: test-various
try-job: x86_64-apple-1
try-job: x86_64-msvc-ext2
@bors

This comment was marked as outdated.

@rust-log-analyzer

This comment has been minimized.

@bors

This comment was marked as outdated.

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 6, 2025
@tgross35 tgross35 force-pushed the core-float-math branch 2 times, most recently from 4375018 to 77794c6 Compare March 6, 2025 21:15
@tgross35

This comment was marked as outdated.

@bors

This comment was marked as outdated.

bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 6, 2025
Initial implementation of `core_float_math`

Since [1], `compiler-builtins` makes a certain set of math symbols
weakly available on all platforms. This means we can begin exposing some
of the related functions in `core`, so begin this process here.

It is not possible to provide inherent methods in both `core` and `std`
while giving them different stability gates, so standalone functions are
added instead. This provides a way to experiment with the functionality
while unstable; once it is time to stabilize, they can be converted to
inherent.

For `f16` and `f128`, everything is unstable so we can move the inherent
methods.

The following are included to start:

* floor
* ceil
* round
* round_ties_even
* trunc
* fract
* mul_add
* div_euclid
* rem_euclid
* powi
* sqrt
* abs_sub
* cbrt

These mirror the set of functions that we have in `compiler-builtins`
since [1], with the exception of `powi` that has been there longer.

Tracking issue: rust-lang#137578

[1]: rust-lang/compiler-builtins#763

r? `@ghost`

try-job: aarch64-apple
try-job: aarch64-gnu
try-job: arm-android
tru-job: armhf-gnu
try-job: dist-various-1
try-job: dist-various-2
try-job: i686-msvc-1
try-job: test-various
try-job: x86_64-apple-1
try-job: x86_64-msvc-ext2
@tgross35 tgross35 marked this pull request as ready for review March 6, 2025 21:35
@tgross35
Copy link
Contributor Author

tgross35 commented Mar 6, 2025

test-various passed, the others likely only need tweaks for f128 config.

r? @Amanieu

@bors bors added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label May 14, 2025
tgross35 added 2 commits May 14, 2025 14:29
The previous commit moved all test files from `std` to `core` so git
understands the move. Not all functionality is actually testable in
`core`, however, so perform move the relevant portions back. Changes
from inherent to module methods is also done since this is the form of
math operations available in `core` (as `core_float_math`).
Per [1], MinGW has an incorrect fma implementation. This showed up in
tests run with cranelift after adding float math operations to `core`.
Presumably we hadn't noticed this when running tests with LLVM because
LLVM was constant folding the result away.

Rust issue: rust-lang#140515

[1]: https://sourceforge.net/p/mingw-w64/bugs/848/
@tgross35
Copy link
Contributor Author

@bors try

bors added a commit to rust-lang-ci/rust that referenced this pull request May 14, 2025
Initial implementation of `core_float_math`

Since [1], `compiler-builtins` makes a certain set of math symbols
weakly available on all platforms. This means we can begin exposing some
of the related functions in `core`, so begin this process here.

It is not possible to provide inherent methods in both `core` and `std`
while giving them different stability gates, so standalone functions are
added instead. This provides a way to experiment with the functionality
while unstable; once it is time to stabilize, they can be converted to
inherent.

For `f16` and `f128`, everything is unstable so we can move the inherent
methods.

The following are included to start:

* floor
* ceil
* round
* round_ties_even
* trunc
* fract
* mul_add
* div_euclid
* rem_euclid
* powi
* sqrt
* abs_sub
* cbrt

These mirror the set of functions that we have in `compiler-builtins`
since [1], with the exception of `powi` that has been there longer.

Details for each of the changes is in the commit messages.

Tracking issue: rust-lang#137578

[1]: rust-lang/compiler-builtins#763

try-job: aarch64-gnu
tru-job: armhf-gnu
try-job: i686-msvc-1
try-job: test-various
try-job: x86_64-mingw-1
try-job: x86_64-mingw-2
@bors
Copy link
Collaborator

bors commented May 14, 2025

⌛ Trying commit 65117ee with merge 9577b71...

@bors
Copy link
Collaborator

bors commented May 14, 2025

☀️ Try build successful - checks-actions
Build commit: 9577b71 (9577b719e027050906395fd518d4df98fa17ced3)

@tgross35
Copy link
Contributor Author

tgross35 commented May 17, 2025

Discussed in person

@bors r=Amanieu

@bors
Copy link
Collaborator

bors commented May 17, 2025

📌 Commit 65117ee has been approved by Amanieu

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 17, 2025
@bors
Copy link
Collaborator

bors commented May 17, 2025

⌛ Testing commit 65117ee with merge 777d372...

@bors
Copy link
Collaborator

bors commented May 17, 2025

☀️ Test successful - checks-actions
Approved by: Amanieu
Pushing 777d372 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label May 17, 2025
@bors bors merged commit 777d372 into rust-lang:master May 17, 2025
7 checks passed
@rustbot rustbot added this to the 1.89.0 milestone May 17, 2025
@tgross35 tgross35 deleted the core-float-math branch May 17, 2025 22:32
Copy link

What is this? This is an experimental post-merge analysis report that shows differences in test outcomes between the merged PR and its parent PR.

Comparing bf5a38d (parent) -> 777d372 (this PR)

Test differences

Show 1962 test diffs

Stage 0

  • f128::test_clamp_min_is_nan: pass -> [missing] (J0)
  • f128::test_to_degrees: pass -> [missing] (J0)
  • f128::test_to_radians: pass -> [missing] (J0)
  • f16::test_algebraic: pass -> [missing] (J0)
  • f16::test_clamp_min_is_nan: pass -> [missing] (J0)
  • f16::test_classify: pass -> [missing] (J0)
  • f16::test_floor: pass -> [missing] (J0)
  • f16::test_maximum: pass -> [missing] (J0)
  • f16::test_mul_add: pass -> [missing] (J0)
  • f16::test_neg_zero: pass -> [missing] (J0)
  • f16::test_next_down: pass -> [missing] (J0)
  • f16::test_trunc: pass -> [missing] (J0)
  • f32::test_algebraic: pass -> [missing] (J0)
  • f32::test_clamp_min_is_nan: pass -> [missing] (J0)
  • f32::test_classify: pass -> [missing] (J0)
  • f32::test_is_finite: pass -> [missing] (J0)
  • f32::test_maximum: pass -> [missing] (J0)
  • f32::test_min_nan: pass -> [missing] (J0)
  • f32::test_one: pass -> [missing] (J0)
  • f32::test_to_degrees: pass -> [missing] (J0)
  • f64::test_is_normal: pass -> [missing] (J0)
  • f64::test_neg_zero: pass -> [missing] (J0)
  • f64::test_powi: pass -> [missing] (J0)
  • f64::test_sqrt_domain: pass -> [missing] (J0)
  • floats::f128::test_clamp_max_is_nan: [missing] -> pass (J0)
  • floats::f128::test_clamp_min_is_nan: [missing] -> pass (J0)
  • floats::f128::test_is_sign_positive: [missing] -> pass (J0)
  • floats::f128::test_next_down: [missing] -> pass (J0)
  • floats::f128::test_to_radians: [missing] -> pass (J0)
  • floats::f16::test_float_bits_conv: [missing] -> pass (J0)
  • floats::f16::test_fract: [missing] -> pass (J0)
  • floats::f16::test_is_sign_positive: [missing] -> pass (J0)
  • floats::f16::test_maximum: [missing] -> pass (J0)
  • floats::f16::test_minimum: [missing] -> pass (J0)
  • floats::f16::test_mul_add: [missing] -> pass (J0)
  • floats::f16::test_neg_zero: [missing] -> pass (J0)
  • floats::f16::test_next_down: [missing] -> pass (J0)
  • floats::f16::test_num_f16: [missing] -> pass (J0)
  • floats::f32::test_clamp_max_is_nan: [missing] -> pass (J0)
  • floats::f32::test_is_nan: [missing] -> pass (J0)
  • floats::f32::test_mul_add: [missing] -> pass (J0)
  • floats::f32::test_next_down: [missing] -> pass (J0)
  • floats::f32::test_round: [missing] -> pass (J0)
  • floats::f32::test_trunc: [missing] -> pass (J0)
  • floats::f64::test_abs: [missing] -> pass (J0)
  • floats::f64::test_classify: [missing] -> pass (J0)
  • floats::f64::test_is_finite: [missing] -> pass (J0)
  • floats::f64::test_is_sign_negative: [missing] -> pass (J0)
  • floats::f64::test_max_nan: [missing] -> pass (J0)
  • floats::f64::test_neg_infinity: [missing] -> pass (J0)
  • floats::f64::test_recip: [missing] -> pass (J0)

Stage 1

  • f32::test_algebraic: pass -> [missing] (J1)
  • f32::test_floor: pass -> [missing] (J1)
  • f32::test_infinity: pass -> [missing] (J1)
  • f32::test_max_nan: pass -> [missing] (J1)
  • f32::test_next_down: pass -> [missing] (J1)
  • f32::test_powi: pass -> [missing] (J1)
  • f64::test_clamp_max_is_nan: pass -> [missing] (J1)
  • f64::test_classify: pass -> [missing] (J1)
  • f64::test_min_nan: pass -> [missing] (J1)
  • f64::test_mul_add: pass -> [missing] (J1)
  • f64::test_total_cmp: pass -> [missing] (J1)
  • floats::f32::test_clamp_min_is_nan: [missing] -> pass (J1)
  • floats::f32::test_infinity: [missing] -> pass (J1)
  • floats::f32::test_max_nan: [missing] -> pass (J1)
  • floats::f32::test_min_nan: [missing] -> pass (J1)
  • floats::f32::test_minimum: [missing] -> pass (J1)
  • floats::f64::test_ceil: [missing] -> pass (J1)
  • floats::f64::test_infinity: [missing] -> pass (J1)
  • floats::f64::test_is_nan: [missing] -> pass (J1)
  • floats::f64::test_is_sign_negative: [missing] -> pass (J1)
  • floats::f64::test_nan: [missing] -> pass (J1)
  • floats::f64::test_neg_infinity: [missing] -> pass (J1)
  • floats::f64::test_signum: [missing] -> pass (J1)
  • floats::f64::test_to_degrees: [missing] -> pass (J1)
  • f16::test_abs: pass -> [missing] (J2)
  • f16::test_powi: pass -> [missing] (J2)
  • f16::test_recip: pass -> [missing] (J2)
  • floats::f16::test_max_nan: [missing] -> pass (J2)
  • floats::f16::test_min_nan: [missing] -> pass (J2)
  • floats::f16::test_minimum: [missing] -> pass (J2)
  • floats::f16::test_powi: [missing] -> pass (J2)
  • f16::test_classify: pass -> [missing] (J3)
  • f16::test_next_down: pass -> [missing] (J3)
  • f16::test_one: pass -> [missing] (J3)
  • floats::f16::test_clamp_max_is_nan: [missing] -> pass (J3)
  • floats::f16::test_clamp_min_is_nan: [missing] -> pass (J3)
  • floats::f16::test_float_bits_conv: [missing] -> pass (J3)
  • floats::f16::test_is_infinite: [missing] -> pass (J3)
  • f128::test_next_down: pass -> [missing] (J4)
  • f128::test_to_degrees: pass -> [missing] (J4)
  • floats::f128::test_clamp_min_greater_than_max: [missing] -> pass (J4)
  • floats::f128::test_clamp_min_is_nan: [missing] -> pass (J4)
  • floats::f128::test_is_sign_positive: [missing] -> pass (J4)
  • floats::f128::test_next_down: [missing] -> pass (J4)
  • floats::f128::test_to_degrees: [missing] -> pass (J4)
  • f128::test_abs: pass -> [missing] (J5)
  • f128::test_recip: pass -> [missing] (J5)
  • floats::f128::test_powi: [missing] -> pass (J5)
  • floats::f128::test_sqrt_domain: [missing] -> pass (J5)

(and 504 additional test diffs)

Additionally, 1358 doctest diffs were found. These are ignored, as they are noisy.

Job group index

Test dashboard

Run

cargo run --manifest-path src/ci/citool/Cargo.toml -- \
    test-dashboard 777d372772aa3b39ba7273fcb8208a89f2ab0afd --output-dir test-dashboard

And then open test-dashboard/index.html in your browser to see an overview of all executed tests.

Job duration changes

  1. dist-x86_64-apple: 8402.6s -> 7108.3s (-15.4%)
  2. dist-arm-linux: 4534.3s -> 4966.9s (9.5%)
  3. x86_64-apple-1: 8055.4s -> 7371.2s (-8.5%)
  4. dist-apple-various: 6533.7s -> 6014.7s (-7.9%)
  5. aarch64-apple: 3636.0s -> 3919.6s (7.8%)
  6. x86_64-apple-2: 4336.8s -> 4665.0s (7.6%)
  7. x86_64-gnu-stable: 6645.2s -> 7103.7s (6.9%)
  8. x86_64-msvc-ext1: 7457.7s -> 6970.0s (-6.5%)
  9. x86_64-gnu-aux: 6005.7s -> 6386.8s (6.3%)
  10. dist-x86_64-mingw: 8071.4s -> 7648.4s (-5.2%)
How to interpret the job duration changes?

Job durations can vary a lot, based on the actual runner instance
that executed the job, system noise, invalidated caches, etc. The table above is provided
mostly for t-infra members, for simpler debugging of potential CI slow-downs.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (777d372): comparison URL.

Overall result: ❌✅ regressions and improvements - no action needed

@rustbot label: -perf-regression

Instruction count

This is the most reliable metric that we have; it was used to determine the overall result at the top of this comment. However, even this metric can sometimes exhibit noise.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
1.1% [1.1%, 1.1%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-0.8% [-0.8%, -0.7%] 3
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results (secondary -1.4%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.7% [0.6%, 0.7%] 5
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-4.1% [-5.1%, -2.3%] 4
All ❌✅ (primary) - - 0

Cycles

Results (secondary 0.6%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
1.3% [0.4%, 3.2%] 7
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-1.0% [-1.1%, -0.9%] 3
All ❌✅ (primary) - - 0

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 774.349s -> 775.816s (0.19%)
Artifact size: 365.45 MiB -> 365.47 MiB (0.01%)

@DJMcNab
Copy link
Contributor

DJMcNab commented May 19, 2025

This landing in nightly has unfortunately broken Linebender's color crate. This is because we are trying to access the cbrt method on type@f32 as f32::cbrt (defined via a trait which uses libm to polyfill), and separately incidentally import the core::f32 module (presumably for some constants - I'm on mobile so can't check).

Name resolution seems to prefer these new functions over the ones defined on the f32 type. Unfortunately, as far as I know, there is no fully qualified name for f32, so we have to tweak our code to either define a type alias for f32, or to not import core::f32

I'm not sure how to determine if this class of breakage is classed as allowable. I think it would in theory be a regression on stable once 1.89 is stable. However, no matter where these functions live, it would be possible to adversarially trigger this for any unstable function being added.
I also don't really see what the alternative on the libs team side could be.

@tgross35
Copy link
Contributor Author

tgross35 commented May 19, 2025

Are you glob importing something from std? This is something we do try to discourage because that means that std adding any new api can break things (rust-lang/rust-clippy#13961). Regardless of the outcome here, please consider fixing this in color.

However, this is also intended to be temporary API that isn’t worth breaking anybody over, and color is a large enough crate to justify reconsideration. I think it would be fine if you put up a PR moving these from core::f32 to a new core::f32::math, unless @Amanieu has any thoughts here. (If you don’t get to it, I should be able to later)

@ajakubowicz-canva
Copy link

For reference – fix for color: linebender/color#175

@beetrees
Copy link
Contributor

Unfortunately, as far as I know, there is no fully qualified name for f32

For reference, all the primitive types are re-exported in std::primitive/core::primitive.

@DJMcNab
Copy link
Contributor

DJMcNab commented May 19, 2025

Are you glob importing something from std?

No, not that I'm aware of. We're only importing the (module) core::f32, and separately attempting to get a function value for the f32::cbrt function, to.
This is morally the "adding a new inherent method" breakage, but it occurs due to core::f32 and type@f32 having the same name.

We have now made a remedial release of color (I don't know if this impacts prior minor versions - I'm still on mobile).

@Amanieu
Copy link
Member

Amanieu commented May 19, 2025

It's hard to evaluate the breakage without the crater run, so we should either:

  • Revert this and perform a crater run.
  • Just move these to a different module like core::f32::math.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. rla-silenced Silences rust-log-analyzer postings to the PR it's added on. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants