11
11
12
12
#![ unstable( feature = "f128" , issue = "116909" ) ]
13
13
14
+ use crate :: convert:: FloatToInt ;
14
15
use crate :: mem;
15
16
16
17
/// Basic mathematical constants.
@@ -220,12 +221,50 @@ impl f128 {
220
221
#[ unstable( feature = "f128" , issue = "116909" ) ]
221
222
pub const MAX_10_EXP : i32 = 4_932 ;
222
223
224
+ /// Not a Number (NaN).
225
+ ///
226
+ /// Note that IEEE 754 doesn't define just a single NaN value;
227
+ /// a plethora of bit patterns are considered to be NaN.
228
+ /// Furthermore, the standard makes a difference
229
+ /// between a "signaling" and a "quiet" NaN,
230
+ /// and allows inspecting its "payload" (the unspecified bits in the bit pattern).
231
+ /// This constant isn't guaranteed to equal to any specific NaN bitpattern,
232
+ /// and the stability of its representation over Rust versions
233
+ /// and target platforms isn't guaranteed.
234
+ #[ cfg( not( bootstrap) ) ]
235
+ #[ allow( clippy:: eq_op) ]
236
+ #[ rustc_diagnostic_item = "f128_nan" ]
237
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
238
+ pub const NAN : f128 = 0.0_f128 / 0.0_f128 ;
239
+
240
+ /// Infinity (∞).
241
+ #[ cfg( not( bootstrap) ) ]
242
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
243
+ pub const INFINITY : f128 = 1.0_f128 / 0.0_f128 ;
244
+
245
+ /// Negative infinity (−∞).
246
+ #[ cfg( not( bootstrap) ) ]
247
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
248
+ pub const NEG_INFINITY : f128 = -1.0_f128 / 0.0_f128 ;
249
+
250
+ /// Sign bit
251
+ #[ cfg( not( bootstrap) ) ]
252
+ pub ( crate ) const SIGN_MASK : u128 = 0x8000_0000_0000_0000_0000_0000_0000_0000 ;
253
+
254
+ /// Minimum representable positive value (min subnormal)
255
+ #[ cfg( not( bootstrap) ) ]
256
+ const TINY_BITS : u128 = 0x1 ;
257
+
258
+ /// Minimum representable negative value (min negative subnormal)
259
+ #[ cfg( not( bootstrap) ) ]
260
+ const NEG_TINY_BITS : u128 = Self :: TINY_BITS | Self :: SIGN_MASK ;
261
+
223
262
/// Returns `true` if this value is NaN.
224
263
///
225
264
/// ```
226
265
/// #![feature(f128)]
227
266
/// # // FIXME(f16_f128): remove when `unordtf2` is available
228
- /// # #[cfg(target_arch = "x86_64", target_os = "linux")] {
267
+ /// # #[cfg(all( target_arch = "x86_64", target_os = "linux") )] {
229
268
///
230
269
/// let nan = f128::NAN;
231
270
/// let f = 7.0_f128;
@@ -243,6 +282,78 @@ impl f128 {
243
282
self != self
244
283
}
245
284
285
+ // FIXME(#50145): `abs` is publicly unavailable in core due to
286
+ // concerns about portability, so this implementation is for
287
+ // private use internally.
288
+ #[ inline]
289
+ #[ cfg( not( bootstrap) ) ]
290
+ #[ rustc_const_unstable( feature = "const_float_classify" , issue = "72505" ) ]
291
+ pub ( crate ) const fn abs_private ( self ) -> f128 {
292
+ // SAFETY: This transmutation is fine. Probably. For the reasons std is using it.
293
+ unsafe {
294
+ mem:: transmute :: < u128 , f128 > ( mem:: transmute :: < f128 , u128 > ( self ) & !Self :: SIGN_MASK )
295
+ }
296
+ }
297
+
298
+ /// Returns `true` if this value is positive infinity or negative infinity, and
299
+ /// `false` otherwise.
300
+ ///
301
+ /// ```
302
+ /// #![feature(f128)]
303
+ /// # // FIXME(f16_f128): remove when `eqtf2` is available
304
+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
305
+ ///
306
+ /// let f = 7.0f128;
307
+ /// let inf = f128::INFINITY;
308
+ /// let neg_inf = f128::NEG_INFINITY;
309
+ /// let nan = f128::NAN;
310
+ ///
311
+ /// assert!(!f.is_infinite());
312
+ /// assert!(!nan.is_infinite());
313
+ ///
314
+ /// assert!(inf.is_infinite());
315
+ /// assert!(neg_inf.is_infinite());
316
+ /// # }
317
+ /// ```
318
+ #[ inline]
319
+ #[ must_use]
320
+ #[ cfg( not( bootstrap) ) ]
321
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
322
+ #[ rustc_const_unstable( feature = "const_float_classify" , issue = "72505" ) ]
323
+ pub const fn is_infinite ( self ) -> bool {
324
+ ( self == f128:: INFINITY ) | ( self == f128:: NEG_INFINITY )
325
+ }
326
+
327
+ /// Returns `true` if this number is neither infinite nor NaN.
328
+ ///
329
+ /// ```
330
+ /// #![feature(f128)]
331
+ /// # // FIXME(f16_f128): remove when `lttf2` is available
332
+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
333
+ ///
334
+ /// let f = 7.0f128;
335
+ /// let inf: f128 = f128::INFINITY;
336
+ /// let neg_inf: f128 = f128::NEG_INFINITY;
337
+ /// let nan: f128 = f128::NAN;
338
+ ///
339
+ /// assert!(f.is_finite());
340
+ ///
341
+ /// assert!(!nan.is_finite());
342
+ /// assert!(!inf.is_finite());
343
+ /// assert!(!neg_inf.is_finite());
344
+ /// # }
345
+ /// ```
346
+ #[ inline]
347
+ #[ must_use]
348
+ #[ cfg( not( bootstrap) ) ]
349
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
350
+ #[ rustc_const_unstable( feature = "const_float_classify" , issue = "72505" ) ]
351
+ pub const fn is_finite ( self ) -> bool {
352
+ // There's no need to handle NaN separately: if self is NaN,
353
+ // the comparison is not true, exactly as desired.
354
+ self . abs_private ( ) < Self :: INFINITY
355
+ }
356
+
246
357
/// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with
247
358
/// positive sign bit and positive infinity. Note that IEEE 754 doesn't assign any
248
359
/// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
@@ -292,6 +403,222 @@ impl f128 {
292
403
( self . to_bits ( ) & ( 1 << 127 ) ) != 0
293
404
}
294
405
406
+ /// Returns the least number greater than `self`.
407
+ ///
408
+ /// Let `TINY` be the smallest representable positive `f128`. Then,
409
+ /// - if `self.is_nan()`, this returns `self`;
410
+ /// - if `self` is [`NEG_INFINITY`], this returns [`MIN`];
411
+ /// - if `self` is `-TINY`, this returns -0.0;
412
+ /// - if `self` is -0.0 or +0.0, this returns `TINY`;
413
+ /// - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`];
414
+ /// - otherwise the unique least value greater than `self` is returned.
415
+ ///
416
+ /// The identity `x.next_up() == -(-x).next_down()` holds for all non-NaN `x`. When `x`
417
+ /// is finite `x == x.next_up().next_down()` also holds.
418
+ ///
419
+ /// ```rust
420
+ /// #![feature(f128)]
421
+ /// #![feature(float_next_up_down)]
422
+ /// # // FIXME(f16_f128): remove when `eqtf2` is available
423
+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
424
+ ///
425
+ /// // f128::EPSILON is the difference between 1.0 and the next number up.
426
+ /// assert_eq!(1.0f128.next_up(), 1.0 + f128::EPSILON);
427
+ /// // But not for most numbers.
428
+ /// assert!(0.1f128.next_up() < 0.1 + f128::EPSILON);
429
+ /// assert_eq!(4611686018427387904f128.next_up(), 4611686018427387904.000000000000001);
430
+ /// # }
431
+ /// ```
432
+ ///
433
+ /// [`NEG_INFINITY`]: Self::NEG_INFINITY
434
+ /// [`INFINITY`]: Self::INFINITY
435
+ /// [`MIN`]: Self::MIN
436
+ /// [`MAX`]: Self::MAX
437
+ #[ inline]
438
+ #[ cfg( not( bootstrap) ) ]
439
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
440
+ // #[unstable(feature = "float_next_up_down", issue = "91399")]
441
+ pub fn next_up ( self ) -> Self {
442
+ // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
443
+ // denormals to zero. This is in general unsound and unsupported, but here
444
+ // we do our best to still produce the correct result on such targets.
445
+ let bits = self . to_bits ( ) ;
446
+ if self . is_nan ( ) || bits == Self :: INFINITY . to_bits ( ) {
447
+ return self ;
448
+ }
449
+
450
+ let abs = bits & !Self :: SIGN_MASK ;
451
+ let next_bits = if abs == 0 {
452
+ Self :: TINY_BITS
453
+ } else if bits == abs {
454
+ bits + 1
455
+ } else {
456
+ bits - 1
457
+ } ;
458
+ Self :: from_bits ( next_bits)
459
+ }
460
+
461
+ /// Returns the greatest number less than `self`.
462
+ ///
463
+ /// Let `TINY` be the smallest representable positive `f128`. Then,
464
+ /// - if `self.is_nan()`, this returns `self`;
465
+ /// - if `self` is [`INFINITY`], this returns [`MAX`];
466
+ /// - if `self` is `TINY`, this returns 0.0;
467
+ /// - if `self` is -0.0 or +0.0, this returns `-TINY`;
468
+ /// - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`];
469
+ /// - otherwise the unique greatest value less than `self` is returned.
470
+ ///
471
+ /// The identity `x.next_down() == -(-x).next_up()` holds for all non-NaN `x`. When `x`
472
+ /// is finite `x == x.next_down().next_up()` also holds.
473
+ ///
474
+ /// ```rust
475
+ /// #![feature(f128)]
476
+ /// #![feature(float_next_up_down)]
477
+ /// # // FIXME(f16_f128): remove when `eqtf2` is available
478
+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
479
+ ///
480
+ /// let x = 1.0f128;
481
+ /// // Clamp value into range [0, 1).
482
+ /// let clamped = x.clamp(0.0, 1.0f128.next_down());
483
+ /// assert!(clamped < 1.0);
484
+ /// assert_eq!(clamped.next_up(), 1.0);
485
+ /// # }
486
+ /// ```
487
+ ///
488
+ /// [`NEG_INFINITY`]: Self::NEG_INFINITY
489
+ /// [`INFINITY`]: Self::INFINITY
490
+ /// [`MIN`]: Self::MIN
491
+ /// [`MAX`]: Self::MAX
492
+ #[ inline]
493
+ #[ cfg( not( bootstrap) ) ]
494
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
495
+ // #[unstable(feature = "float_next_up_down", issue = "91399")]
496
+ pub fn next_down ( self ) -> Self {
497
+ // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
498
+ // denormals to zero. This is in general unsound and unsupported, but here
499
+ // we do our best to still produce the correct result on such targets.
500
+ let bits = self . to_bits ( ) ;
501
+ if self . is_nan ( ) || bits == Self :: NEG_INFINITY . to_bits ( ) {
502
+ return self ;
503
+ }
504
+
505
+ let abs = bits & !Self :: SIGN_MASK ;
506
+ let next_bits = if abs == 0 {
507
+ Self :: NEG_TINY_BITS
508
+ } else if bits == abs {
509
+ bits - 1
510
+ } else {
511
+ bits + 1
512
+ } ;
513
+ Self :: from_bits ( next_bits)
514
+ }
515
+
516
+ /// Takes the reciprocal (inverse) of a number, `1/x`.
517
+ ///
518
+ /// ```
519
+ /// #![feature(f128)]
520
+ /// # // FIXME(f16_f128): remove when `eqtf2` is available
521
+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
522
+ ///
523
+ /// let x = 2.0_f128;
524
+ /// let abs_difference = (x.recip() - (1.0 / x)).abs();
525
+ ///
526
+ /// assert!(abs_difference <= f128::EPSILON);
527
+ /// # }
528
+ /// ```
529
+ #[ inline]
530
+ #[ cfg( not( bootstrap) ) ]
531
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
532
+ #[ must_use = "this returns the result of the operation, without modifying the original" ]
533
+ pub fn recip ( self ) -> Self {
534
+ 1.0 / self
535
+ }
536
+
537
+ /// Converts radians to degrees.
538
+ ///
539
+ /// ```
540
+ /// #![feature(f128)]
541
+ /// # // FIXME(f16_f128): remove when `eqtf2` is available
542
+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
543
+ ///
544
+ /// let angle = std::f128::consts::PI;
545
+ ///
546
+ /// let abs_difference = (angle.to_degrees() - 180.0).abs();
547
+ /// assert!(abs_difference <= f128::EPSILON);
548
+ /// # }
549
+ /// ```
550
+ #[ inline]
551
+ #[ cfg( not( bootstrap) ) ]
552
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
553
+ #[ must_use = "this returns the result of the operation, without modifying the original" ]
554
+ pub fn to_degrees ( self ) -> Self {
555
+ // Use a literal for better precision.
556
+ const PIS_IN_180 : f128 = 57.2957795130823208767981548141051703324054724665643215491602_f128 ;
557
+ self * PIS_IN_180
558
+ }
559
+
560
+ /// Converts degrees to radians.
561
+ ///
562
+ /// ```
563
+ /// #![feature(f128)]
564
+ /// # // FIXME(f16_f128): remove when `eqtf2` is available
565
+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
566
+ ///
567
+ /// let angle = 180.0f128;
568
+ ///
569
+ /// let abs_difference = (angle.to_radians() - std::f128::consts::PI).abs();
570
+ ///
571
+ /// assert!(abs_difference <= 1e-30);
572
+ /// # }
573
+ /// ```
574
+ #[ inline]
575
+ #[ cfg( not( bootstrap) ) ]
576
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
577
+ #[ must_use = "this returns the result of the operation, without modifying the original" ]
578
+ pub fn to_radians ( self ) -> f128 {
579
+ // Use a literal for better precision.
580
+ const RADS_PER_DEG : f128 =
581
+ 0.0174532925199432957692369076848861271344287188854172545609719_f128 ;
582
+ self * RADS_PER_DEG
583
+ }
584
+
585
+ /// Rounds toward zero and converts to any primitive integer type,
586
+ /// assuming that the value is finite and fits in that type.
587
+ ///
588
+ /// ```
589
+ /// #![feature(f128)]
590
+ /// # // FIXME(f16_f128): remove when `float*itf` is available
591
+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
592
+ ///
593
+ /// let value = 4.6_f128;
594
+ /// let rounded = unsafe { value.to_int_unchecked::<u16>() };
595
+ /// assert_eq!(rounded, 4);
596
+ ///
597
+ /// let value = -128.9_f128;
598
+ /// let rounded = unsafe { value.to_int_unchecked::<i8>() };
599
+ /// assert_eq!(rounded, i8::MIN);
600
+ /// # }
601
+ /// ```
602
+ ///
603
+ /// # Safety
604
+ ///
605
+ /// The value must:
606
+ ///
607
+ /// * Not be `NaN`
608
+ /// * Not be infinite
609
+ /// * Be representable in the return type `Int`, after truncating off its fractional part
610
+ #[ inline]
611
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
612
+ #[ must_use = "this returns the result of the operation, without modifying the original" ]
613
+ pub unsafe fn to_int_unchecked < Int > ( self ) -> Int
614
+ where
615
+ Self : FloatToInt < Int > ,
616
+ {
617
+ // SAFETY: the caller must uphold the safety contract for
618
+ // `FloatToInt::to_int_unchecked`.
619
+ unsafe { FloatToInt :: < Int > :: to_int_unchecked ( self ) }
620
+ }
621
+
295
622
/// Raw transmutation to `u128`.
296
623
///
297
624
/// This is currently identical to `transmute::<f128, u128>(self)` on all platforms.
@@ -367,4 +694,315 @@ impl f128 {
367
694
// Stability concerns.
368
695
unsafe { mem:: transmute ( v) }
369
696
}
697
+
698
+ /// Return the memory representation of this floating point number as a byte array in
699
+ /// big-endian (network) byte order.
700
+ ///
701
+ /// See [`from_bits`](Self::from_bits) for some discussion of the
702
+ /// portability of this operation (there are almost no issues).
703
+ ///
704
+ /// # Examples
705
+ ///
706
+ /// ```
707
+ /// #![feature(f128)]
708
+ ///
709
+ /// let bytes = 12.5f128.to_be_bytes();
710
+ /// assert_eq!(
711
+ /// bytes,
712
+ /// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
713
+ /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
714
+ /// );
715
+ /// ```
716
+ #[ inline]
717
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
718
+ #[ must_use = "this returns the result of the operation, without modifying the original" ]
719
+ pub fn to_be_bytes ( self ) -> [ u8 ; 16 ] {
720
+ self . to_bits ( ) . to_be_bytes ( )
721
+ }
722
+
723
+ /// Return the memory representation of this floating point number as a byte array in
724
+ /// little-endian byte order.
725
+ ///
726
+ /// See [`from_bits`](Self::from_bits) for some discussion of the
727
+ /// portability of this operation (there are almost no issues).
728
+ ///
729
+ /// # Examples
730
+ ///
731
+ /// ```
732
+ /// #![feature(f128)]
733
+ ///
734
+ /// let bytes = 12.5f128.to_le_bytes();
735
+ /// assert_eq!(
736
+ /// bytes,
737
+ /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
738
+ /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x02, 0x40]
739
+ /// );
740
+ /// ```
741
+ #[ inline]
742
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
743
+ #[ must_use = "this returns the result of the operation, without modifying the original" ]
744
+ pub fn to_le_bytes ( self ) -> [ u8 ; 16 ] {
745
+ self . to_bits ( ) . to_le_bytes ( )
746
+ }
747
+
748
+ /// Return the memory representation of this floating point number as a byte array in
749
+ /// native byte order.
750
+ ///
751
+ /// As the target platform's native endianness is used, portable code
752
+ /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead.
753
+ ///
754
+ /// [`to_be_bytes`]: f128::to_be_bytes
755
+ /// [`to_le_bytes`]: f128::to_le_bytes
756
+ ///
757
+ /// See [`from_bits`](Self::from_bits) for some discussion of the
758
+ /// portability of this operation (there are almost no issues).
759
+ ///
760
+ /// # Examples
761
+ ///
762
+ /// ```
763
+ /// #![feature(f128)]
764
+ ///
765
+ /// let bytes = 12.5f128.to_ne_bytes();
766
+ /// assert_eq!(
767
+ /// bytes,
768
+ /// if cfg!(target_endian = "big") {
769
+ /// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
770
+ /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
771
+ /// } else {
772
+ /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773
+ /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x02, 0x40]
774
+ /// }
775
+ /// );
776
+ /// ```
777
+ #[ inline]
778
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
779
+ #[ must_use = "this returns the result of the operation, without modifying the original" ]
780
+ pub fn to_ne_bytes ( self ) -> [ u8 ; 16 ] {
781
+ self . to_bits ( ) . to_ne_bytes ( )
782
+ }
783
+
784
+ /// Create a floating point value from its representation as a byte array in big endian.
785
+ ///
786
+ /// See [`from_bits`](Self::from_bits) for some discussion of the
787
+ /// portability of this operation (there are almost no issues).
788
+ ///
789
+ /// # Examples
790
+ ///
791
+ /// ```
792
+ /// #![feature(f128)]
793
+ /// # // FIXME(f16_f128): remove when `eqtf2` is available
794
+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
795
+ ///
796
+ /// let value = f128::from_be_bytes(
797
+ /// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
798
+ /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
799
+ /// );
800
+ /// assert_eq!(value, 12.5);
801
+ /// # }
802
+ /// ```
803
+ #[ inline]
804
+ #[ must_use]
805
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
806
+ pub fn from_be_bytes ( bytes : [ u8 ; 16 ] ) -> Self {
807
+ Self :: from_bits ( u128:: from_be_bytes ( bytes) )
808
+ }
809
+
810
+ /// Create a floating point value from its representation as a byte array in little endian.
811
+ ///
812
+ /// See [`from_bits`](Self::from_bits) for some discussion of the
813
+ /// portability of this operation (there are almost no issues).
814
+ ///
815
+ /// # Examples
816
+ ///
817
+ /// ```
818
+ /// #![feature(f128)]
819
+ /// # // FIXME(f16_f128): remove when `eqtf2` is available
820
+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
821
+ ///
822
+ /// let value = f128::from_le_bytes(
823
+ /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
824
+ /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x02, 0x40]
825
+ /// );
826
+ /// assert_eq!(value, 12.5);
827
+ /// # }
828
+ /// ```
829
+ #[ inline]
830
+ #[ must_use]
831
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
832
+ pub fn from_le_bytes ( bytes : [ u8 ; 16 ] ) -> Self {
833
+ Self :: from_bits ( u128:: from_le_bytes ( bytes) )
834
+ }
835
+
836
+ /// Create a floating point value from its representation as a byte array in native endian.
837
+ ///
838
+ /// As the target platform's native endianness is used, portable code
839
+ /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
840
+ /// appropriate instead.
841
+ ///
842
+ /// [`from_be_bytes`]: f128::from_be_bytes
843
+ /// [`from_le_bytes`]: f128::from_le_bytes
844
+ ///
845
+ /// See [`from_bits`](Self::from_bits) for some discussion of the
846
+ /// portability of this operation (there are almost no issues).
847
+ ///
848
+ /// # Examples
849
+ ///
850
+ /// ```
851
+ /// #![feature(f128)]
852
+ /// # // FIXME(f16_f128): remove when `eqtf2` is available
853
+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
854
+ ///
855
+ /// let value = f128::from_ne_bytes(if cfg!(target_endian = "big") {
856
+ /// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
857
+ /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
858
+ /// } else {
859
+ /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
860
+ /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x02, 0x40]
861
+ /// });
862
+ /// assert_eq!(value, 12.5);
863
+ /// # }
864
+ /// ```
865
+ #[ inline]
866
+ #[ must_use]
867
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
868
+ pub fn from_ne_bytes ( bytes : [ u8 ; 16 ] ) -> Self {
869
+ Self :: from_bits ( u128:: from_ne_bytes ( bytes) )
870
+ }
871
+
872
+ /// Return the ordering between `self` and `other`.
873
+ ///
874
+ /// Unlike the standard partial comparison between floating point numbers,
875
+ /// this comparison always produces an ordering in accordance to
876
+ /// the `totalOrder` predicate as defined in the IEEE 754 (2008 revision)
877
+ /// floating point standard. The values are ordered in the following sequence:
878
+ ///
879
+ /// - negative quiet NaN
880
+ /// - negative signaling NaN
881
+ /// - negative infinity
882
+ /// - negative numbers
883
+ /// - negative subnormal numbers
884
+ /// - negative zero
885
+ /// - positive zero
886
+ /// - positive subnormal numbers
887
+ /// - positive numbers
888
+ /// - positive infinity
889
+ /// - positive signaling NaN
890
+ /// - positive quiet NaN.
891
+ ///
892
+ /// The ordering established by this function does not always agree with the
893
+ /// [`PartialOrd`] and [`PartialEq`] implementations of `f128`. For example,
894
+ /// they consider negative and positive zero equal, while `total_cmp`
895
+ /// doesn't.
896
+ ///
897
+ /// The interpretation of the signaling NaN bit follows the definition in
898
+ /// the IEEE 754 standard, which may not match the interpretation by some of
899
+ /// the older, non-conformant (e.g. MIPS) hardware implementations.
900
+ ///
901
+ /// # Example
902
+ ///
903
+ /// ```
904
+ /// #![feature(f128)]
905
+ ///
906
+ /// struct GoodBoy {
907
+ /// name: &'static str,
908
+ /// weight: f128,
909
+ /// }
910
+ ///
911
+ /// let mut bois = vec![
912
+ /// GoodBoy { name: "Pucci", weight: 0.1 },
913
+ /// GoodBoy { name: "Woofer", weight: 99.0 },
914
+ /// GoodBoy { name: "Yapper", weight: 10.0 },
915
+ /// GoodBoy { name: "Chonk", weight: f128::INFINITY },
916
+ /// GoodBoy { name: "Abs. Unit", weight: f128::NAN },
917
+ /// GoodBoy { name: "Floaty", weight: -5.0 },
918
+ /// ];
919
+ ///
920
+ /// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight));
921
+ ///
922
+ /// // `f128::NAN` could be positive or negative, which will affect the sort order.
923
+ /// if f128::NAN.is_sign_negative() {
924
+ /// bois.into_iter().map(|b| b.weight)
925
+ /// .zip([f128::NAN, -5.0, 0.1, 10.0, 99.0, f128::INFINITY].iter())
926
+ /// .for_each(|(a, b)| assert_eq!(a.to_bits(), b.to_bits()))
927
+ /// } else {
928
+ /// bois.into_iter().map(|b| b.weight)
929
+ /// .zip([-5.0, 0.1, 10.0, 99.0, f128::INFINITY, f128::NAN].iter())
930
+ /// .for_each(|(a, b)| assert_eq!(a.to_bits(), b.to_bits()))
931
+ /// }
932
+ /// ```
933
+ #[ inline]
934
+ #[ must_use]
935
+ #[ cfg( not( bootstrap) ) ]
936
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
937
+ pub fn total_cmp ( & self , other : & Self ) -> crate :: cmp:: Ordering {
938
+ let mut left = self . to_bits ( ) as i128 ;
939
+ let mut right = other. to_bits ( ) as i128 ;
940
+
941
+ // In case of negatives, flip all the bits except the sign
942
+ // to achieve a similar layout as two's complement integers
943
+ //
944
+ // Why does this work? IEEE 754 floats consist of three fields:
945
+ // Sign bit, exponent and mantissa. The set of exponent and mantissa
946
+ // fields as a whole have the property that their bitwise order is
947
+ // equal to the numeric magnitude where the magnitude is defined.
948
+ // The magnitude is not normally defined on NaN values, but
949
+ // IEEE 754 totalOrder defines the NaN values also to follow the
950
+ // bitwise order. This leads to order explained in the doc comment.
951
+ // However, the representation of magnitude is the same for negative
952
+ // and positive numbers – only the sign bit is different.
953
+ // To easily compare the floats as signed integers, we need to
954
+ // flip the exponent and mantissa bits in case of negative numbers.
955
+ // We effectively convert the numbers to "two's complement" form.
956
+ //
957
+ // To do the flipping, we construct a mask and XOR against it.
958
+ // We branchlessly calculate an "all-ones except for the sign bit"
959
+ // mask from negative-signed values: right shifting sign-extends
960
+ // the integer, so we "fill" the mask with sign bits, and then
961
+ // convert to unsigned to push one more zero bit.
962
+ // On positive values, the mask is all zeros, so it's a no-op.
963
+ left ^= ( ( ( left >> 127 ) as u128 ) >> 1 ) as i128 ;
964
+ right ^= ( ( ( right >> 127 ) as u128 ) >> 1 ) as i128 ;
965
+
966
+ left. cmp ( & right)
967
+ }
968
+
969
+ /// Restrict a value to a certain interval unless it is NaN.
970
+ ///
971
+ /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
972
+ /// less than `min`. Otherwise this returns `self`.
973
+ ///
974
+ /// Note that this function returns NaN if the initial value was NaN as
975
+ /// well.
976
+ ///
977
+ /// # Panics
978
+ ///
979
+ /// Panics if `min > max`, `min` is NaN, or `max` is NaN.
980
+ ///
981
+ /// # Examples
982
+ ///
983
+ /// ```
984
+ /// #![feature(f128)]
985
+ /// # // FIXME(f16_f128): remove when `{eq,gt,unord}tf` are available
986
+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
987
+ ///
988
+ /// assert!((-3.0f128).clamp(-2.0, 1.0) == -2.0);
989
+ /// assert!((0.0f128).clamp(-2.0, 1.0) == 0.0);
990
+ /// assert!((2.0f128).clamp(-2.0, 1.0) == 1.0);
991
+ /// assert!((f128::NAN).clamp(-2.0, 1.0).is_nan());
992
+ /// # }
993
+ /// ```
994
+ #[ inline]
995
+ #[ cfg( not( bootstrap) ) ]
996
+ #[ unstable( feature = "f128" , issue = "116909" ) ]
997
+ #[ must_use = "method returns a new number and does not mutate the original value" ]
998
+ pub fn clamp ( mut self , min : f128 , max : f128 ) -> f128 {
999
+ assert ! ( min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}" ) ;
1000
+ if self < min {
1001
+ self = min;
1002
+ }
1003
+ if self > max {
1004
+ self = max;
1005
+ }
1006
+ self
1007
+ }
370
1008
}
0 commit comments