Skip to content
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

Implement f{16,32,64,128}::{erf,erfc} (#![feature(float_erf)]) #136324

Merged
merged 2 commits into from
Feb 15, 2025

Conversation

GrigorenkoPV
Copy link
Contributor

@GrigorenkoPV GrigorenkoPV commented Jan 31, 2025

Tracking issue: #136321

try-job: x86_64-gnu-aux

@rustbot
Copy link
Collaborator

rustbot commented Jan 31, 2025

r? @Amanieu

rustbot has assigned @Amanieu.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@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 Jan 31, 2025
@GrigorenkoPV GrigorenkoPV changed the title Implement f{16,32,64,128}::{erf,erfc} (float_erf) Implement f{16,32,64,128}::{erf,erfc} (#![feature(float_erf)]) Jan 31, 2025
@tgross35
Copy link
Contributor

r? tgross35

@rustbot rustbot assigned tgross35 and unassigned Amanieu Jan 31, 2025
@tgross35
Copy link
Contributor

1. Should the functions for `f16` & `f128` be gated under the `float_erf` flag or under `f16` & `f128` respectively?

Could you gate behind f16 and f128 but add a commented out // #[unstable(feature = "float_erf", issue = "136321")]? We do this for most methods on these types (like minimum), looks like I forgot to do that for gamma though.

2. A doctest for `erfc` is obvious: check that it's within `fN::EPSILON` from `1 - erf`. But what about `erf`? I currently check that `erf(1.0)` is within `fN::EPSILON` from a hardcoded constant. But the docs say:
   > The precision of this function is non-deterministic. This means it varies by platform, Rust version, and can even differ within the same execution from one invocation to the next.
   > Is there a better way to test `erf`?

Afaik there aren't any "convenient" values, it's probably fine to pick some random numbers. For reference:

> erf.(big.([-1.0, -0.5, 0.0, 0.5, 1.0]))
5-element Vector{BigFloat}:
 -0.8427007929497148693412206350826092592960669979663029084599378978347172540960087
 -0.5204998778130465376827466538919645287364515757579637000588057256471935217168533
  0.0
  0.5204998778130465376827466538919645287364515757579637000588057256471935217168533
  0.8427007929497148693412206350826092592960669979663029084599378978347172540960087
3. `compiler-builtins` has no `erf*` functions exposed [[src](https://github.com/rust-lang/compiler-builtins/blob/a233db5491360c01af0698784940ec4508738f33/src/math.rs)]. Is that an issue? Libm [does provide implementations](https://docs.rs/libm/latest/libm/?search=erf) though.

If you don't mind waiting a week or so (updating builtins is temporarily stuck), I think it would be easiest to expose them from libm before this merges. Otherwise the doctests will need to be gated to

4. Not sure if I should `#[cfg(not(msvc/aix))]` out any things, but I guess CI will tell.

They mention these functions in their docs https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/erf-erff-erfl-erfc-erfcf-erfcl?view=msvc-170 but the docs also mention atanf which is one of the symbols we shim https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/acos-acosf-acosl?view=msvc-170. Maybe they are only available for more recent versions? @ChrisDenton may know better.

In any case we can run a try job for these two targets.

@ChrisDenton
Copy link
Member

ChrisDenton commented Jan 31, 2025

They mention these functions in their docs https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/erf-erff-erfl-erfc-erfcf-erfcl?view=msvc-170 but the docs also mention atanf which is one of the symbols we shim https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/acos-acosf-acosl?view=msvc-170. Maybe they are only available for more recent versions? @ChrisDenton may know better.

In 32-bit x86 MSVC, some UCRT functions are header-only but the DLL does indeed export erf, erfc, erfcf, erfcl, erff and erfl.

@GrigorenkoPV
Copy link
Contributor Author

GrigorenkoPV commented Jan 31, 2025

Could you gate behind f16 and f128 but add a commented out // #[unstable(feature = "float_erf", issue = "136321")]?

Done.

looks like I forgot to do that for gamma though.

Added those as well. I think it's fine to not do it in a separate PR, since it's just a comment, not to mention float_gamma and float_erf are somewhat related.

Afaik there aren't any "convenient" values, it's probably fine to pick some random numbers.

Is one number enough or should I add more?

Also, out of curiosity, what language was that example in?

If you don't mind waiting a week or so (updating builtins is temporarily stuck), I think it would be easiest to expose them from libm before this merges. Otherwise the doctests will need to be gated too

I will file a PR in the compiler-builtins repo.

UPD: Done. rust-lang/compiler-builtins#753

BTW, under what conditions will the doctests fail if the functions are not exposed in compiler-builtins? I'm not entirely familiar with how these things work.

GrigorenkoPV added a commit to GrigorenkoPV/rust that referenced this pull request Jan 31, 2025
Also add
```rust
// #[unstable(feature = "float_gamma", issue = "99842")]
```
to `gamma`-function-related methods on `f16` & `f128`,
as per rust-lang#136324 (comment)
@rustbot rustbot added the S-blocked Status: Blocked on something else such as an RFC or other implementation work. label Jan 31, 2025
@tgross35
Copy link
Contributor

tgross35 commented Feb 1, 2025

Added those as well. I think it's fine to not do it in a separate PR, since it's just a comment, not to mention float_gamma and float_erf are somewhat related.

Thanks!

Afaik there aren't any "convenient" values, it's probably fine to pick some random numbers.

Is one number enough or should I add more?

🤷 up to you, it's more of a demonstration than a test. I guess if you are looking for ideas you could use something based on the emperical rule:

/// The error function relates what percent of a normal distribution lies
/// within `x` standard deviations (scaled by `1/sqrt(2)`).
fn within_standard_deviations(x: f32) -> f32 {
    (x as f32 * std::f32::consts::FRAC_1_SQRT_2).erf() * 100.0
}

// 68% of a normal distribution is within one standard deviation
assert!((within_standard_deviations(1.0) - 68.269).abs() < 0.01);
// 95% of a normal distribution is within two standard deviations
assert!((within_standard_deviations(2.0) - 95.450).abs() < 0.01);
// 99.7% of a normal distribution is within three standard deviations
assert!((within_standard_deviations(3.0) - 99.730).abs() < 0.01);

Also, out of curiosity, what language was that example in?

Julia, with using SpecialFunctions to get erf. The repl is kind of handy for scratch math, especially since bigfloats are easy to use.

If you don't mind waiting a week or so (updating builtins is temporarily stuck), I think it would be easiest to expose them from libm before this merges. Otherwise the doctests will need to be gated too

I will file a PR in the compiler-builtins repo.

UPD: Done. rust-lang/compiler-builtins#753

Left a comment there but that change LGTM, But as noted there,

@rustbot blocked

BTW, under what conditions will the doctests fail if the functions are not exposed in compiler-builtins? I'm not entirely familiar with how these things work.

Most everything uses the system's C libm if it is available, but compiler-builtins provides the math operations for platforms that don't have it. At least WASM and UEFI would fail without it, I'm not sure exactly what else. You may have seen it already but the config for what platforms get exposed is here https://github.com/rust-lang/compiler-builtins/blob/c038174b9099e85c3c30c4e9ba85c5f4ae8f7d50/src/lib.rs#L44-L60.

@tgross35
Copy link
Contributor

tgross35 commented Feb 8, 2025

I just reverted the thing that was blocking the builtins update, it will be merged in #136714. Once that merges I'll run a couple try jobs.

This looks pretty reasonable, I think you wanted to update the examples still.

@rustbot author

@rustbot rustbot 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. S-blocked Status: Blocked on something else such as an RFC or other implementation work. labels Feb 8, 2025
Comment on lines 1275 to 1278
/// # Unspecified precision
///
/// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
/// can even differ within the same execution from one invocation to the next.
/// This function currently corresponds to the `erff` from libc on Unix
/// and Windows. Note that this might change in the future.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're updating the docs, mind copying this section from the f128 or f16 files? The f32/f64 ones just have really random wrapping.

GrigorenkoPV added a commit to GrigorenkoPV/rust that referenced this pull request Feb 12, 2025
Also add
```rust
// #[unstable(feature = "float_gamma", issue = "99842")]
```
to `gamma`-function-related methods on `f16` & `f128`,
as per rust-lang#136324 (comment)
GrigorenkoPV added a commit to GrigorenkoPV/rust that referenced this pull request Feb 12, 2025
Also add
```rust
// #[unstable(feature = "float_gamma", issue = "99842")]
```
to `gamma`-function-related methods on `f16` & `f128`,
as per rust-lang#136324 (comment)
@GrigorenkoPV
Copy link
Contributor Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 12, 2025
@@ -742,6 +742,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
| "log1pf"
| "expm1f"
| "tgammaf"
| "erff"
| "erfcf"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also add calls to this function in src/tools/miri/tests/pass/float.rs.

@RalfJung
Copy link
Member

Miri changes LGTM. :) But let's ensure they pass CI.

@tgross35
Copy link
Contributor

@bors try

@bors
Copy link
Contributor

bors commented Feb 14, 2025

⌛ Trying commit 18b9ede with merge 0b51376...

bors added a commit to rust-lang-ci/rust that referenced this pull request Feb 14, 2025
Implement `f{16,32,64,128}::{erf,erfc}` (`#![feature(float_erf)]`)

Tracking issue: rust-lang#136321

try-job: x86_64-gnu-aux
@bors
Copy link
Contributor

bors commented Feb 14, 2025

☀️ Try build successful - checks-actions
Build commit: 0b51376 (0b513760eb662d9fbdc0af2ea925d36f6cd5a087)

@tgross35
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Feb 15, 2025

📌 Commit 18b9ede has been approved by tgross35

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-review Status: Awaiting review from the assignee but also interested parties. labels Feb 15, 2025
@bors
Copy link
Contributor

bors commented Feb 15, 2025

⌛ Testing commit 18b9ede with merge f77247a...

@bors
Copy link
Contributor

bors commented Feb 15, 2025

☀️ Test successful - checks-actions
Approved by: tgross35
Pushing f77247a to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Feb 15, 2025
@bors bors merged commit f77247a into rust-lang:master Feb 15, 2025
7 checks passed
@rustbot rustbot added this to the 1.86.0 milestone Feb 15, 2025
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (f77247a): comparison URL.

Overall result: no relevant changes - no action needed

@rustbot label: -perf-regression

Instruction count

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

Max RSS (memory usage)

Results (secondary -2.1%)

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
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-2.1% [-2.1%, -2.1%] 1
All ❌✅ (primary) - - 0

Cycles

Results (secondary 9.2%)

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)
9.2% [8.8%, 10.0%] 6
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Binary size

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

Bootstrap: 790.529s -> 788.977s (-0.20%)
Artifact size: 347.33 MiB -> 347.33 MiB (-0.00%)

@GrigorenkoPV GrigorenkoPV deleted the erf branch February 15, 2025 14:00
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Feb 18, 2025
… r=tgross35

tests: Also gate `f16::erfc()` doctest with `reliable_f16_math` cfg

In rust-lang#136324 the doctest for `f16::erf()` was gated with `reliable_f16_math`. Add the same gate on `f16::erfc()` to avoid:

    rust_out.71e2e529d20ea47d-cgu.0:\
    (.text._ZN8rust_out4main43_doctest_main_library_std_src_f16_rs_1321_017h485f3ffe6bf2a981E+0x38): \
    undefined reference to `__gnu_h2f_ieee'

on MIPS (and maybe other architectures).

r? tgross35
Urgau added a commit to Urgau/rust that referenced this pull request Feb 18, 2025
… r=tgross35

tests: Also gate `f16::erfc()` doctest with `reliable_f16_math` cfg

In rust-lang#136324 the doctest for `f16::erf()` was gated with `reliable_f16_math`. Add the same gate on `f16::erfc()` to avoid:

    rust_out.71e2e529d20ea47d-cgu.0:\
    (.text._ZN8rust_out4main43_doctest_main_library_std_src_f16_rs_1321_017h485f3ffe6bf2a981E+0x38): \
    undefined reference to `__gnu_h2f_ieee'

on MIPS (and maybe other architectures).

r? tgross35
Urgau added a commit to Urgau/rust that referenced this pull request Feb 18, 2025
… r=tgross35

tests: Also gate `f16::erfc()` doctest with `reliable_f16_math` cfg

In rust-lang#136324 the doctest for `f16::erf()` was gated with `reliable_f16_math`. Add the same gate on `f16::erfc()` to avoid:

    rust_out.71e2e529d20ea47d-cgu.0:\
    (.text._ZN8rust_out4main43_doctest_main_library_std_src_f16_rs_1321_017h485f3ffe6bf2a981E+0x38): \
    undefined reference to `__gnu_h2f_ieee'

on MIPS (and maybe other architectures).

r? tgross35
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Feb 18, 2025
… r=tgross35

tests: Also gate `f16::erfc()` doctest with `reliable_f16_math` cfg

In rust-lang#136324 the doctest for `f16::erf()` was gated with `reliable_f16_math`. Add the same gate on `f16::erfc()` to avoid:

    rust_out.71e2e529d20ea47d-cgu.0:\
    (.text._ZN8rust_out4main43_doctest_main_library_std_src_f16_rs_1321_017h485f3ffe6bf2a981E+0x38): \
    undefined reference to `__gnu_h2f_ieee'

on MIPS (and maybe other architectures).

r? tgross35
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Feb 18, 2025
Rollup merge of rust-lang#137167 - martn3:reliable_f16_math-f16-erfc, r=tgross35

tests: Also gate `f16::erfc()` doctest with `reliable_f16_math` cfg

In rust-lang#136324 the doctest for `f16::erf()` was gated with `reliable_f16_math`. Add the same gate on `f16::erfc()` to avoid:

    rust_out.71e2e529d20ea47d-cgu.0:\
    (.text._ZN8rust_out4main43_doctest_main_library_std_src_f16_rs_1321_017h485f3ffe6bf2a981E+0x38): \
    undefined reference to `__gnu_h2f_ieee'

on MIPS (and maybe other architectures).

r? tgross35
github-actions bot pushed a commit to model-checking/verify-rust-std that referenced this pull request Feb 22, 2025
Also add
```rust
// #[unstable(feature = "float_gamma", issue = "99842")]
```
to `gamma`-function-related methods on `f16` & `f128`,
as per rust-lang#136324 (comment)
github-actions bot pushed a commit to carolynzech/rust that referenced this pull request Feb 22, 2025
Also add
```rust
// #[unstable(feature = "float_gamma", issue = "99842")]
```
to `gamma`-function-related methods on `f16` & `f128`,
as per rust-lang#136324 (comment)
github-actions bot pushed a commit to tautschnig/verify-rust-std that referenced this pull request Feb 22, 2025
Also add
```rust
// #[unstable(feature = "float_gamma", issue = "99842")]
```
to `gamma`-function-related methods on `f16` & `f128`,
as per rust-lang#136324 (comment)
github-actions bot pushed a commit to thanhnguyen-aws/verify-rust-std that referenced this pull request Feb 22, 2025
Also add
```rust
// #[unstable(feature = "float_gamma", issue = "99842")]
```
to `gamma`-function-related methods on `f16` & `f128`,
as per rust-lang#136324 (comment)
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. 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.