| Age | Commit message (Collapse) | Author | Lines |
|
|
|
|
|
Fix asinh of negative values
Rust's current implementation of asinh has [large errors](https://www.wolframalpha.com/input/?i=arcsinh%28x%29%2C+ln%28x%2B%28x%5E2%2B1%29%5E0.5%29%2C+x+from+-67452095.07139316+to+0) in its negative range. ~These are (mostly) not numerical, but rather seem due to an incorrect implementation.~ This appears to be due to avoidable catastrophic cancellation.
[Playground before/after](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=bd04ae6d86d06612e4e389a8b95d19ab).
[glibc uses](https://github.com/bminor/glibc/blob/81dca813cc35f91414731fdd0ff6b756d5e1827f/sysdeps/ieee754/dbl-64/s_asinh.c#L56) abs here.
Many thanks to @danieldeankon for finding this weird behavior, @jebrosen for diagnosing it, and @toasteater for identifying the probable implementation error!
|
|
|
|
|
|
Implement total_cmp for f32, f64
# Overview
* Implements method `total_cmp` on `f32` and `f64`. This method implements a float comparison that, unlike the standard `partial_cmp`, is total (defined on all values) in accordance to the IEEE 754 (rev 2008) §5.10 `totalOrder` predicate.
* The method has an API similar to `cmp`: `pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { ... }`.
* Implements tests.
* Has documentation.
# Justification for the API
* Total ordering for `f32` and `f64` has been discussed many time before:
* https://internals.rust-lang.org/t/pre-pre-rfc-range-restricting-wrappers-for-floating-point-types/6701
* https://github.com/rust-lang/rfcs/issues/1249
* https://github.com/rust-lang/rust/pull/53938
* https://github.com/rust-lang/rust/issues/5585
* The lack of total ordering leads to frequent complaints, especially from people new to Rust.
* This is an ergonomics issue that needs to be addressed.
* However, the default behaviour of implementing only `PartialOrd` is intentional, as relaxing it might lead to correctness issues.
* Most earlier implementations and discussions have been focusing on a wrapper type that implements trait `Ord`. Such a wrapper type is, however not easy to add because of the large API surface added.
* As a minimal step that hopefully proves uncontroversial, we can implement a stand-alone method `total_cmp` on floating point types.
* I expect adding such methods should be uncontroversial because...
* Similar methods on `f32` and `f64` would be warranted even in case stdlib would provide a wrapper type that implements `Ord` some day.
* It implements functionality that is standardised. (IEEE 754, 2008 rev. §5.10 Note, that the 2019 revision relaxes the ordering. The way we do ordering in this method conforms to the stricter 2008 standard.)
* With stdlib APIs such as `slice::sort_by` and `slice::binary_search_by` that allow users to provide a custom ordering criterion, providing additional helper methods is a minimal way of adding ordering functionality.
* Not also does it allow easily using aforementioned APIs, it also provides an easy and well-tested primitive for the users and library authors to implement an `Ord`-implementing wrapper, if needed.
|
|
|
|
When `x` has large magnitude, `x + ((x * x) + 1.0).sqrt()` approaches
`x + x.abs()`. For negative values of `x`, this leads to catastrophic
cancellation, resulting in large errors or even 0 being passed to
`ln`, producing incorrect results including `-inf`.
Becuase asinh is an odd function, i.e. -asinh(x) = asinh(-x) for all
x, we can avoid the catastrophic cancellation and obtain correct
results by taking the absolute value of `self` for the first
term. `self * self` is always positive, so in effect this gives us
`x.abs().asinh().copysign(x)` which as discussed above is
algebraically equivalent, but is much more accurate.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Don't use f64 shims for f32 cmath functions on non 32-bit x86 MSVC
These shims are only needed on 32-bit x86. Additionally since https://reviews.llvm.org/rL268875 LLVM handles adding the shims itself for the intrinsics.
|
|
Changed docs for f32 and f64.
|
|
|
|
|
|
It is not self-explanatory whether the fract() function inverts the fractional part of negative numbers.
Co-Authored-By: Mateusz Mikuła <mati865@users.noreply.github.com>
|
|
These shims are only needed on 32-bit x86. Additionally since https://reviews.llvm.org/rL268875 LLVM handles adding the shims itself for the intrinsics.
|
|
It hasn't been UB to pass negative numbers to sqrt since https://reviews.llvm.org/D28797 which was included in LLVM 5.
|
|
This commit applies rustfmt with rust-lang/rust's default settings to
files in src/libstd *that are not involved in any currently open PR* to
minimize merge conflicts. THe list of files involved in open PRs was
determined by querying GitHub's GraphQL API with this script:
https://gist.github.com/dtolnay/aa9c34993dc051a4f344d1b10e4487e8
With the list of files from the script in outstanding_files, the
relevant commands were:
$ find src/libstd -name '*.rs' \
| xargs rustfmt --edition=2018 --unstable-features --skip-children
$ rg libstd outstanding_files | xargs git checkout --
Repeating this process several months apart should get us coverage of
most of the rest of libstd.
To confirm no funny business:
$ git checkout $THIS_COMMIT^
$ git show --pretty= --name-only $THIS_COMMIT \
| xargs rustfmt --edition=2018 --unstable-features --skip-children
$ git diff $THIS_COMMIT # there should be no difference
|
|
Add #[must_use] to all functions 'fn(float) -> float'
These are pure functions.
```rust
impl f32/f64 {
fn floor(self) -> Self;
fn ceil(self) -> Self;
fn round(self) -> Self;
fn trunc(self) -> Self;
fn fract(self) -> Self;
fn abs(self) -> Self;
fn signum(self) -> Self;
fn mul_add(self, a: Self, b: Self) -> Self;
fn div_euclid(self, rhs: Self) -> Self;
fn rem_euclid(self, rhs: Self) -> Self;
fn powi(self, n: i32) -> Self;
fn powf(self, n: Self) -> Self;
fn sqrt(self) -> Self;
fn exp(self) -> Self;
fn exp2(self) -> Self;
fn ln(self) -> Self;
fn log(self, base: Self) -> Self;
fn log2(self) -> Self;
fn log10(self) -> Self;
fn abs_sub(self, other: Self) -> Self;
fn cbrt(self) -> Self;
fn hypot(self, other: Self) -> Self;
fn sin(self) -> Self;
fn cos(self) -> Self;
fn tan(self) -> Self;
fn asin(self) -> Self;
fn acos(self) -> Self;
fn atan(self) -> Self;
fn atan2(self, other: Self) -> Self;
fn exp_m1(self) -> Self;
fn ln_1p(self) -> Self;
fn sinh(self) -> Self;
fn cosh(self) -> Self;
fn tanh(self) -> Self;
fn asinh(self) -> Self;
fn acosh(self) -> Self;
fn atanh(self) -> Self;
fn clamp(self, min: Self, max: Self) -> Self;
}
```
Part of #48926
|
|
|
|
|
|
|
|
|
|
Fixed floating point issue with asinh function
This should fixes #63271 , in which `asinh(-0.0)` returns `0.0` instead of `-0.0`.
according to @nagisa
>
>
> IEEE-754 (2008), section 9.2.1:
>
> > For the functions expm1, exp2m1, exp10m1, logp1, log2p1, log10p1, sin, tan, sinPi, atanPi, asin, atan, sinh, tanh, asinh, and atanh, f(+0) is +0 and f(−0) is −0 with no exception.
>
> and
>
> > sinh(±∞) and asinh(±∞) are ±∞ with no exception.
After ensuring that the function `asinh` is the only function affected (functions like `sin`, `sinh` are all based on `cmath` library or `llvm` intrinsics), and that `atanh` always gives the correct result. The only function to modify is `asinh`.
|
|
|
|
f32::consts::PI / 2.0 -> f32::consts::FRAC_PI_2
f32::consts::PI / 4.0 -> f32::consts::FRAC_PI_4
f64::consts::PI / 2.0 -> f64::consts::FRAC_PI_2
f64::consts::PI / 4.0 -> f64::consts::FRAC_PI_4
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Explicitly call out when it returns NaN, adhere to the panic doc
guidelines.
|
|
|
|
|
|
Clarify distinction between floor() and trunc()
`floor()` rounds towards `-INF`, `trunc()` rounds towards 0.
This PR clarifies this in the examples.
|
|
Add clamp for ranges. Implements #44095
Ready for merge
|
|
|
|
|
|
|
|
|
|
|
|
logic is written up in https://github.com/rust-lang/rust/issues/49048
Also, update the documentation slightly
|