Skip to content

Commit 74b3ff1

Browse files
committed
Add some f32 and f64 inherent methods in libcore
… previously in the unstable core::num::Float trait. Per rust-lang#32110 (comment), the `abs`, `signum`, and `powi` methods are *not* included for now since they rely on LLVM intrinsics and we haven’t determined yet whether those instrinsics lower to calls to libm functions on any platform.
1 parent d0afe7f commit 74b3ff1

File tree

10 files changed

+611
-559
lines changed

10 files changed

+611
-559
lines changed

src/liballoc/vec.rs

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ use core::iter::{FromIterator, FusedIterator, TrustedLen};
7474
use core::marker::PhantomData;
7575
use core::mem;
7676
#[cfg(not(test))]
77+
#[cfg(stage0)]
7778
use core::num::Float;
7879
use core::ops::Bound::{Excluded, Included, Unbounded};
7980
use core::ops::{Index, IndexMut, RangeBounds};

src/libcore/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
#![feature(cfg_target_has_atomic)]
7373
#![feature(concat_idents)]
7474
#![feature(const_fn)]
75+
#![feature(core_float)]
7576
#![feature(custom_attribute)]
7677
#![feature(doc_cfg)]
7778
#![feature(doc_spotlight)]

src/libcore/num/f32.rs

+284
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use intrinsics;
2121
use mem;
2222
use num::Float;
23+
#[cfg(not(stage0))] use num::FpCategory;
2324
use num::FpCategory as Fp;
2425

2526
/// The radix or base of the internal representation of `f32`.
@@ -292,3 +293,286 @@ impl Float for f32 {
292293
unsafe { mem::transmute(v) }
293294
}
294295
}
296+
297+
// FIXME: remove (inline) this macro and the Float trait
298+
// when updating to a bootstrap compiler that has the new lang items.
299+
#[cfg_attr(stage0, macro_export)]
300+
#[unstable(feature = "core_float", issue = "32110")]
301+
macro_rules! f32_core_methods { () => {
302+
/// Returns `true` if this value is `NaN` and false otherwise.
303+
///
304+
/// ```
305+
/// use std::f32;
306+
///
307+
/// let nan = f32::NAN;
308+
/// let f = 7.0_f32;
309+
///
310+
/// assert!(nan.is_nan());
311+
/// assert!(!f.is_nan());
312+
/// ```
313+
#[stable(feature = "rust1", since = "1.0.0")]
314+
#[inline]
315+
pub fn is_nan(self) -> bool { Float::is_nan(self) }
316+
317+
/// Returns `true` if this value is positive infinity or negative infinity and
318+
/// false otherwise.
319+
///
320+
/// ```
321+
/// use std::f32;
322+
///
323+
/// let f = 7.0f32;
324+
/// let inf = f32::INFINITY;
325+
/// let neg_inf = f32::NEG_INFINITY;
326+
/// let nan = f32::NAN;
327+
///
328+
/// assert!(!f.is_infinite());
329+
/// assert!(!nan.is_infinite());
330+
///
331+
/// assert!(inf.is_infinite());
332+
/// assert!(neg_inf.is_infinite());
333+
/// ```
334+
#[stable(feature = "rust1", since = "1.0.0")]
335+
#[inline]
336+
pub fn is_infinite(self) -> bool { Float::is_infinite(self) }
337+
338+
/// Returns `true` if this number is neither infinite nor `NaN`.
339+
///
340+
/// ```
341+
/// use std::f32;
342+
///
343+
/// let f = 7.0f32;
344+
/// let inf = f32::INFINITY;
345+
/// let neg_inf = f32::NEG_INFINITY;
346+
/// let nan = f32::NAN;
347+
///
348+
/// assert!(f.is_finite());
349+
///
350+
/// assert!(!nan.is_finite());
351+
/// assert!(!inf.is_finite());
352+
/// assert!(!neg_inf.is_finite());
353+
/// ```
354+
#[stable(feature = "rust1", since = "1.0.0")]
355+
#[inline]
356+
pub fn is_finite(self) -> bool { Float::is_finite(self) }
357+
358+
/// Returns `true` if the number is neither zero, infinite,
359+
/// [subnormal][subnormal], or `NaN`.
360+
///
361+
/// ```
362+
/// use std::f32;
363+
///
364+
/// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
365+
/// let max = f32::MAX;
366+
/// let lower_than_min = 1.0e-40_f32;
367+
/// let zero = 0.0_f32;
368+
///
369+
/// assert!(min.is_normal());
370+
/// assert!(max.is_normal());
371+
///
372+
/// assert!(!zero.is_normal());
373+
/// assert!(!f32::NAN.is_normal());
374+
/// assert!(!f32::INFINITY.is_normal());
375+
/// // Values between `0` and `min` are Subnormal.
376+
/// assert!(!lower_than_min.is_normal());
377+
/// ```
378+
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
379+
#[stable(feature = "rust1", since = "1.0.0")]
380+
#[inline]
381+
pub fn is_normal(self) -> bool { Float::is_normal(self) }
382+
383+
/// Returns the floating point category of the number. If only one property
384+
/// is going to be tested, it is generally faster to use the specific
385+
/// predicate instead.
386+
///
387+
/// ```
388+
/// use std::num::FpCategory;
389+
/// use std::f32;
390+
///
391+
/// let num = 12.4_f32;
392+
/// let inf = f32::INFINITY;
393+
///
394+
/// assert_eq!(num.classify(), FpCategory::Normal);
395+
/// assert_eq!(inf.classify(), FpCategory::Infinite);
396+
/// ```
397+
#[stable(feature = "rust1", since = "1.0.0")]
398+
#[inline]
399+
pub fn classify(self) -> FpCategory { Float::classify(self) }
400+
401+
/// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
402+
/// positive sign bit and positive infinity.
403+
///
404+
/// ```
405+
/// let f = 7.0_f32;
406+
/// let g = -7.0_f32;
407+
///
408+
/// assert!(f.is_sign_positive());
409+
/// assert!(!g.is_sign_positive());
410+
/// ```
411+
#[stable(feature = "rust1", since = "1.0.0")]
412+
#[inline]
413+
pub fn is_sign_positive(self) -> bool { Float::is_sign_positive(self) }
414+
415+
/// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
416+
/// negative sign bit and negative infinity.
417+
///
418+
/// ```
419+
/// let f = 7.0f32;
420+
/// let g = -7.0f32;
421+
///
422+
/// assert!(!f.is_sign_negative());
423+
/// assert!(g.is_sign_negative());
424+
/// ```
425+
#[stable(feature = "rust1", since = "1.0.0")]
426+
#[inline]
427+
pub fn is_sign_negative(self) -> bool { Float::is_sign_negative(self) }
428+
429+
/// Takes the reciprocal (inverse) of a number, `1/x`.
430+
///
431+
/// ```
432+
/// use std::f32;
433+
///
434+
/// let x = 2.0_f32;
435+
/// let abs_difference = (x.recip() - (1.0/x)).abs();
436+
///
437+
/// assert!(abs_difference <= f32::EPSILON);
438+
/// ```
439+
#[stable(feature = "rust1", since = "1.0.0")]
440+
#[inline]
441+
pub fn recip(self) -> f32 { Float::recip(self) }
442+
443+
/// Converts radians to degrees.
444+
///
445+
/// ```
446+
/// use std::f32::{self, consts};
447+
///
448+
/// let angle = consts::PI;
449+
///
450+
/// let abs_difference = (angle.to_degrees() - 180.0).abs();
451+
///
452+
/// assert!(abs_difference <= f32::EPSILON);
453+
/// ```
454+
#[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
455+
#[inline]
456+
pub fn to_degrees(self) -> f32 { Float::to_degrees(self) }
457+
458+
/// Converts degrees to radians.
459+
///
460+
/// ```
461+
/// use std::f32::{self, consts};
462+
///
463+
/// let angle = 180.0f32;
464+
///
465+
/// let abs_difference = (angle.to_radians() - consts::PI).abs();
466+
///
467+
/// assert!(abs_difference <= f32::EPSILON);
468+
/// ```
469+
#[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
470+
#[inline]
471+
pub fn to_radians(self) -> f32 { Float::to_radians(self) }
472+
473+
/// Returns the maximum of the two numbers.
474+
///
475+
/// ```
476+
/// let x = 1.0f32;
477+
/// let y = 2.0f32;
478+
///
479+
/// assert_eq!(x.max(y), y);
480+
/// ```
481+
///
482+
/// If one of the arguments is NaN, then the other argument is returned.
483+
#[stable(feature = "rust1", since = "1.0.0")]
484+
#[inline]
485+
pub fn max(self, other: f32) -> f32 {
486+
Float::max(self, other)
487+
}
488+
489+
/// Returns the minimum of the two numbers.
490+
///
491+
/// ```
492+
/// let x = 1.0f32;
493+
/// let y = 2.0f32;
494+
///
495+
/// assert_eq!(x.min(y), x);
496+
/// ```
497+
///
498+
/// If one of the arguments is NaN, then the other argument is returned.
499+
#[stable(feature = "rust1", since = "1.0.0")]
500+
#[inline]
501+
pub fn min(self, other: f32) -> f32 {
502+
Float::min(self, other)
503+
}
504+
505+
/// Raw transmutation to `u32`.
506+
///
507+
/// This is currently identical to `transmute::<f32, u32>(self)` on all platforms.
508+
///
509+
/// See `from_bits` for some discussion of the portability of this operation
510+
/// (there are almost no issues).
511+
///
512+
/// Note that this function is distinct from `as` casting, which attempts to
513+
/// preserve the *numeric* value, and not the bitwise value.
514+
///
515+
/// # Examples
516+
///
517+
/// ```
518+
/// assert_ne!((1f32).to_bits(), 1f32 as u32); // to_bits() is not casting!
519+
/// assert_eq!((12.5f32).to_bits(), 0x41480000);
520+
///
521+
/// ```
522+
#[stable(feature = "float_bits_conv", since = "1.20.0")]
523+
#[inline]
524+
pub fn to_bits(self) -> u32 {
525+
Float::to_bits(self)
526+
}
527+
528+
/// Raw transmutation from `u32`.
529+
///
530+
/// This is currently identical to `transmute::<u32, f32>(v)` on all platforms.
531+
/// It turns out this is incredibly portable, for two reasons:
532+
///
533+
/// * Floats and Ints have the same endianness on all supported platforms.
534+
/// * IEEE-754 very precisely specifies the bit layout of floats.
535+
///
536+
/// However there is one caveat: prior to the 2008 version of IEEE-754, how
537+
/// to interpret the NaN signaling bit wasn't actually specified. Most platforms
538+
/// (notably x86 and ARM) picked the interpretation that was ultimately
539+
/// standardized in 2008, but some didn't (notably MIPS). As a result, all
540+
/// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
541+
///
542+
/// Rather than trying to preserve signaling-ness cross-platform, this
543+
/// implementation favours preserving the exact bits. This means that
544+
/// any payloads encoded in NaNs will be preserved even if the result of
545+
/// this method is sent over the network from an x86 machine to a MIPS one.
546+
///
547+
/// If the results of this method are only manipulated by the same
548+
/// architecture that produced them, then there is no portability concern.
549+
///
550+
/// If the input isn't NaN, then there is no portability concern.
551+
///
552+
/// If you don't care about signalingness (very likely), then there is no
553+
/// portability concern.
554+
///
555+
/// Note that this function is distinct from `as` casting, which attempts to
556+
/// preserve the *numeric* value, and not the bitwise value.
557+
///
558+
/// # Examples
559+
///
560+
/// ```
561+
/// use std::f32;
562+
/// let v = f32::from_bits(0x41480000);
563+
/// let difference = (v - 12.5).abs();
564+
/// assert!(difference <= 1e-5);
565+
/// ```
566+
#[stable(feature = "float_bits_conv", since = "1.20.0")]
567+
#[inline]
568+
pub fn from_bits(v: u32) -> Self {
569+
Float::from_bits(v)
570+
}
571+
}}
572+
573+
#[lang = "f32"]
574+
#[cfg(not(test))]
575+
#[cfg(not(stage0))]
576+
impl f32 {
577+
f32_core_methods!();
578+
}

0 commit comments

Comments
 (0)