@@ -285,17 +285,6 @@ impl f128 {
285
285
self != self
286
286
}
287
287
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
-
299
288
/// Returns `true` if this value is positive infinity or negative infinity, and
300
289
/// `false` otherwise.
301
290
///
@@ -345,10 +334,11 @@ impl f128 {
345
334
#[ inline]
346
335
#[ must_use]
347
336
#[ unstable( feature = "f128" , issue = "116909" ) ]
337
+ #[ rustc_allow_const_fn_unstable( const_float_methods) ] // for `abs`
348
338
pub const fn is_finite ( self ) -> bool {
349
339
// There's no need to handle NaN separately: if self is NaN,
350
340
// the comparison is not true, exactly as desired.
351
- self . abs_private ( ) < Self :: INFINITY
341
+ self . abs ( ) < Self :: INFINITY
352
342
}
353
343
354
344
/// Returns `true` if the number is [subnormal].
@@ -836,8 +826,8 @@ impl f128 {
836
826
const HI : f128 = f128:: MAX / 2. ;
837
827
838
828
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 ( ) ;
841
831
842
832
if abs_a <= HI && abs_b <= HI {
843
833
// Overflow is impossible
@@ -1281,4 +1271,100 @@ impl f128 {
1281
1271
}
1282
1272
self
1283
1273
}
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
+ }
1284
1370
}
0 commit comments