Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 554aa5f

Browse files
committedMar 7, 2025·
Auto merge of rust-lang#138087 - tgross35:core-float-math, r=<try>
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
2 parents 98a4878 + 2c6414b commit 554aa5f

File tree

25 files changed

+4611
-3685
lines changed

25 files changed

+4611
-3685
lines changed
 

‎library/core/src/num/f128.rs‎

Lines changed: 377 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,3 +1366,380 @@ impl f128 {
13661366
unsafe { intrinsics::copysignf128(self, sign) }
13671367
}
13681368
}
1369+
1370+
// Functions in this module fall into `core_float_math`
1371+
// FIXME(f16_f128): all doctests must be gated to platforms that have `long double` === `_Float128`
1372+
// due to https://github.com/llvm/llvm-project/issues/44744. aarch64 linux matches this.
1373+
// #[unstable(feature = "core_float_math", issue = "137578")]
1374+
#[cfg(not(test))]
1375+
impl f128 {
1376+
/// Returns the largest integer less than or equal to `self`.
1377+
///
1378+
/// This function always returns the precise result.
1379+
///
1380+
/// # Examples
1381+
///
1382+
/// ```
1383+
/// #![feature(f128)]
1384+
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
1385+
///
1386+
/// let f = 3.7_f128;
1387+
/// let g = 3.0_f128;
1388+
/// let h = -3.7_f128;
1389+
///
1390+
/// assert_eq!(f.floor(), 3.0);
1391+
/// assert_eq!(g.floor(), 3.0);
1392+
/// assert_eq!(h.floor(), -4.0);
1393+
/// # }
1394+
/// ```
1395+
#[inline]
1396+
#[rustc_allow_incoherent_impl]
1397+
#[unstable(feature = "f128", issue = "116909")]
1398+
#[must_use = "method returns a new number and does not mutate the original value"]
1399+
pub fn floor(self) -> f128 {
1400+
// SAFETY: intrinsic with no preconditions
1401+
unsafe { intrinsics::floorf128(self) }
1402+
}
1403+
1404+
/// Returns the smallest integer greater than or equal to `self`.
1405+
///
1406+
/// This function always returns the precise result.
1407+
///
1408+
/// # Examples
1409+
///
1410+
/// ```
1411+
/// #![feature(f128)]
1412+
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
1413+
///
1414+
/// let f = 3.01_f128;
1415+
/// let g = 4.0_f128;
1416+
///
1417+
/// assert_eq!(f.ceil(), 4.0);
1418+
/// assert_eq!(g.ceil(), 4.0);
1419+
/// # }
1420+
/// ```
1421+
#[inline]
1422+
#[doc(alias = "ceiling")]
1423+
#[rustc_allow_incoherent_impl]
1424+
#[unstable(feature = "f128", issue = "116909")]
1425+
#[must_use = "method returns a new number and does not mutate the original value"]
1426+
pub fn ceil(self) -> f128 {
1427+
// SAFETY: intrinsic with no preconditions
1428+
unsafe { intrinsics::ceilf128(self) }
1429+
}
1430+
1431+
/// Returns the nearest integer to `self`. If a value is half-way between two
1432+
/// integers, round away from `0.0`.
1433+
///
1434+
/// This function always returns the precise result.
1435+
///
1436+
/// # Examples
1437+
///
1438+
/// ```
1439+
/// #![feature(f128)]
1440+
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
1441+
///
1442+
/// let f = 3.3_f128;
1443+
/// let g = -3.3_f128;
1444+
/// let h = -3.7_f128;
1445+
/// let i = 3.5_f128;
1446+
/// let j = 4.5_f128;
1447+
///
1448+
/// assert_eq!(f.round(), 3.0);
1449+
/// assert_eq!(g.round(), -3.0);
1450+
/// assert_eq!(h.round(), -4.0);
1451+
/// assert_eq!(i.round(), 4.0);
1452+
/// assert_eq!(j.round(), 5.0);
1453+
/// # }
1454+
/// ```
1455+
#[inline]
1456+
#[rustc_allow_incoherent_impl]
1457+
#[unstable(feature = "f128", issue = "116909")]
1458+
#[must_use = "method returns a new number and does not mutate the original value"]
1459+
pub fn round(self) -> f128 {
1460+
// SAFETY: intrinsic with no preconditions
1461+
unsafe { intrinsics::roundf128(self) }
1462+
}
1463+
1464+
/// Returns the nearest integer to a number. Rounds half-way cases to the number
1465+
/// with an even least significant digit.
1466+
///
1467+
/// This function always returns the precise result.
1468+
///
1469+
/// # Examples
1470+
///
1471+
/// ```
1472+
/// #![feature(f128)]
1473+
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
1474+
///
1475+
/// let f = 3.3_f128;
1476+
/// let g = -3.3_f128;
1477+
/// let h = 3.5_f128;
1478+
/// let i = 4.5_f128;
1479+
///
1480+
/// assert_eq!(f.round_ties_even(), 3.0);
1481+
/// assert_eq!(g.round_ties_even(), -3.0);
1482+
/// assert_eq!(h.round_ties_even(), 4.0);
1483+
/// assert_eq!(i.round_ties_even(), 4.0);
1484+
/// # }
1485+
/// ```
1486+
#[inline]
1487+
#[rustc_allow_incoherent_impl]
1488+
#[unstable(feature = "f128", issue = "116909")]
1489+
#[must_use = "method returns a new number and does not mutate the original value"]
1490+
pub fn round_ties_even(self) -> f128 {
1491+
intrinsics::round_ties_even_f128(self)
1492+
}
1493+
1494+
/// Returns the integer part of `self`.
1495+
/// This means that non-integer numbers are always truncated towards zero.
1496+
///
1497+
/// This function always returns the precise result.
1498+
///
1499+
/// # Examples
1500+
///
1501+
/// ```
1502+
/// #![feature(f128)]
1503+
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
1504+
///
1505+
/// let f = 3.7_f128;
1506+
/// let g = 3.0_f128;
1507+
/// let h = -3.7_f128;
1508+
///
1509+
/// assert_eq!(f.trunc(), 3.0);
1510+
/// assert_eq!(g.trunc(), 3.0);
1511+
/// assert_eq!(h.trunc(), -3.0);
1512+
/// # }
1513+
/// ```
1514+
#[inline]
1515+
#[doc(alias = "truncate")]
1516+
#[rustc_allow_incoherent_impl]
1517+
#[unstable(feature = "f128", issue = "116909")]
1518+
#[must_use = "method returns a new number and does not mutate the original value"]
1519+
pub fn trunc(self) -> f128 {
1520+
// SAFETY: intrinsic with no preconditions
1521+
unsafe { intrinsics::truncf128(self) }
1522+
}
1523+
1524+
/// Returns the fractional part of `self`.
1525+
///
1526+
/// This function always returns the precise result.
1527+
///
1528+
/// # Examples
1529+
///
1530+
/// ```
1531+
/// #![feature(f128)]
1532+
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
1533+
///
1534+
/// let x = 3.6_f128;
1535+
/// let y = -3.6_f128;
1536+
/// let abs_difference_x = (x.fract() - 0.6).abs();
1537+
/// let abs_difference_y = (y.fract() - (-0.6)).abs();
1538+
///
1539+
/// assert!(abs_difference_x <= f128::EPSILON);
1540+
/// assert!(abs_difference_y <= f128::EPSILON);
1541+
/// # }
1542+
/// ```
1543+
#[inline]
1544+
#[rustc_allow_incoherent_impl]
1545+
#[unstable(feature = "f128", issue = "116909")]
1546+
#[must_use = "method returns a new number and does not mutate the original value"]
1547+
pub fn fract(self) -> f128 {
1548+
self - self.trunc()
1549+
}
1550+
1551+
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
1552+
/// error, yielding a more accurate result than an unfused multiply-add.
1553+
///
1554+
/// Using `mul_add` *may* be more performant than an unfused multiply-add if
1555+
/// the target architecture has a dedicated `fma` CPU instruction. However,
1556+
/// this is not always true, and will be heavily dependant on designing
1557+
/// algorithms with specific target hardware in mind.
1558+
///
1559+
/// # Precision
1560+
///
1561+
/// The result of this operation is guaranteed to be the rounded
1562+
/// infinite-precision result. It is specified by IEEE 754 as
1563+
/// `fusedMultiplyAdd` and guaranteed not to change.
1564+
///
1565+
/// # Examples
1566+
///
1567+
/// ```
1568+
/// #![feature(f128)]
1569+
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
1570+
///
1571+
/// let m = 10.0_f128;
1572+
/// let x = 4.0_f128;
1573+
/// let b = 60.0_f128;
1574+
///
1575+
/// assert_eq!(m.mul_add(x, b), 100.0);
1576+
/// assert_eq!(m * x + b, 100.0);
1577+
///
1578+
/// let one_plus_eps = 1.0_f128 + f128::EPSILON;
1579+
/// let one_minus_eps = 1.0_f128 - f128::EPSILON;
1580+
/// let minus_one = -1.0_f128;
1581+
///
1582+
/// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
1583+
/// assert_eq!(one_plus_eps.mul_add(one_minus_eps, minus_one), -f128::EPSILON * f128::EPSILON);
1584+
/// // Different rounding with the non-fused multiply and add.
1585+
/// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
1586+
/// # }
1587+
/// ```
1588+
#[inline]
1589+
#[rustc_allow_incoherent_impl]
1590+
#[doc(alias = "fmaf128", alias = "fusedMultiplyAdd")]
1591+
#[unstable(feature = "f128", issue = "116909")]
1592+
#[must_use = "method returns a new number and does not mutate the original value"]
1593+
pub fn mul_add(self, a: f128, b: f128) -> f128 {
1594+
// SAFETY: intrinsic with no preconditions
1595+
unsafe { intrinsics::fmaf128(self, a, b) }
1596+
}
1597+
1598+
/// Calculates Euclidean division, the matching method for `rem_euclid`.
1599+
///
1600+
/// This computes the integer `n` such that
1601+
/// `self = n * rhs + self.rem_euclid(rhs)`.
1602+
/// In other words, the result is `self / rhs` rounded to the integer `n`
1603+
/// such that `self >= n * rhs`.
1604+
///
1605+
/// # Precision
1606+
///
1607+
/// The result of this operation is guaranteed to be the rounded
1608+
/// infinite-precision result.
1609+
///
1610+
/// # Examples
1611+
///
1612+
/// ```
1613+
/// #![feature(f128)]
1614+
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
1615+
///
1616+
/// let a: f128 = 7.0;
1617+
/// let b = 4.0;
1618+
/// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
1619+
/// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0
1620+
/// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
1621+
/// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
1622+
/// # }
1623+
/// ```
1624+
#[inline]
1625+
#[rustc_allow_incoherent_impl]
1626+
#[unstable(feature = "f128", issue = "116909")]
1627+
#[must_use = "method returns a new number and does not mutate the original value"]
1628+
pub fn div_euclid(self, rhs: f128) -> f128 {
1629+
let q = (self / rhs).trunc();
1630+
if self % rhs < 0.0 {
1631+
return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
1632+
}
1633+
q
1634+
}
1635+
1636+
/// Calculates the least nonnegative remainder of `self (mod rhs)`.
1637+
///
1638+
/// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
1639+
/// most cases. However, due to a floating point round-off error it can
1640+
/// result in `r == rhs.abs()`, violating the mathematical definition, if
1641+
/// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
1642+
/// This result is not an element of the function's codomain, but it is the
1643+
/// closest floating point number in the real numbers and thus fulfills the
1644+
/// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
1645+
/// approximately.
1646+
///
1647+
/// # Precision
1648+
///
1649+
/// The result of this operation is guaranteed to be the rounded
1650+
/// infinite-precision result.
1651+
///
1652+
/// # Examples
1653+
///
1654+
/// ```
1655+
/// #![feature(f128)]
1656+
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
1657+
///
1658+
/// let a: f128 = 7.0;
1659+
/// let b = 4.0;
1660+
/// assert_eq!(a.rem_euclid(b), 3.0);
1661+
/// assert_eq!((-a).rem_euclid(b), 1.0);
1662+
/// assert_eq!(a.rem_euclid(-b), 3.0);
1663+
/// assert_eq!((-a).rem_euclid(-b), 1.0);
1664+
/// // limitation due to round-off error
1665+
/// assert!((-f128::EPSILON).rem_euclid(3.0) != 0.0);
1666+
/// # }
1667+
/// ```
1668+
#[inline]
1669+
#[rustc_allow_incoherent_impl]
1670+
#[doc(alias = "modulo", alias = "mod")]
1671+
#[unstable(feature = "f128", issue = "116909")]
1672+
#[must_use = "method returns a new number and does not mutate the original value"]
1673+
pub fn rem_euclid(self, rhs: f128) -> f128 {
1674+
let r = self % rhs;
1675+
if r < 0.0 { r + rhs.abs() } else { r }
1676+
}
1677+
1678+
/// Raises a number to an integer power.
1679+
///
1680+
/// Using this function is generally faster than using `powf`.
1681+
/// It might have a different sequence of rounding operations than `powf`,
1682+
/// so the results are not guaranteed to agree.
1683+
///
1684+
/// # Unspecified precision
1685+
///
1686+
/// The precision of this function is non-deterministic. This means it varies by platform,
1687+
/// Rust version, and can even differ within the same execution from one invocation to the next.
1688+
///
1689+
/// # Examples
1690+
///
1691+
/// ```
1692+
/// #![feature(f128)]
1693+
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
1694+
///
1695+
/// let x = 2.0_f128;
1696+
/// let abs_difference = (x.powi(2) - (x * x)).abs();
1697+
/// assert!(abs_difference <= f128::EPSILON);
1698+
///
1699+
/// assert_eq!(f128::powi(f128::NAN, 0), 1.0);
1700+
/// # }
1701+
/// ```
1702+
#[inline]
1703+
#[rustc_allow_incoherent_impl]
1704+
#[unstable(feature = "f128", issue = "116909")]
1705+
#[must_use = "method returns a new number and does not mutate the original value"]
1706+
pub fn powi(self, n: i32) -> f128 {
1707+
// SAFETY: intrinsic with no preconditions
1708+
unsafe { intrinsics::powif128(self, n) }
1709+
}
1710+
1711+
/// Returns the square root of a number.
1712+
///
1713+
/// Returns NaN if `self` is a negative number other than `-0.0`.
1714+
///
1715+
/// # Precision
1716+
///
1717+
/// The result of this operation is guaranteed to be the rounded
1718+
/// infinite-precision result. It is specified by IEEE 754 as `squareRoot`
1719+
/// and guaranteed not to change.
1720+
///
1721+
/// # Examples
1722+
///
1723+
/// ```
1724+
/// #![feature(f128)]
1725+
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
1726+
///
1727+
/// let positive = 4.0_f128;
1728+
/// let negative = -4.0_f128;
1729+
/// let negative_zero = -0.0_f128;
1730+
///
1731+
/// assert_eq!(positive.sqrt(), 2.0);
1732+
/// assert!(negative.sqrt().is_nan());
1733+
/// assert!(negative_zero.sqrt() == negative_zero);
1734+
/// # }
1735+
/// ```
1736+
#[inline]
1737+
#[doc(alias = "squareRoot")]
1738+
#[rustc_allow_incoherent_impl]
1739+
#[unstable(feature = "f128", issue = "116909")]
1740+
#[must_use = "method returns a new number and does not mutate the original value"]
1741+
pub fn sqrt(self) -> f128 {
1742+
// SAFETY: intrinsic with no preconditions
1743+
unsafe { intrinsics::sqrtf128(self) }
1744+
}
1745+
}

‎library/core/src/num/f16.rs‎

Lines changed: 410 additions & 0 deletions
Large diffs are not rendered by default.

‎library/core/src/num/f32.rs‎

Lines changed: 411 additions & 1 deletion
Large diffs are not rendered by default.

‎library/core/src/num/f64.rs‎

Lines changed: 404 additions & 1 deletion
Large diffs are not rendered by default.

‎library/core/src/num/libm.rs‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//! Bindings to math functions provided by the system `libm` or by the `libm` crate, exposed
2+
//! via `compiler-builtins`.
3+
4+
// These symbols are all defined by `libm`, or by `compiler-builtins` on unsupported platforms.
5+
unsafe extern "C" {
6+
pub(crate) fn cbrt(n: f64) -> f64;
7+
pub(crate) fn cbrtf(n: f32) -> f32;
8+
pub(crate) fn fdim(a: f64, b: f64) -> f64;
9+
pub(crate) fn fdimf(a: f32, b: f32) -> f32;
10+
}

‎library/core/src/num/mod.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ mod uint_macros; // import uint_impl!
4646
mod error;
4747
mod int_log10;
4848
mod int_sqrt;
49+
pub(crate) mod libm;
4950
mod nonzero;
5051
mod overflow_panic;
5152
mod saturating;

‎library/coretests/build.rs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
mod build_shared {
2+
include!("../std/build_shared.rs");
3+
}
4+
5+
fn main() {
6+
let cfg = build_shared::Config::from_env();
7+
build_shared::configure_f16_f128(&cfg);
8+
}

‎library/coretests/tests/floats/f128.rs‎

Lines changed: 718 additions & 0 deletions
Large diffs are not rendered by default.

‎library/coretests/tests/floats/f16.rs‎

Lines changed: 701 additions & 0 deletions
Large diffs are not rendered by default.

‎library/coretests/tests/floats/f32.rs‎

Lines changed: 677 additions & 0 deletions
Large diffs are not rendered by default.

‎library/coretests/tests/floats/f64.rs‎

Lines changed: 659 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use std::fmt;
2+
use std::ops::{Add, Div, Mul, Rem, Sub};
3+
4+
/// Verify that floats are within a tolerance of each other, 1.0e-6 by default.
5+
macro_rules! assert_approx_eq {
6+
($a:expr, $b:expr) => {{ assert_approx_eq!($a, $b, 1.0e-6) }};
7+
($a:expr, $b:expr, $lim:expr) => {{
8+
let (a, b) = (&$a, &$b);
9+
let diff = (*a - *b).abs();
10+
assert!(
11+
diff < $lim,
12+
"{a:?} is not approximately equal to {b:?} (threshold {lim:?}, difference {diff:?})",
13+
lim = $lim
14+
);
15+
}};
16+
}
17+
18+
/// Helper function for testing numeric operations
19+
pub fn test_num<T>(ten: T, two: T)
20+
where
21+
T: PartialEq
22+
+ Add<Output = T>
23+
+ Sub<Output = T>
24+
+ Mul<Output = T>
25+
+ Div<Output = T>
26+
+ Rem<Output = T>
27+
+ fmt::Debug
28+
+ Copy,
29+
{
30+
assert_eq!(ten.add(two), ten + two);
31+
assert_eq!(ten.sub(two), ten - two);
32+
assert_eq!(ten.mul(two), ten * two);
33+
assert_eq!(ten.div(two), ten / two);
34+
assert_eq!(ten.rem(two), ten % two);
35+
}
36+
37+
mod f128;
38+
mod f16;
39+
mod f32;
40+
mod f64;

‎library/coretests/tests/lib.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#![feature(const_eval_select)]
1919
#![feature(const_swap_nonoverlapping)]
2020
#![feature(const_trait_impl)]
21+
#![feature(core_float_math)]
2122
#![feature(core_intrinsics)]
2223
#![feature(core_intrinsics_fallbacks)]
2324
#![feature(core_io_borrowed_buf)]
@@ -30,6 +31,8 @@
3031
#![feature(exact_size_is_empty)]
3132
#![feature(extend_one)]
3233
#![feature(extern_types)]
34+
#![feature(f128)]
35+
#![feature(f16)]
3336
#![feature(float_minimum_maximum)]
3437
#![feature(flt2dec)]
3538
#![feature(fmt_internals)]
@@ -144,6 +147,7 @@ mod cmp;
144147
mod const_ptr;
145148
mod convert;
146149
mod ffi;
150+
mod floats;
147151
mod fmt;
148152
mod future;
149153
mod hash;

‎library/std/build.rs‎

Lines changed: 7 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,13 @@
11
use std::env;
22

3+
use build_shared::Config;
4+
mod build_shared;
5+
36
fn main() {
47
println!("cargo:rerun-if-changed=build.rs");
5-
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").expect("CARGO_CFG_TARGET_ARCH was not set");
6-
let target_os = env::var("CARGO_CFG_TARGET_OS").expect("CARGO_CFG_TARGET_OS was not set");
7-
let target_vendor =
8-
env::var("CARGO_CFG_TARGET_VENDOR").expect("CARGO_CFG_TARGET_VENDOR was not set");
9-
let target_env = env::var("CARGO_CFG_TARGET_ENV").expect("CARGO_CFG_TARGET_ENV was not set");
10-
let target_abi = env::var("CARGO_CFG_TARGET_ABI").expect("CARGO_CFG_TARGET_ABI was not set");
11-
let target_pointer_width: u32 = env::var("CARGO_CFG_TARGET_POINTER_WIDTH")
12-
.expect("CARGO_CFG_TARGET_POINTER_WIDTH was not set")
13-
.parse()
14-
.unwrap();
15-
let target_features: Vec<_> = env::var("CARGO_CFG_TARGET_FEATURE")
16-
.unwrap_or_default()
17-
.split(",")
18-
.map(ToOwned::to_owned)
19-
.collect();
20-
let is_miri = env::var_os("CARGO_CFG_MIRI").is_some();
8+
9+
let cfg = Config::from_env();
10+
let Config { ref target_arch, ref target_os, ref target_vendor, ref target_env, .. } = cfg;
2111

2212
println!("cargo:rustc-check-cfg=cfg(netbsd10)");
2313
if target_os == "netbsd" && env::var("RUSTC_STD_NETBSD10").is_ok() {
@@ -84,110 +74,5 @@ fn main() {
8474

8575
println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap());
8676

87-
// Emit these on platforms that have no known ABI bugs, LLVM selection bugs, lowering bugs,
88-
// missing symbols, or other problems, to determine when tests get run.
89-
// If more broken platforms are found, please update the tracking issue at
90-
// <https://github.com/rust-lang/rust/issues/116909>
91-
//
92-
// Some of these match arms are redundant; the goal is to separate reasons that the type is
93-
// unreliable, even when multiple reasons might fail the same platform.
94-
println!("cargo:rustc-check-cfg=cfg(reliable_f16)");
95-
println!("cargo:rustc-check-cfg=cfg(reliable_f128)");
96-
97-
// This is a step beyond only having the types and basic functions available. Math functions
98-
// aren't consistently available or correct.
99-
println!("cargo:rustc-check-cfg=cfg(reliable_f16_math)");
100-
println!("cargo:rustc-check-cfg=cfg(reliable_f128_math)");
101-
102-
let has_reliable_f16 = match (target_arch.as_str(), target_os.as_str()) {
103-
// We can always enable these in Miri as that is not affected by codegen bugs.
104-
_ if is_miri => true,
105-
// Selection failure <https://github.com/llvm/llvm-project/issues/50374>
106-
("s390x", _) => false,
107-
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
108-
("arm64ec", _) => false,
109-
// LLVM crash <https://github.com/llvm/llvm-project/issues/129394>
110-
("aarch64", _) if !target_features.iter().any(|f| f == "neon") => false,
111-
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
112-
("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
113-
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
114-
("csky", _) => false,
115-
("hexagon", _) => false,
116-
("loongarch64", _) => false,
117-
("powerpc" | "powerpc64", _) => false,
118-
("sparc" | "sparc64", _) => false,
119-
("wasm32" | "wasm64", _) => false,
120-
// `f16` support only requires that symbols converting to and from `f32` are available. We
121-
// provide these in `compiler-builtins`, so `f16` should be available on all platforms that
122-
// do not have other ABI issues or LLVM crashes.
123-
_ => true,
124-
};
125-
126-
let has_reliable_f128 = match (target_arch.as_str(), target_os.as_str()) {
127-
// We can always enable these in Miri as that is not affected by codegen bugs.
128-
_ if is_miri => true,
129-
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
130-
("arm64ec", _) => false,
131-
// Selection bug <https://github.com/llvm/llvm-project/issues/96432>
132-
("mips64" | "mips64r6", _) => false,
133-
// Selection bug <https://github.com/llvm/llvm-project/issues/95471>
134-
("nvptx64", _) => false,
135-
// ABI bugs <https://github.com/rust-lang/rust/issues/125109> et al. (full
136-
// list at <https://github.com/rust-lang/rust/issues/116909>)
137-
("powerpc" | "powerpc64", _) => false,
138-
// ABI unsupported <https://github.com/llvm/llvm-project/issues/41838>
139-
("sparc", _) => false,
140-
// Stack alignment bug <https://github.com/llvm/llvm-project/issues/77401>. NB: tests may
141-
// not fail if our compiler-builtins is linked.
142-
("x86", _) => false,
143-
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
144-
("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
145-
// There are no known problems on other platforms, so the only requirement is that symbols
146-
// are available. `compiler-builtins` provides all symbols required for core `f128`
147-
// support, so this should work for everything else.
148-
_ => true,
149-
};
150-
151-
// Configure platforms that have reliable basics but may have unreliable math.
152-
153-
// LLVM is currently adding missing routines, <https://github.com/llvm/llvm-project/issues/93566>
154-
let has_reliable_f16_math = has_reliable_f16
155-
&& match (target_arch.as_str(), target_os.as_str()) {
156-
// FIXME: Disabled on Miri as the intrinsics are not implemented yet.
157-
_ if is_miri => false,
158-
// x86 has a crash for `powi`: <https://github.com/llvm/llvm-project/issues/105747>
159-
("x86" | "x86_64", _) => false,
160-
// Assume that working `f16` means working `f16` math for most platforms, since
161-
// operations just go through `f32`.
162-
_ => true,
163-
};
164-
165-
let has_reliable_f128_math = has_reliable_f128
166-
&& match (target_arch.as_str(), target_os.as_str()) {
167-
// FIXME: Disabled on Miri as the intrinsics are not implemented yet.
168-
_ if is_miri => false,
169-
// LLVM lowers `fp128` math to `long double` symbols even on platforms where
170-
// `long double` is not IEEE binary128. See
171-
// <https://github.com/llvm/llvm-project/issues/44744>.
172-
//
173-
// This rules out anything that doesn't have `long double` = `binary128`; <= 32 bits
174-
// (ld is `f64`), anything other than Linux (Windows and MacOS use `f64`), and `x86`
175-
// (ld is 80-bit extended precision).
176-
("x86_64", _) => false,
177-
(_, "linux") if target_pointer_width == 64 => true,
178-
_ => false,
179-
};
180-
181-
if has_reliable_f16 {
182-
println!("cargo:rustc-cfg=reliable_f16");
183-
}
184-
if has_reliable_f128 {
185-
println!("cargo:rustc-cfg=reliable_f128");
186-
}
187-
if has_reliable_f16_math {
188-
println!("cargo:rustc-cfg=reliable_f16_math");
189-
}
190-
if has_reliable_f128_math {
191-
println!("cargo:rustc-cfg=reliable_f128_math");
192-
}
77+
build_shared::configure_f16_f128(&cfg);
19378
}

‎library/std/build_shared.rs‎

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// This portion of configuration is shared between `std` and `coretests`.
2+
3+
use std::env;
4+
5+
#[allow(dead_code)] // Not all importers of this file use all fields
6+
pub struct Config {
7+
pub target_arch: String,
8+
pub target_os: String,
9+
pub target_vendor: String,
10+
pub target_env: String,
11+
pub target_abi: String,
12+
pub target_pointer_width: u32,
13+
pub target_features: Vec<String>,
14+
pub is_miri: bool,
15+
}
16+
17+
impl Config {
18+
pub fn from_env() -> Self {
19+
Self {
20+
target_arch: env::var("CARGO_CFG_TARGET_ARCH")
21+
.expect("CARGO_CFG_TARGET_ARCH was not set"),
22+
target_os: env::var("CARGO_CFG_TARGET_OS").expect("CARGO_CFG_TARGET_OS was not set"),
23+
target_vendor: env::var("CARGO_CFG_TARGET_VENDOR")
24+
.expect("CARGO_CFG_TARGET_VENDOR was not set"),
25+
target_env: env::var("CARGO_CFG_TARGET_ENV").expect("CARGO_CFG_TARGET_ENV was not set"),
26+
target_abi: env::var("CARGO_CFG_TARGET_ABI").expect("CARGO_CFG_TARGET_ABI was not set"),
27+
target_pointer_width: env::var("CARGO_CFG_TARGET_POINTER_WIDTH")
28+
.expect("CARGO_CFG_TARGET_POINTER_WIDTH was not set")
29+
.parse()
30+
.unwrap(),
31+
target_features: env::var("CARGO_CFG_TARGET_FEATURE")
32+
.unwrap_or_default()
33+
.split(",")
34+
.map(ToOwned::to_owned)
35+
.collect(),
36+
is_miri: env::var_os("CARGO_CFG_MIRI").is_some(),
37+
}
38+
}
39+
}
40+
41+
pub fn configure_f16_f128(cfg: &Config) {
42+
// Emit these on platforms that have no known ABI bugs, LLVM selection bugs, lowering bugs,
43+
// missing symbols, or other problems, to determine when tests get run.
44+
// If more broken platforms are found, please update the tracking issue at
45+
// <https://github.com/rust-lang/rust/issues/116909>
46+
//
47+
// Some of these match arms are redundant; the goal is to separate reasons that the type is
48+
// unreliable, even when multiple reasons might fail the same platform.
49+
println!("cargo:rustc-check-cfg=cfg(reliable_f16)");
50+
println!("cargo:rustc-check-cfg=cfg(reliable_f128)");
51+
52+
// This is a step beyond only having the types and basic functions available. Math functions
53+
// aren't consistently available or correct.
54+
println!("cargo:rustc-check-cfg=cfg(reliable_f16_math)");
55+
println!("cargo:rustc-check-cfg=cfg(reliable_f128_math)");
56+
57+
let target_arch = cfg.target_arch.as_str();
58+
let target_os = cfg.target_os.as_str();
59+
60+
let has_reliable_f16 = match (target_arch, target_os) {
61+
// We can always enable these in Miri as that is not affected by codegen bugs.
62+
_ if cfg.is_miri => true,
63+
// Selection failure <https://github.com/llvm/llvm-project/issues/50374>
64+
("s390x", _) => false,
65+
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
66+
("arm64ec", _) => false,
67+
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
68+
("x86_64", "windows") if cfg.target_env == "gnu" && cfg.target_abi != "llvm" => false,
69+
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
70+
("csky", _) => false,
71+
("hexagon", _) => false,
72+
("loongarch64", _) => false,
73+
("mips" | "mips64" | "mips32r6" | "mips64r6", _) => false,
74+
("powerpc" | "powerpc64", _) => false,
75+
("sparc" | "sparc64", _) => false,
76+
("wasm32" | "wasm64", _) => false,
77+
// `f16` support only requires that symbols converting to and from `f32` are available. We
78+
// provide these in `compiler-builtins`, so `f16` should be available on all platforms that
79+
// do not have other ABI issues or LLVM crashes.
80+
_ => true,
81+
};
82+
83+
let has_reliable_f128 = match (target_arch, target_os) {
84+
// We can always enable these in Miri as that is not affected by codegen bugs.
85+
_ if cfg.is_miri => true,
86+
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
87+
("arm64ec", _) => false,
88+
// Selection bug <https://github.com/llvm/llvm-project/issues/96432>
89+
("mips64" | "mips64r6", _) => false,
90+
// Selection bug <https://github.com/llvm/llvm-project/issues/95471>
91+
("nvptx64", _) => false,
92+
// ABI bugs <https://github.com/rust-lang/rust/issues/125109> et al. (full
93+
// list at <https://github.com/rust-lang/rust/issues/116909>)
94+
("powerpc" | "powerpc64", _) => false,
95+
// ABI unsupported <https://github.com/llvm/llvm-project/issues/41838>
96+
("sparc", _) => false,
97+
// Stack alignment bug <https://github.com/llvm/llvm-project/issues/77401>. NB: tests may
98+
// not fail if our compiler-builtins is linked.
99+
("x86", _) => false,
100+
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
101+
("x86_64", "windows") if cfg.target_env == "gnu" && cfg.target_abi != "llvm" => false,
102+
// There are no known problems on other platforms, so the only requirement is that symbols
103+
// are available. `compiler-builtins` provides all symbols required for core `f128`
104+
// support, so this should work for everything else.
105+
_ => true,
106+
};
107+
108+
// Configure platforms that have reliable basics but may have unreliable math.
109+
110+
// LLVM is currently adding missing routines, <https://github.com/llvm/llvm-project/issues/93566>
111+
let has_reliable_f16_math = has_reliable_f16
112+
&& match (target_arch, target_os) {
113+
// FIXME: Disabled on Miri as the intrinsics are not implemented yet.
114+
_ if cfg.is_miri => false,
115+
// x86 has a crash for `powi`: <https://github.com/llvm/llvm-project/issues/105747>
116+
("x86" | "x86_64", _) => false,
117+
// Assume that working `f16` means working `f16` math for most platforms, since
118+
// operations just go through `f32`.
119+
_ => true,
120+
};
121+
122+
let has_reliable_f128_math = has_reliable_f128
123+
&& match (target_arch, target_os) {
124+
// FIXME: Disabled on Miri as the intrinsics are not implemented yet.
125+
_ if cfg.is_miri => false,
126+
// LLVM lowers `fp128` math to `long double` symbols even on platforms where
127+
// `long double` is not IEEE binary128. See
128+
// <https://github.com/llvm/llvm-project/issues/44744>.
129+
//
130+
// This rules out anything that doesn't have `long double` = `binary128`; <= 32 bits
131+
// (ld is `f64`), anything other than Linux (Windows and MacOS use `f64`), and `x86`
132+
// (ld is 80-bit extended precision).
133+
("x86_64", _) => false,
134+
(_, "linux") if cfg.target_pointer_width == 64 => true,
135+
_ => false,
136+
};
137+
138+
if has_reliable_f16 {
139+
println!("cargo:rustc-cfg=reliable_f16");
140+
}
141+
if has_reliable_f128 {
142+
println!("cargo:rustc-cfg=reliable_f128");
143+
}
144+
if has_reliable_f16_math {
145+
println!("cargo:rustc-cfg=reliable_f16_math");
146+
}
147+
if has_reliable_f128_math {
148+
println!("cargo:rustc-cfg=reliable_f128_math");
149+
}
150+
}

‎library/std/src/f128.rs‎

Lines changed: 0 additions & 363 deletions
Original file line numberDiff line numberDiff line change
@@ -14,335 +14,6 @@ use crate::sys::cmath;
1414

1515
#[cfg(not(test))]
1616
impl f128 {
17-
/// Returns the largest integer less than or equal to `self`.
18-
///
19-
/// This function always returns the precise result.
20-
///
21-
/// # Examples
22-
///
23-
/// ```
24-
/// #![feature(f128)]
25-
/// # #[cfg(reliable_f128_math)] {
26-
///
27-
/// let f = 3.7_f128;
28-
/// let g = 3.0_f128;
29-
/// let h = -3.7_f128;
30-
///
31-
/// assert_eq!(f.floor(), 3.0);
32-
/// assert_eq!(g.floor(), 3.0);
33-
/// assert_eq!(h.floor(), -4.0);
34-
/// # }
35-
/// ```
36-
#[inline]
37-
#[rustc_allow_incoherent_impl]
38-
#[unstable(feature = "f128", issue = "116909")]
39-
#[must_use = "method returns a new number and does not mutate the original value"]
40-
pub fn floor(self) -> f128 {
41-
unsafe { intrinsics::floorf128(self) }
42-
}
43-
44-
/// Returns the smallest integer greater than or equal to `self`.
45-
///
46-
/// This function always returns the precise result.
47-
///
48-
/// # Examples
49-
///
50-
/// ```
51-
/// #![feature(f128)]
52-
/// # #[cfg(reliable_f128_math)] {
53-
///
54-
/// let f = 3.01_f128;
55-
/// let g = 4.0_f128;
56-
///
57-
/// assert_eq!(f.ceil(), 4.0);
58-
/// assert_eq!(g.ceil(), 4.0);
59-
/// # }
60-
/// ```
61-
#[inline]
62-
#[doc(alias = "ceiling")]
63-
#[rustc_allow_incoherent_impl]
64-
#[unstable(feature = "f128", issue = "116909")]
65-
#[must_use = "method returns a new number and does not mutate the original value"]
66-
pub fn ceil(self) -> f128 {
67-
unsafe { intrinsics::ceilf128(self) }
68-
}
69-
70-
/// Returns the nearest integer to `self`. If a value is half-way between two
71-
/// integers, round away from `0.0`.
72-
///
73-
/// This function always returns the precise result.
74-
///
75-
/// # Examples
76-
///
77-
/// ```
78-
/// #![feature(f128)]
79-
/// # #[cfg(reliable_f128_math)] {
80-
///
81-
/// let f = 3.3_f128;
82-
/// let g = -3.3_f128;
83-
/// let h = -3.7_f128;
84-
/// let i = 3.5_f128;
85-
/// let j = 4.5_f128;
86-
///
87-
/// assert_eq!(f.round(), 3.0);
88-
/// assert_eq!(g.round(), -3.0);
89-
/// assert_eq!(h.round(), -4.0);
90-
/// assert_eq!(i.round(), 4.0);
91-
/// assert_eq!(j.round(), 5.0);
92-
/// # }
93-
/// ```
94-
#[inline]
95-
#[rustc_allow_incoherent_impl]
96-
#[unstable(feature = "f128", issue = "116909")]
97-
#[must_use = "method returns a new number and does not mutate the original value"]
98-
pub fn round(self) -> f128 {
99-
unsafe { intrinsics::roundf128(self) }
100-
}
101-
102-
/// Returns the nearest integer to a number. Rounds half-way cases to the number
103-
/// with an even least significant digit.
104-
///
105-
/// This function always returns the precise result.
106-
///
107-
/// # Examples
108-
///
109-
/// ```
110-
/// #![feature(f128)]
111-
/// # #[cfg(reliable_f128_math)] {
112-
///
113-
/// let f = 3.3_f128;
114-
/// let g = -3.3_f128;
115-
/// let h = 3.5_f128;
116-
/// let i = 4.5_f128;
117-
///
118-
/// assert_eq!(f.round_ties_even(), 3.0);
119-
/// assert_eq!(g.round_ties_even(), -3.0);
120-
/// assert_eq!(h.round_ties_even(), 4.0);
121-
/// assert_eq!(i.round_ties_even(), 4.0);
122-
/// # }
123-
/// ```
124-
#[inline]
125-
#[rustc_allow_incoherent_impl]
126-
#[unstable(feature = "f128", issue = "116909")]
127-
#[must_use = "method returns a new number and does not mutate the original value"]
128-
pub fn round_ties_even(self) -> f128 {
129-
intrinsics::round_ties_even_f128(self)
130-
}
131-
132-
/// Returns the integer part of `self`.
133-
/// This means that non-integer numbers are always truncated towards zero.
134-
///
135-
/// This function always returns the precise result.
136-
///
137-
/// # Examples
138-
///
139-
/// ```
140-
/// #![feature(f128)]
141-
/// # #[cfg(reliable_f128_math)] {
142-
///
143-
/// let f = 3.7_f128;
144-
/// let g = 3.0_f128;
145-
/// let h = -3.7_f128;
146-
///
147-
/// assert_eq!(f.trunc(), 3.0);
148-
/// assert_eq!(g.trunc(), 3.0);
149-
/// assert_eq!(h.trunc(), -3.0);
150-
/// # }
151-
/// ```
152-
#[inline]
153-
#[doc(alias = "truncate")]
154-
#[rustc_allow_incoherent_impl]
155-
#[unstable(feature = "f128", issue = "116909")]
156-
#[must_use = "method returns a new number and does not mutate the original value"]
157-
pub fn trunc(self) -> f128 {
158-
unsafe { intrinsics::truncf128(self) }
159-
}
160-
161-
/// Returns the fractional part of `self`.
162-
///
163-
/// This function always returns the precise result.
164-
///
165-
/// # Examples
166-
///
167-
/// ```
168-
/// #![feature(f128)]
169-
/// # #[cfg(reliable_f128_math)] {
170-
///
171-
/// let x = 3.6_f128;
172-
/// let y = -3.6_f128;
173-
/// let abs_difference_x = (x.fract() - 0.6).abs();
174-
/// let abs_difference_y = (y.fract() - (-0.6)).abs();
175-
///
176-
/// assert!(abs_difference_x <= f128::EPSILON);
177-
/// assert!(abs_difference_y <= f128::EPSILON);
178-
/// # }
179-
/// ```
180-
#[inline]
181-
#[rustc_allow_incoherent_impl]
182-
#[unstable(feature = "f128", issue = "116909")]
183-
#[must_use = "method returns a new number and does not mutate the original value"]
184-
pub fn fract(self) -> f128 {
185-
self - self.trunc()
186-
}
187-
188-
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
189-
/// error, yielding a more accurate result than an unfused multiply-add.
190-
///
191-
/// Using `mul_add` *may* be more performant than an unfused multiply-add if
192-
/// the target architecture has a dedicated `fma` CPU instruction. However,
193-
/// this is not always true, and will be heavily dependant on designing
194-
/// algorithms with specific target hardware in mind.
195-
///
196-
/// # Precision
197-
///
198-
/// The result of this operation is guaranteed to be the rounded
199-
/// infinite-precision result. It is specified by IEEE 754 as
200-
/// `fusedMultiplyAdd` and guaranteed not to change.
201-
///
202-
/// # Examples
203-
///
204-
/// ```
205-
/// #![feature(f128)]
206-
/// # #[cfg(reliable_f128_math)] {
207-
///
208-
/// let m = 10.0_f128;
209-
/// let x = 4.0_f128;
210-
/// let b = 60.0_f128;
211-
///
212-
/// assert_eq!(m.mul_add(x, b), 100.0);
213-
/// assert_eq!(m * x + b, 100.0);
214-
///
215-
/// let one_plus_eps = 1.0_f128 + f128::EPSILON;
216-
/// let one_minus_eps = 1.0_f128 - f128::EPSILON;
217-
/// let minus_one = -1.0_f128;
218-
///
219-
/// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
220-
/// assert_eq!(one_plus_eps.mul_add(one_minus_eps, minus_one), -f128::EPSILON * f128::EPSILON);
221-
/// // Different rounding with the non-fused multiply and add.
222-
/// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
223-
/// # }
224-
/// ```
225-
#[inline]
226-
#[rustc_allow_incoherent_impl]
227-
#[doc(alias = "fmaf128", alias = "fusedMultiplyAdd")]
228-
#[unstable(feature = "f128", issue = "116909")]
229-
#[must_use = "method returns a new number and does not mutate the original value"]
230-
pub fn mul_add(self, a: f128, b: f128) -> f128 {
231-
unsafe { intrinsics::fmaf128(self, a, b) }
232-
}
233-
234-
/// Calculates Euclidean division, the matching method for `rem_euclid`.
235-
///
236-
/// This computes the integer `n` such that
237-
/// `self = n * rhs + self.rem_euclid(rhs)`.
238-
/// In other words, the result is `self / rhs` rounded to the integer `n`
239-
/// such that `self >= n * rhs`.
240-
///
241-
/// # Precision
242-
///
243-
/// The result of this operation is guaranteed to be the rounded
244-
/// infinite-precision result.
245-
///
246-
/// # Examples
247-
///
248-
/// ```
249-
/// #![feature(f128)]
250-
/// # #[cfg(reliable_f128_math)] {
251-
///
252-
/// let a: f128 = 7.0;
253-
/// let b = 4.0;
254-
/// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
255-
/// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0
256-
/// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
257-
/// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
258-
/// # }
259-
/// ```
260-
#[inline]
261-
#[rustc_allow_incoherent_impl]
262-
#[unstable(feature = "f128", issue = "116909")]
263-
#[must_use = "method returns a new number and does not mutate the original value"]
264-
pub fn div_euclid(self, rhs: f128) -> f128 {
265-
let q = (self / rhs).trunc();
266-
if self % rhs < 0.0 {
267-
return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
268-
}
269-
q
270-
}
271-
272-
/// Calculates the least nonnegative remainder of `self (mod rhs)`.
273-
///
274-
/// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
275-
/// most cases. However, due to a floating point round-off error it can
276-
/// result in `r == rhs.abs()`, violating the mathematical definition, if
277-
/// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
278-
/// This result is not an element of the function's codomain, but it is the
279-
/// closest floating point number in the real numbers and thus fulfills the
280-
/// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
281-
/// approximately.
282-
///
283-
/// # Precision
284-
///
285-
/// The result of this operation is guaranteed to be the rounded
286-
/// infinite-precision result.
287-
///
288-
/// # Examples
289-
///
290-
/// ```
291-
/// #![feature(f128)]
292-
/// # #[cfg(reliable_f128_math)] {
293-
///
294-
/// let a: f128 = 7.0;
295-
/// let b = 4.0;
296-
/// assert_eq!(a.rem_euclid(b), 3.0);
297-
/// assert_eq!((-a).rem_euclid(b), 1.0);
298-
/// assert_eq!(a.rem_euclid(-b), 3.0);
299-
/// assert_eq!((-a).rem_euclid(-b), 1.0);
300-
/// // limitation due to round-off error
301-
/// assert!((-f128::EPSILON).rem_euclid(3.0) != 0.0);
302-
/// # }
303-
/// ```
304-
#[inline]
305-
#[rustc_allow_incoherent_impl]
306-
#[doc(alias = "modulo", alias = "mod")]
307-
#[unstable(feature = "f128", issue = "116909")]
308-
#[must_use = "method returns a new number and does not mutate the original value"]
309-
pub fn rem_euclid(self, rhs: f128) -> f128 {
310-
let r = self % rhs;
311-
if r < 0.0 { r + rhs.abs() } else { r }
312-
}
313-
314-
/// Raises a number to an integer power.
315-
///
316-
/// Using this function is generally faster than using `powf`.
317-
/// It might have a different sequence of rounding operations than `powf`,
318-
/// so the results are not guaranteed to agree.
319-
///
320-
/// # Unspecified precision
321-
///
322-
/// The precision of this function is non-deterministic. This means it varies by platform,
323-
/// Rust version, and can even differ within the same execution from one invocation to the next.
324-
///
325-
/// # Examples
326-
///
327-
/// ```
328-
/// #![feature(f128)]
329-
/// # #[cfg(reliable_f128_math)] {
330-
///
331-
/// let x = 2.0_f128;
332-
/// let abs_difference = (x.powi(2) - (x * x)).abs();
333-
/// assert!(abs_difference <= f128::EPSILON);
334-
///
335-
/// assert_eq!(f128::powi(f128::NAN, 0), 1.0);
336-
/// # }
337-
/// ```
338-
#[inline]
339-
#[rustc_allow_incoherent_impl]
340-
#[unstable(feature = "f128", issue = "116909")]
341-
#[must_use = "method returns a new number and does not mutate the original value"]
342-
pub fn powi(self, n: i32) -> f128 {
343-
unsafe { intrinsics::powif128(self, n) }
344-
}
345-
34617
/// Raises a number to a floating point power.
34718
///
34819
/// # Unspecified precision
@@ -372,40 +43,6 @@ impl f128 {
37243
unsafe { intrinsics::powf128(self, n) }
37344
}
37445

375-
/// Returns the square root of a number.
376-
///
377-
/// Returns NaN if `self` is a negative number other than `-0.0`.
378-
///
379-
/// # Precision
380-
///
381-
/// The result of this operation is guaranteed to be the rounded
382-
/// infinite-precision result. It is specified by IEEE 754 as `squareRoot`
383-
/// and guaranteed not to change.
384-
///
385-
/// # Examples
386-
///
387-
/// ```
388-
/// #![feature(f128)]
389-
/// # #[cfg(reliable_f128_math)] {
390-
///
391-
/// let positive = 4.0_f128;
392-
/// let negative = -4.0_f128;
393-
/// let negative_zero = -0.0_f128;
394-
///
395-
/// assert_eq!(positive.sqrt(), 2.0);
396-
/// assert!(negative.sqrt().is_nan());
397-
/// assert!(negative_zero.sqrt() == negative_zero);
398-
/// # }
399-
/// ```
400-
#[inline]
401-
#[doc(alias = "squareRoot")]
402-
#[rustc_allow_incoherent_impl]
403-
#[unstable(feature = "f128", issue = "116909")]
404-
#[must_use = "method returns a new number and does not mutate the original value"]
405-
pub fn sqrt(self) -> f128 {
406-
unsafe { intrinsics::sqrtf128(self) }
407-
}
408-
40946
/// Returns `e^(self)`, (the exponential function).
41047
///
41148
/// # Unspecified precision

‎library/std/src/f16.rs‎

Lines changed: 0 additions & 395 deletions
Large diffs are not rendered by default.

‎library/std/src/f32.rs‎

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl f32 {
4646
#[stable(feature = "rust1", since = "1.0.0")]
4747
#[inline]
4848
pub fn floor(self) -> f32 {
49-
unsafe { intrinsics::floorf32(self) }
49+
core::f32::floor(self)
5050
}
5151

5252
/// Returns the smallest integer greater than or equal to `self`.
@@ -68,7 +68,7 @@ impl f32 {
6868
#[stable(feature = "rust1", since = "1.0.0")]
6969
#[inline]
7070
pub fn ceil(self) -> f32 {
71-
unsafe { intrinsics::ceilf32(self) }
71+
core::f32::ceil(self)
7272
}
7373

7474
/// Returns the nearest integer to `self`. If a value is half-way between two
@@ -96,7 +96,7 @@ impl f32 {
9696
#[stable(feature = "rust1", since = "1.0.0")]
9797
#[inline]
9898
pub fn round(self) -> f32 {
99-
unsafe { intrinsics::roundf32(self) }
99+
core::f32::round(self)
100100
}
101101

102102
/// Returns the nearest integer to a number. Rounds half-way cases to the number
@@ -122,7 +122,7 @@ impl f32 {
122122
#[stable(feature = "round_ties_even", since = "1.77.0")]
123123
#[inline]
124124
pub fn round_ties_even(self) -> f32 {
125-
intrinsics::round_ties_even_f32(self)
125+
core::f32::round_ties_even(self)
126126
}
127127

128128
/// Returns the integer part of `self`.
@@ -147,7 +147,7 @@ impl f32 {
147147
#[stable(feature = "rust1", since = "1.0.0")]
148148
#[inline]
149149
pub fn trunc(self) -> f32 {
150-
unsafe { intrinsics::truncf32(self) }
150+
core::f32::trunc(self)
151151
}
152152

153153
/// Returns the fractional part of `self`.
@@ -170,7 +170,7 @@ impl f32 {
170170
#[stable(feature = "rust1", since = "1.0.0")]
171171
#[inline]
172172
pub fn fract(self) -> f32 {
173-
self - self.trunc()
173+
core::f32::fract(self)
174174
}
175175

176176
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
@@ -212,7 +212,7 @@ impl f32 {
212212
#[stable(feature = "rust1", since = "1.0.0")]
213213
#[inline]
214214
pub fn mul_add(self, a: f32, b: f32) -> f32 {
215-
unsafe { intrinsics::fmaf32(self, a, b) }
215+
core::f32::mul_add(self, a, b)
216216
}
217217

218218
/// Calculates Euclidean division, the matching method for `rem_euclid`.
@@ -242,11 +242,7 @@ impl f32 {
242242
#[inline]
243243
#[stable(feature = "euclidean_division", since = "1.38.0")]
244244
pub fn div_euclid(self, rhs: f32) -> f32 {
245-
let q = (self / rhs).trunc();
246-
if self % rhs < 0.0 {
247-
return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
248-
}
249-
q
245+
core::f32::div_euclid(self, rhs)
250246
}
251247

252248
/// Calculates the least nonnegative remainder of `self (mod rhs)`.
@@ -283,8 +279,7 @@ impl f32 {
283279
#[inline]
284280
#[stable(feature = "euclidean_division", since = "1.38.0")]
285281
pub fn rem_euclid(self, rhs: f32) -> f32 {
286-
let r = self % rhs;
287-
if r < 0.0 { r + rhs.abs() } else { r }
282+
core::f32::rem_euclid(self, rhs)
288283
}
289284

290285
/// Raises a number to an integer power.
@@ -312,7 +307,7 @@ impl f32 {
312307
#[stable(feature = "rust1", since = "1.0.0")]
313308
#[inline]
314309
pub fn powi(self, n: i32) -> f32 {
315-
unsafe { intrinsics::powif32(self, n) }
310+
core::f32::powi(self, n)
316311
}
317312

318313
/// Raises a number to a floating point power.
@@ -367,7 +362,7 @@ impl f32 {
367362
#[stable(feature = "rust1", since = "1.0.0")]
368363
#[inline]
369364
pub fn sqrt(self) -> f32 {
370-
unsafe { intrinsics::sqrtf32(self) }
365+
core::f32::sqrt(self)
371366
}
372367

373368
/// Returns `e^(self)`, (the exponential function).
@@ -567,7 +562,8 @@ impl f32 {
567562
filing an issue describing your use-case too)."
568563
)]
569564
pub fn abs_sub(self, other: f32) -> f32 {
570-
unsafe { cmath::fdimf(self, other) }
565+
#[allow(deprecated)]
566+
core::f32::abs_sub(self, other)
571567
}
572568

573569
/// Returns the cube root of a number.
@@ -594,7 +590,7 @@ impl f32 {
594590
#[stable(feature = "rust1", since = "1.0.0")]
595591
#[inline]
596592
pub fn cbrt(self) -> f32 {
597-
unsafe { cmath::cbrtf(self) }
593+
core::f32::cbrt(self)
598594
}
599595

600596
/// Compute the distance between the origin and a point (`x`, `y`) on the

‎library/std/src/f64.rs‎

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl f64 {
4646
#[stable(feature = "rust1", since = "1.0.0")]
4747
#[inline]
4848
pub fn floor(self) -> f64 {
49-
unsafe { intrinsics::floorf64(self) }
49+
core::f64::floor(self)
5050
}
5151

5252
/// Returns the smallest integer greater than or equal to `self`.
@@ -68,7 +68,7 @@ impl f64 {
6868
#[stable(feature = "rust1", since = "1.0.0")]
6969
#[inline]
7070
pub fn ceil(self) -> f64 {
71-
unsafe { intrinsics::ceilf64(self) }
71+
core::f64::ceil(self)
7272
}
7373

7474
/// Returns the nearest integer to `self`. If a value is half-way between two
@@ -96,7 +96,7 @@ impl f64 {
9696
#[stable(feature = "rust1", since = "1.0.0")]
9797
#[inline]
9898
pub fn round(self) -> f64 {
99-
unsafe { intrinsics::roundf64(self) }
99+
core::f64::round(self)
100100
}
101101

102102
/// Returns the nearest integer to a number. Rounds half-way cases to the number
@@ -122,7 +122,7 @@ impl f64 {
122122
#[stable(feature = "round_ties_even", since = "1.77.0")]
123123
#[inline]
124124
pub fn round_ties_even(self) -> f64 {
125-
intrinsics::round_ties_even_f64(self)
125+
core::f64::round_ties_even(self)
126126
}
127127

128128
/// Returns the integer part of `self`.
@@ -147,7 +147,7 @@ impl f64 {
147147
#[stable(feature = "rust1", since = "1.0.0")]
148148
#[inline]
149149
pub fn trunc(self) -> f64 {
150-
unsafe { intrinsics::truncf64(self) }
150+
core::f64::trunc(self)
151151
}
152152

153153
/// Returns the fractional part of `self`.
@@ -170,7 +170,7 @@ impl f64 {
170170
#[stable(feature = "rust1", since = "1.0.0")]
171171
#[inline]
172172
pub fn fract(self) -> f64 {
173-
self - self.trunc()
173+
core::f64::fract(self)
174174
}
175175

176176
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
@@ -212,7 +212,7 @@ impl f64 {
212212
#[stable(feature = "rust1", since = "1.0.0")]
213213
#[inline]
214214
pub fn mul_add(self, a: f64, b: f64) -> f64 {
215-
unsafe { intrinsics::fmaf64(self, a, b) }
215+
core::f64::mul_add(self, a, b)
216216
}
217217

218218
/// Calculates Euclidean division, the matching method for `rem_euclid`.
@@ -242,11 +242,7 @@ impl f64 {
242242
#[inline]
243243
#[stable(feature = "euclidean_division", since = "1.38.0")]
244244
pub fn div_euclid(self, rhs: f64) -> f64 {
245-
let q = (self / rhs).trunc();
246-
if self % rhs < 0.0 {
247-
return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
248-
}
249-
q
245+
core::f64::div_euclid(self, rhs)
250246
}
251247

252248
/// Calculates the least nonnegative remainder of `self (mod rhs)`.
@@ -283,8 +279,7 @@ impl f64 {
283279
#[inline]
284280
#[stable(feature = "euclidean_division", since = "1.38.0")]
285281
pub fn rem_euclid(self, rhs: f64) -> f64 {
286-
let r = self % rhs;
287-
if r < 0.0 { r + rhs.abs() } else { r }
282+
core::f64::rem_euclid(self, rhs)
288283
}
289284

290285
/// Raises a number to an integer power.
@@ -312,7 +307,7 @@ impl f64 {
312307
#[stable(feature = "rust1", since = "1.0.0")]
313308
#[inline]
314309
pub fn powi(self, n: i32) -> f64 {
315-
unsafe { intrinsics::powif64(self, n) }
310+
core::f64::powi(self, n)
316311
}
317312

318313
/// Raises a number to a floating point power.
@@ -367,7 +362,7 @@ impl f64 {
367362
#[stable(feature = "rust1", since = "1.0.0")]
368363
#[inline]
369364
pub fn sqrt(self) -> f64 {
370-
unsafe { intrinsics::sqrtf64(self) }
365+
core::f64::sqrt(self)
371366
}
372367

373368
/// Returns `e^(self)`, (the exponential function).
@@ -567,7 +562,8 @@ impl f64 {
567562
filing an issue describing your use-case too)."
568563
)]
569564
pub fn abs_sub(self, other: f64) -> f64 {
570-
unsafe { cmath::fdim(self, other) }
565+
#[allow(deprecated)]
566+
core::f64::abs_sub(self, other)
571567
}
572568

573569
/// Returns the cube root of a number.
@@ -594,7 +590,7 @@ impl f64 {
594590
#[stable(feature = "rust1", since = "1.0.0")]
595591
#[inline]
596592
pub fn cbrt(self) -> f64 {
597-
unsafe { cmath::cbrt(self) }
593+
core::f64::cbrt(self)
598594
}
599595

600596
/// Compute the distance between the origin and a point (`x`, `y`) on the

‎library/std/src/lib.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@
285285
#![feature(cfi_encoding)]
286286
#![feature(char_max_len)]
287287
#![feature(concat_idents)]
288+
#![feature(core_float_math)]
288289
#![feature(decl_macro)]
289290
#![feature(deprecated_suggestion)]
290291
#![feature(doc_cfg)]

‎library/std/src/sys/cmath.rs‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,9 @@ unsafe extern "C" {
77
pub fn asin(n: f64) -> f64;
88
pub fn atan(n: f64) -> f64;
99
pub fn atan2(a: f64, b: f64) -> f64;
10-
pub fn cbrt(n: f64) -> f64;
11-
pub fn cbrtf(n: f32) -> f32;
1210
pub fn cosh(n: f64) -> f64;
1311
pub fn expm1(n: f64) -> f64;
1412
pub fn expm1f(n: f32) -> f32;
15-
pub fn fdim(a: f64, b: f64) -> f64;
16-
pub fn fdimf(a: f32, b: f32) -> f32;
1713
#[cfg_attr(target_env = "msvc", link_name = "_hypot")]
1814
pub fn hypot(x: f64, y: f64) -> f64;
1915
#[cfg_attr(target_env = "msvc", link_name = "_hypotf")]

‎library/std/tests/floats/f128.rs‎

Lines changed: 5 additions & 684 deletions
Large diffs are not rendered by default.

‎library/std/tests/floats/f16.rs‎

Lines changed: 0 additions & 768 deletions
Large diffs are not rendered by default.

‎library/std/tests/floats/f32.rs‎

Lines changed: 0 additions & 664 deletions
Large diffs are not rendered by default.

‎library/std/tests/floats/f64.rs‎

Lines changed: 0 additions & 647 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
This repository has been archived.