Skip to content

Commit 6335056

Browse files
committed
float types: move copysign, abs, signum to libcore
1 parent 36cfa4e commit 6335056

File tree

8 files changed

+363
-363
lines changed

8 files changed

+363
-363
lines changed

core/src/num/f128.rs

+98
Original file line numberDiff line numberDiff line change
@@ -1282,4 +1282,102 @@ impl f128 {
12821282
}
12831283
self
12841284
}
1285+
1286+
/// Computes the absolute value of `self`.
1287+
///
1288+
/// This function always returns the precise result.
1289+
///
1290+
/// # Examples
1291+
///
1292+
/// ```
1293+
/// #![feature(f128)]
1294+
/// # #[cfg(reliable_f128)] {
1295+
///
1296+
/// let x = 3.5_f128;
1297+
/// let y = -3.5_f128;
1298+
///
1299+
/// assert_eq!(x.abs(), x);
1300+
/// assert_eq!(y.abs(), -y);
1301+
///
1302+
/// assert!(f128::NAN.abs().is_nan());
1303+
/// # }
1304+
/// ```
1305+
#[inline]
1306+
#[rustc_allow_incoherent_impl]
1307+
#[unstable(feature = "f128", issue = "116909")]
1308+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
1309+
#[must_use = "method returns a new number and does not mutate the original value"]
1310+
pub const fn abs(self) -> Self {
1311+
// FIXME(f16_f128): replace with `intrinsics::fabsf128` when available
1312+
// We don't do this now because LLVM has lowering bugs for f128 math.
1313+
Self::from_bits(self.to_bits() & !(1 << 127))
1314+
}
1315+
1316+
/// Returns a number that represents the sign of `self`.
1317+
///
1318+
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
1319+
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
1320+
/// - NaN if the number is NaN
1321+
///
1322+
/// # Examples
1323+
///
1324+
/// ```
1325+
/// #![feature(f128)]
1326+
/// # #[cfg(reliable_f128_math)] {
1327+
///
1328+
/// let f = 3.5_f128;
1329+
///
1330+
/// assert_eq!(f.signum(), 1.0);
1331+
/// assert_eq!(f128::NEG_INFINITY.signum(), -1.0);
1332+
///
1333+
/// assert!(f128::NAN.signum().is_nan());
1334+
/// # }
1335+
/// ```
1336+
#[inline]
1337+
#[rustc_allow_incoherent_impl]
1338+
#[unstable(feature = "f128", issue = "116909")]
1339+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
1340+
#[must_use = "method returns a new number and does not mutate the original value"]
1341+
pub const fn signum(self) -> f128 {
1342+
if self.is_nan() { Self::NAN } else { 1.0_f128.copysign(self) }
1343+
}
1344+
1345+
/// Returns a number composed of the magnitude of `self` and the sign of
1346+
/// `sign`.
1347+
///
1348+
/// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`.
1349+
/// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is
1350+
/// returned.
1351+
///
1352+
/// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note
1353+
/// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust
1354+
/// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the
1355+
/// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable
1356+
/// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
1357+
/// info.
1358+
///
1359+
/// # Examples
1360+
///
1361+
/// ```
1362+
/// #![feature(f128)]
1363+
/// # #[cfg(reliable_f128_math)] {
1364+
///
1365+
/// let f = 3.5_f128;
1366+
///
1367+
/// assert_eq!(f.copysign(0.42), 3.5_f128);
1368+
/// assert_eq!(f.copysign(-0.42), -3.5_f128);
1369+
/// assert_eq!((-f).copysign(0.42), 3.5_f128);
1370+
/// assert_eq!((-f).copysign(-0.42), -3.5_f128);
1371+
///
1372+
/// assert!(f128::NAN.copysign(1.0).is_nan());
1373+
/// # }
1374+
/// ```
1375+
#[inline]
1376+
#[rustc_allow_incoherent_impl]
1377+
#[unstable(feature = "f128", issue = "116909")]
1378+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
1379+
#[must_use = "method returns a new number and does not mutate the original value"]
1380+
pub const fn copysign(self, sign: f128) -> f128 {
1381+
unsafe { intrinsics::copysignf128(self, sign) }
1382+
}
12851383
}

core/src/num/f16.rs

+97
Original file line numberDiff line numberDiff line change
@@ -1257,4 +1257,101 @@ impl f16 {
12571257
}
12581258
self
12591259
}
1260+
1261+
/// Computes the absolute value of `self`.
1262+
///
1263+
/// This function always returns the precise result.
1264+
///
1265+
/// # Examples
1266+
///
1267+
/// ```
1268+
/// #![feature(f16)]
1269+
/// # #[cfg(reliable_f16)] {
1270+
///
1271+
/// let x = 3.5_f16;
1272+
/// let y = -3.5_f16;
1273+
///
1274+
/// assert_eq!(x.abs(), x);
1275+
/// assert_eq!(y.abs(), -y);
1276+
///
1277+
/// assert!(f16::NAN.abs().is_nan());
1278+
/// # }
1279+
/// ```
1280+
#[inline]
1281+
#[rustc_allow_incoherent_impl]
1282+
#[unstable(feature = "f16", issue = "116909")]
1283+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
1284+
#[must_use = "method returns a new number and does not mutate the original value"]
1285+
pub const fn abs(self) -> Self {
1286+
// FIXME(f16_f128): replace with `intrinsics::fabsf16` when available
1287+
Self::from_bits(self.to_bits() & !(1 << 15))
1288+
}
1289+
1290+
/// Returns a number that represents the sign of `self`.
1291+
///
1292+
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
1293+
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
1294+
/// - NaN if the number is NaN
1295+
///
1296+
/// # Examples
1297+
///
1298+
/// ```
1299+
/// #![feature(f16)]
1300+
/// # #[cfg(reliable_f16_math)] {
1301+
///
1302+
/// let f = 3.5_f16;
1303+
///
1304+
/// assert_eq!(f.signum(), 1.0);
1305+
/// assert_eq!(f16::NEG_INFINITY.signum(), -1.0);
1306+
///
1307+
/// assert!(f16::NAN.signum().is_nan());
1308+
/// # }
1309+
/// ```
1310+
#[inline]
1311+
#[rustc_allow_incoherent_impl]
1312+
#[unstable(feature = "f16", issue = "116909")]
1313+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
1314+
#[must_use = "method returns a new number and does not mutate the original value"]
1315+
pub const fn signum(self) -> f16 {
1316+
if self.is_nan() { Self::NAN } else { 1.0_f16.copysign(self) }
1317+
}
1318+
1319+
/// Returns a number composed of the magnitude of `self` and the sign of
1320+
/// `sign`.
1321+
///
1322+
/// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`.
1323+
/// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is
1324+
/// returned.
1325+
///
1326+
/// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note
1327+
/// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust
1328+
/// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the
1329+
/// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable
1330+
/// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
1331+
/// info.
1332+
///
1333+
/// # Examples
1334+
///
1335+
/// ```
1336+
/// #![feature(f16)]
1337+
/// # #[cfg(reliable_f16_math)] {
1338+
///
1339+
/// let f = 3.5_f16;
1340+
///
1341+
/// assert_eq!(f.copysign(0.42), 3.5_f16);
1342+
/// assert_eq!(f.copysign(-0.42), -3.5_f16);
1343+
/// assert_eq!((-f).copysign(0.42), 3.5_f16);
1344+
/// assert_eq!((-f).copysign(-0.42), -3.5_f16);
1345+
///
1346+
/// assert!(f16::NAN.copysign(1.0).is_nan());
1347+
/// # }
1348+
/// ```
1349+
#[inline]
1350+
#[rustc_allow_incoherent_impl]
1351+
#[unstable(feature = "f16", issue = "116909")]
1352+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
1353+
#[must_use = "method returns a new number and does not mutate the original value"]
1354+
pub const fn copysign(self, sign: f16) -> f16 {
1355+
unsafe { intrinsics::copysignf16(self, sign) }
1356+
}
12601357
}

core/src/num/f32.rs

+84
Original file line numberDiff line numberDiff line change
@@ -1427,4 +1427,88 @@ impl f32 {
14271427
}
14281428
self
14291429
}
1430+
1431+
/// Computes the absolute value of `self`.
1432+
///
1433+
/// This function always returns the precise result.
1434+
///
1435+
/// # Examples
1436+
///
1437+
/// ```
1438+
/// let x = 3.5_f32;
1439+
/// let y = -3.5_f32;
1440+
///
1441+
/// assert_eq!(x.abs(), x);
1442+
/// assert_eq!(y.abs(), -y);
1443+
///
1444+
/// assert!(f32::NAN.abs().is_nan());
1445+
/// ```
1446+
#[rustc_allow_incoherent_impl]
1447+
#[must_use = "method returns a new number and does not mutate the original value"]
1448+
#[stable(feature = "rust1", since = "1.0.0")]
1449+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
1450+
#[inline]
1451+
pub const fn abs(self) -> f32 {
1452+
unsafe { intrinsics::fabsf32(self) }
1453+
}
1454+
1455+
/// Returns a number that represents the sign of `self`.
1456+
///
1457+
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
1458+
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
1459+
/// - NaN if the number is NaN
1460+
///
1461+
/// # Examples
1462+
///
1463+
/// ```
1464+
/// let f = 3.5_f32;
1465+
///
1466+
/// assert_eq!(f.signum(), 1.0);
1467+
/// assert_eq!(f32::NEG_INFINITY.signum(), -1.0);
1468+
///
1469+
/// assert!(f32::NAN.signum().is_nan());
1470+
/// ```
1471+
#[rustc_allow_incoherent_impl]
1472+
#[must_use = "method returns a new number and does not mutate the original value"]
1473+
#[stable(feature = "rust1", since = "1.0.0")]
1474+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
1475+
#[inline]
1476+
pub const fn signum(self) -> f32 {
1477+
if self.is_nan() { Self::NAN } else { 1.0_f32.copysign(self) }
1478+
}
1479+
1480+
/// Returns a number composed of the magnitude of `self` and the sign of
1481+
/// `sign`.
1482+
///
1483+
/// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`.
1484+
/// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is
1485+
/// returned.
1486+
///
1487+
/// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note
1488+
/// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust
1489+
/// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the
1490+
/// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable
1491+
/// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
1492+
/// info.
1493+
///
1494+
/// # Examples
1495+
///
1496+
/// ```
1497+
/// let f = 3.5_f32;
1498+
///
1499+
/// assert_eq!(f.copysign(0.42), 3.5_f32);
1500+
/// assert_eq!(f.copysign(-0.42), -3.5_f32);
1501+
/// assert_eq!((-f).copysign(0.42), 3.5_f32);
1502+
/// assert_eq!((-f).copysign(-0.42), -3.5_f32);
1503+
///
1504+
/// assert!(f32::NAN.copysign(1.0).is_nan());
1505+
/// ```
1506+
#[rustc_allow_incoherent_impl]
1507+
#[must_use = "method returns a new number and does not mutate the original value"]
1508+
#[inline]
1509+
#[stable(feature = "copysign", since = "1.35.0")]
1510+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
1511+
pub const fn copysign(self, sign: f32) -> f32 {
1512+
unsafe { intrinsics::copysignf32(self, sign) }
1513+
}
14301514
}

core/src/num/f64.rs

+84
Original file line numberDiff line numberDiff line change
@@ -1427,4 +1427,88 @@ impl f64 {
14271427
}
14281428
self
14291429
}
1430+
1431+
/// Computes the absolute value of `self`.
1432+
///
1433+
/// This function always returns the precise result.
1434+
///
1435+
/// # Examples
1436+
///
1437+
/// ```
1438+
/// let x = 3.5_f64;
1439+
/// let y = -3.5_f64;
1440+
///
1441+
/// assert_eq!(x.abs(), x);
1442+
/// assert_eq!(y.abs(), -y);
1443+
///
1444+
/// assert!(f64::NAN.abs().is_nan());
1445+
/// ```
1446+
#[rustc_allow_incoherent_impl]
1447+
#[must_use = "method returns a new number and does not mutate the original value"]
1448+
#[stable(feature = "rust1", since = "1.0.0")]
1449+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
1450+
#[inline]
1451+
pub const fn abs(self) -> f64 {
1452+
unsafe { intrinsics::fabsf64(self) }
1453+
}
1454+
1455+
/// Returns a number that represents the sign of `self`.
1456+
///
1457+
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
1458+
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
1459+
/// - NaN if the number is NaN
1460+
///
1461+
/// # Examples
1462+
///
1463+
/// ```
1464+
/// let f = 3.5_f64;
1465+
///
1466+
/// assert_eq!(f.signum(), 1.0);
1467+
/// assert_eq!(f64::NEG_INFINITY.signum(), -1.0);
1468+
///
1469+
/// assert!(f64::NAN.signum().is_nan());
1470+
/// ```
1471+
#[rustc_allow_incoherent_impl]
1472+
#[must_use = "method returns a new number and does not mutate the original value"]
1473+
#[stable(feature = "rust1", since = "1.0.0")]
1474+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
1475+
#[inline]
1476+
pub const fn signum(self) -> f64 {
1477+
if self.is_nan() { Self::NAN } else { 1.0_f64.copysign(self) }
1478+
}
1479+
1480+
/// Returns a number composed of the magnitude of `self` and the sign of
1481+
/// `sign`.
1482+
///
1483+
/// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`.
1484+
/// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is
1485+
/// returned.
1486+
///
1487+
/// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note
1488+
/// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust
1489+
/// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the
1490+
/// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable
1491+
/// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
1492+
/// info.
1493+
///
1494+
/// # Examples
1495+
///
1496+
/// ```
1497+
/// let f = 3.5_f64;
1498+
///
1499+
/// assert_eq!(f.copysign(0.42), 3.5_f64);
1500+
/// assert_eq!(f.copysign(-0.42), -3.5_f64);
1501+
/// assert_eq!((-f).copysign(0.42), 3.5_f64);
1502+
/// assert_eq!((-f).copysign(-0.42), -3.5_f64);
1503+
///
1504+
/// assert!(f64::NAN.copysign(1.0).is_nan());
1505+
/// ```
1506+
#[rustc_allow_incoherent_impl]
1507+
#[must_use = "method returns a new number and does not mutate the original value"]
1508+
#[stable(feature = "copysign", since = "1.35.0")]
1509+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
1510+
#[inline]
1511+
pub const fn copysign(self, sign: f64) -> f64 {
1512+
unsafe { intrinsics::copysignf64(self, sign) }
1513+
}
14301514
}

0 commit comments

Comments
 (0)