@@ -285,17 +285,6 @@ impl f128 {
285285 self != self
286286 }
287287
288- // FIXME(#50145): `abs` is publicly unavailable in core due to
289- // concerns about portability, so this implementation is for
290- // private use internally.
291- #[ inline]
292- pub ( crate ) const fn abs_private ( self ) -> f128 {
293- // SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
294- unsafe {
295- mem:: transmute :: < u128 , f128 > ( mem:: transmute :: < f128 , u128 > ( self ) & !Self :: SIGN_MASK )
296- }
297- }
298-
299288 /// Returns `true` if this value is positive infinity or negative infinity, and
300289 /// `false` otherwise.
301290 ///
@@ -345,10 +334,11 @@ impl f128 {
345334 #[ inline]
346335 #[ must_use]
347336 #[ unstable( feature = "f128" , issue = "116909" ) ]
337+ #[ rustc_allow_const_fn_unstable( const_float_methods) ] // for `abs`
348338 pub const fn is_finite ( self ) -> bool {
349339 // There's no need to handle NaN separately: if self is NaN,
350340 // the comparison is not true, exactly as desired.
351- self . abs_private ( ) < Self :: INFINITY
341+ self . abs ( ) < Self :: INFINITY
352342 }
353343
354344 /// Returns `true` if the number is [subnormal].
@@ -836,8 +826,8 @@ impl f128 {
836826 const HI : f128 = f128:: MAX / 2. ;
837827
838828 let ( a, b) = ( self , other) ;
839- let abs_a = a. abs_private ( ) ;
840- let abs_b = b. abs_private ( ) ;
829+ let abs_a = a. abs ( ) ;
830+ let abs_b = b. abs ( ) ;
841831
842832 if abs_a <= HI && abs_b <= HI {
843833 // Overflow is impossible
@@ -1281,4 +1271,100 @@ impl f128 {
12811271 }
12821272 self
12831273 }
1274+
1275+ /// Computes the absolute value of `self`.
1276+ ///
1277+ /// This function always returns the precise result.
1278+ ///
1279+ /// # Examples
1280+ ///
1281+ /// ```
1282+ /// #![feature(f128)]
1283+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1284+ ///
1285+ /// let x = 3.5_f128;
1286+ /// let y = -3.5_f128;
1287+ ///
1288+ /// assert_eq!(x.abs(), x);
1289+ /// assert_eq!(y.abs(), -y);
1290+ ///
1291+ /// assert!(f128::NAN.abs().is_nan());
1292+ /// # }
1293+ /// ```
1294+ #[ inline]
1295+ #[ unstable( feature = "f128" , issue = "116909" ) ]
1296+ #[ rustc_const_unstable( feature = "const_float_methods" , issue = "130843" ) ]
1297+ #[ must_use = "method returns a new number and does not mutate the original value" ]
1298+ pub const fn abs ( self ) -> Self {
1299+ // FIXME(f16_f128): replace with `intrinsics::fabsf128` when available
1300+ // We don't do this now because LLVM has lowering bugs for f128 math.
1301+ Self :: from_bits ( self . to_bits ( ) & !( 1 << 127 ) )
1302+ }
1303+
1304+ /// Returns a number that represents the sign of `self`.
1305+ ///
1306+ /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
1307+ /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
1308+ /// - NaN if the number is NaN
1309+ ///
1310+ /// # Examples
1311+ ///
1312+ /// ```
1313+ /// #![feature(f128)]
1314+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1315+ ///
1316+ /// let f = 3.5_f128;
1317+ ///
1318+ /// assert_eq!(f.signum(), 1.0);
1319+ /// assert_eq!(f128::NEG_INFINITY.signum(), -1.0);
1320+ ///
1321+ /// assert!(f128::NAN.signum().is_nan());
1322+ /// # }
1323+ /// ```
1324+ #[ inline]
1325+ #[ unstable( feature = "f128" , issue = "116909" ) ]
1326+ #[ rustc_const_unstable( feature = "const_float_methods" , issue = "130843" ) ]
1327+ #[ must_use = "method returns a new number and does not mutate the original value" ]
1328+ pub const fn signum ( self ) -> f128 {
1329+ if self . is_nan ( ) { Self :: NAN } else { 1.0_f128 . copysign ( self ) }
1330+ }
1331+
1332+ /// Returns a number composed of the magnitude of `self` and the sign of
1333+ /// `sign`.
1334+ ///
1335+ /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`.
1336+ /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is
1337+ /// returned.
1338+ ///
1339+ /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note
1340+ /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust
1341+ /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the
1342+ /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable
1343+ /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
1344+ /// info.
1345+ ///
1346+ /// # Examples
1347+ ///
1348+ /// ```
1349+ /// #![feature(f128)]
1350+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1351+ ///
1352+ /// let f = 3.5_f128;
1353+ ///
1354+ /// assert_eq!(f.copysign(0.42), 3.5_f128);
1355+ /// assert_eq!(f.copysign(-0.42), -3.5_f128);
1356+ /// assert_eq!((-f).copysign(0.42), 3.5_f128);
1357+ /// assert_eq!((-f).copysign(-0.42), -3.5_f128);
1358+ ///
1359+ /// assert!(f128::NAN.copysign(1.0).is_nan());
1360+ /// # }
1361+ /// ```
1362+ #[ inline]
1363+ #[ unstable( feature = "f128" , issue = "116909" ) ]
1364+ #[ rustc_const_unstable( feature = "const_float_methods" , issue = "130843" ) ]
1365+ #[ must_use = "method returns a new number and does not mutate the original value" ]
1366+ pub const fn copysign ( self , sign : f128 ) -> f128 {
1367+ // SAFETY: this is actually a safe intrinsic
1368+ unsafe { intrinsics:: copysignf128 ( self , sign) }
1369+ }
12841370}
0 commit comments