From aa9ceba628f495d1b7de190fa564de43d90c8d84 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 27 Feb 2018 22:12:37 -0800 Subject: [PATCH] Add doctests to FloatCore --- src/float.rs | 504 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 499 insertions(+), 5 deletions(-) diff --git a/src/float.rs b/src/float.rs index d35b071..eeeb48b 100644 --- a/src/float.rs +++ b/src/float.rs @@ -12,48 +12,230 @@ use {Num, NumCast}; /// This trait implements a subset of the `Float` trait. pub trait FloatCore: Num + NumCast + Neg + PartialOrd + Copy { /// Returns positive infinity. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T) { + /// assert!(T::infinity() == x); + /// } + /// + /// check(f32::INFINITY); + /// check(f64::INFINITY); + /// ``` fn infinity() -> Self; /// Returns negative infinity. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T) { + /// assert!(T::neg_infinity() == x); + /// } + /// + /// check(f32::NEG_INFINITY); + /// check(f64::NEG_INFINITY); + /// ``` fn neg_infinity() -> Self; /// Returns NaN. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// + /// fn check() { + /// let n = T::nan(); + /// assert!(n != n); + /// } + /// + /// check::(); + /// check::(); + /// ``` fn nan() -> Self; /// Returns `-0.0`. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(n: T) { + /// let z = T::neg_zero(); + /// assert!(z.is_zero()); + /// assert!(T::one() / z == n); + /// } + /// + /// check(f32::NEG_INFINITY); + /// check(f64::NEG_INFINITY); + /// ``` fn neg_zero() -> Self; /// Returns the smallest finite value that this type can represent. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T) { + /// assert!(T::min_value() == x); + /// } + /// + /// check(f32::MIN); + /// check(f64::MIN); + /// ``` fn min_value() -> Self; /// Returns the smallest positive, normalized value that this type can represent. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T) { + /// assert!(T::min_positive_value() == x); + /// } + /// + /// check(f32::MIN_POSITIVE); + /// check(f64::MIN_POSITIVE); + /// ``` fn min_positive_value() -> Self; /// Returns epsilon, a small positive value. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T) { + /// assert!(T::epsilon() == x); + /// } + /// + /// check(f32::EPSILON); + /// check(f64::EPSILON); + /// ``` fn epsilon() -> Self; /// Returns the largest finite value that this type can represent. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T) { + /// assert!(T::max_value() == x); + /// } + /// + /// check(f32::MAX); + /// check(f64::MAX); + /// ``` fn max_value() -> Self; /// Returns `true` if the number is NaN. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, p: bool) { + /// assert!(x.is_nan() == p); + /// } + /// + /// check(f32::NAN, true); + /// check(f32::INFINITY, false); + /// check(f64::NAN, true); + /// check(0.0f64, false); + /// ``` #[inline] fn is_nan(self) -> bool { self != self } /// Returns `true` if the number is infinite. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, p: bool) { + /// assert!(x.is_infinite() == p); + /// } + /// + /// check(f32::INFINITY, true); + /// check(f32::NEG_INFINITY, true); + /// check(f32::NAN, false); + /// check(f64::INFINITY, true); + /// check(f64::NEG_INFINITY, true); + /// check(0.0f64, false); + /// ``` #[inline] fn is_infinite(self) -> bool { self == Self::infinity() || self == Self::neg_infinity() } /// Returns `true` if the number is neither infinite or NaN. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, p: bool) { + /// assert!(x.is_finite() == p); + /// } + /// + /// check(f32::INFINITY, false); + /// check(f32::MAX, true); + /// check(f64::NEG_INFINITY, false); + /// check(f64::MIN_POSITIVE, true); + /// check(f64::NAN, false); + /// ``` #[inline] fn is_finite(self) -> bool { !(self.is_nan() || self.is_infinite()) } /// Returns `true` if the number is neither zero, infinite, subnormal or NaN. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, p: bool) { + /// assert!(x.is_normal() == p); + /// } + /// + /// check(f32::INFINITY, false); + /// check(f32::MAX, true); + /// check(f64::NEG_INFINITY, false); + /// check(f64::MIN_POSITIVE, true); + /// check(0.0f64, false); + /// ``` #[inline] fn is_normal(self) -> bool { self.classify() == FpCategory::Normal @@ -62,9 +244,49 @@ pub trait FloatCore: Num + NumCast + Neg + PartialOrd + Copy { /// Returns the floating point category of the number. If only one property /// is going to be tested, it is generally faster to use the specific /// predicate instead. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// use std::num::FpCategory; + /// + /// fn check(x: T, c: FpCategory) { + /// assert!(x.classify() == c); + /// } + /// + /// check(f32::INFINITY, FpCategory::Infinite); + /// check(f32::MAX, FpCategory::Normal); + /// check(f64::NAN, FpCategory::Nan); + /// check(f64::MIN_POSITIVE, FpCategory::Normal); + /// check(f64::MIN_POSITIVE / 2.0, FpCategory::Subnormal); + /// check(0.0f64, FpCategory::Zero); + /// ``` fn classify(self) -> FpCategory; /// Returns the largest integer less than or equal to a number. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, y: T) { + /// assert!(x.floor() == y); + /// } + /// + /// check(f32::INFINITY, f32::INFINITY); + /// check(0.9f32, 0.0); + /// check(1.0f32, 1.0); + /// check(1.1f32, 1.0); + /// check(-0.0f64, 0.0); + /// check(-0.9f64, -1.0); + /// check(-1.0f64, -1.0); + /// check(-1.1f64, -2.0); + /// check(f64::MIN, f64::MIN); + /// ``` #[inline] fn floor(self) -> Self { let f = self.fract(); @@ -78,6 +300,27 @@ pub trait FloatCore: Num + NumCast + Neg + PartialOrd + Copy { } /// Returns the smallest integer greater than or equal to a number. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, y: T) { + /// assert!(x.ceil() == y); + /// } + /// + /// check(f32::INFINITY, f32::INFINITY); + /// check(0.9f32, 1.0); + /// check(1.0f32, 1.0); + /// check(1.1f32, 2.0); + /// check(-0.0f64, 0.0); + /// check(-0.9f64, -0.0); + /// check(-1.0f64, -1.0); + /// check(-1.1f64, -1.0); + /// check(f64::MIN, f64::MIN); + /// ``` #[inline] fn ceil(self) -> Self { let f = self.fract(); @@ -91,6 +334,26 @@ pub trait FloatCore: Num + NumCast + Neg + PartialOrd + Copy { } /// Returns the nearest integer to a number. Round half-way cases away from `0.0`. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, y: T) { + /// assert!(x.round() == y); + /// } + /// + /// check(f32::INFINITY, f32::INFINITY); + /// check(0.4f32, 0.0); + /// check(0.5f32, 1.0); + /// check(0.6f32, 1.0); + /// check(-0.4f64, 0.0); + /// check(-0.5f64, -1.0); + /// check(-0.6f64, -1.0); + /// check(f64::MIN, f64::MIN); + /// ``` #[inline] fn round(self) -> Self { let one = Self::one(); @@ -114,6 +377,27 @@ pub trait FloatCore: Num + NumCast + Neg + PartialOrd + Copy { } /// Return the integer part of a number. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, y: T) { + /// assert!(x.trunc() == y); + /// } + /// + /// check(f32::INFINITY, f32::INFINITY); + /// check(0.9f32, 0.0); + /// check(1.0f32, 1.0); + /// check(1.1f32, 1.0); + /// check(-0.0f64, 0.0); + /// check(-0.9f64, -0.0); + /// check(-1.0f64, -1.0); + /// check(-1.1f64, -1.0); + /// check(f64::MIN, f64::MIN); + /// ``` #[inline] fn trunc(self) -> Self { let f = self.fract(); @@ -125,6 +409,27 @@ pub trait FloatCore: Num + NumCast + Neg + PartialOrd + Copy { } /// Returns the fractional part of a number. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, y: T) { + /// assert!(x.fract() == y); + /// } + /// + /// check(f32::MAX, 0.0); + /// check(0.75f32, 0.75); + /// check(1.0f32, 0.0); + /// check(1.25f32, 0.25); + /// check(-0.0f64, 0.0); + /// check(-0.75f64, -0.75); + /// check(-1.0f64, 0.0); + /// check(-1.25f64, -0.25); + /// check(f64::MIN, 0.0); + /// ``` #[inline] fn fract(self) -> Self { if self.is_zero() { @@ -136,6 +441,24 @@ pub trait FloatCore: Num + NumCast + Neg + PartialOrd + Copy { /// Computes the absolute value of `self`. Returns `FloatCore::nan()` if the /// number is `FloatCore::nan()`. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, y: T) { + /// assert!(x.abs() == y); + /// } + /// + /// check(f32::INFINITY, f32::INFINITY); + /// check(1.0f32, 1.0); + /// check(0.0f64, 0.0); + /// check(-0.0f64, 0.0); + /// check(-1.0f64, 1.0); + /// check(f64::MIN, f64::MAX); + /// ``` #[inline] fn abs(self) -> Self { if self.is_sign_positive() { @@ -152,6 +475,24 @@ pub trait FloatCore: Num + NumCast + Neg + PartialOrd + Copy { /// - `1.0` if the number is positive, `+0.0` or `FloatCore::infinity()` /// - `-1.0` if the number is negative, `-0.0` or `FloatCore::neg_infinity()` /// - `FloatCore::nan()` if the number is `FloatCore::nan()` + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, y: T) { + /// assert!(x.signum() == y); + /// } + /// + /// check(f32::INFINITY, 1.0); + /// check(3.0f32, 1.0); + /// check(0.0f32, 1.0); + /// check(-0.0f64, -1.0); + /// check(-3.0f64, -1.0); + /// check(f64::MIN, -1.0); + /// ``` #[inline] fn signum(self) -> Self { if self.is_nan() { @@ -164,14 +505,54 @@ pub trait FloatCore: Num + NumCast + Neg + PartialOrd + Copy { } /// Returns `true` if `self` is positive, including `+0.0` and - /// `FloatCore::infinity()`. + /// `FloatCore::infinity()`, and with newer versions of Rust + /// even `FloatCore::nan()`. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, p: bool) { + /// assert!(x.is_sign_positive() == p); + /// } + /// + /// check(f32::INFINITY, true); + /// check(f32::MAX, true); + /// check(0.0f32, true); + /// check(-0.0f64, false); + /// check(f64::NEG_INFINITY, false); + /// check(f64::MIN_POSITIVE, true); + /// check(-f64::NAN, false); + /// ``` #[inline] fn is_sign_positive(self) -> bool { !self.is_sign_negative() } /// Returns `true` if `self` is negative, including `-0.0` and - /// `FloatCore::neg_infinity()`. + /// `FloatCore::neg_infinity()`, and with newer versions of Rust + /// even `-FloatCore::nan()`. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, p: bool) { + /// assert!(x.is_sign_negative() == p); + /// } + /// + /// check(f32::INFINITY, false); + /// check(f32::MAX, false); + /// check(0.0f32, false); + /// check(-0.0f64, true); + /// check(f64::NEG_INFINITY, true); + /// check(f64::MIN_POSITIVE, false); + /// check(f64::NAN, false); + /// ``` #[inline] fn is_sign_negative(self) -> bool { let (_, _, sign) = self.integer_decode(); @@ -181,6 +562,22 @@ pub trait FloatCore: Num + NumCast + Neg + PartialOrd + Copy { /// Returns the minimum of the two numbers. /// /// If one of the arguments is NaN, then the other argument is returned. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, y: T, min: T) { + /// assert!(x.min(y) == min); + /// } + /// + /// check(1.0f32, 2.0, 1.0); + /// check(f32::NAN, 2.0, 2.0); + /// check(1.0f64, -2.0, -2.0); + /// check(1.0f64, f64::NAN, 1.0); + /// ``` #[inline] fn min(self, other: Self) -> Self { if self.is_nan() { @@ -195,6 +592,22 @@ pub trait FloatCore: Num + NumCast + Neg + PartialOrd + Copy { /// Returns the maximum of the two numbers. /// /// If one of the arguments is NaN, then the other argument is returned. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, y: T, min: T) { + /// assert!(x.max(y) == min); + /// } + /// + /// check(1.0f32, 2.0, 2.0); + /// check(1.0f32, f32::NAN, 1.0); + /// check(-1.0f64, 2.0, 2.0); + /// check(-1.0f64, f64::NAN, -1.0); + /// ``` #[inline] fn max(self, other: Self) -> Self { if self.is_nan() { @@ -207,6 +620,23 @@ pub trait FloatCore: Num + NumCast + Neg + PartialOrd + Copy { } /// Returns the reciprocal (multiplicative inverse) of the number. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, y: T) { + /// assert!(x.recip() == y); + /// assert!(y.recip() == x); + /// } + /// + /// check(f32::INFINITY, 0.0); + /// check(2.0f32, 0.5); + /// check(-0.25f64, -4.0); + /// check(-0.0f64, f64::NEG_INFINITY); + /// ``` #[inline] fn recip(self) -> Self { Self::one() / self @@ -215,6 +645,22 @@ pub trait FloatCore: Num + NumCast + Neg + PartialOrd + Copy { /// Raise a number to an integer power. /// /// Using this function is generally faster than using `powf` + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// + /// fn check(x: T, exp: i32, powi: T) { + /// assert!(x.powi(exp) == powi); + /// } + /// + /// check(9.0f32, 2, 81.0); + /// check(1.0f32, -2, 1.0); + /// check(10.0f64, 20, 1e20); + /// check(4.0f64, -2, 0.0625); + /// check(-1.0f64, std::i32::MIN, 1.0); + /// ``` #[inline] fn powi(mut self, mut exp: i32) -> Self { if exp < 0 { @@ -226,14 +672,64 @@ pub trait FloatCore: Num + NumCast + Neg + PartialOrd + Copy { } /// Converts to degrees, assuming the number is in radians. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(rad: T, deg: T) { + /// assert!(rad.to_degrees() == deg); + /// } + /// + /// check(0.0f32, 0.0); + /// check(f32::consts::PI, 180.0); + /// check(f64::consts::FRAC_PI_4, 45.0); + /// check(f64::INFINITY, f64::INFINITY); + /// ``` fn to_degrees(self) -> Self; /// Converts to radians, assuming the number is in degrees. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(deg: T, rad: T) { + /// assert!(deg.to_radians() == rad); + /// } + /// + /// check(0.0f32, 0.0); + /// check(180.0, f32::consts::PI); + /// check(45.0, f64::consts::FRAC_PI_4); + /// check(f64::INFINITY, f64::INFINITY); + /// ``` fn to_radians(self) -> Self; /// Returns the mantissa, base 2 exponent, and sign as integers, respectively. /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`. - /// The floating point encoding is documented in the [Reference][floating-point]. + /// + /// # Examples + /// + /// ``` + /// use num_traits::float::FloatCore; + /// use std::{f32, f64}; + /// + /// fn check(x: T, m: u64, e: i16, s:i8) { + /// let (mantissa, exponent, sign) = x.integer_decode(); + /// assert_eq!(mantissa, m); + /// assert_eq!(exponent, e); + /// assert_eq!(sign, s); + /// } + /// + /// check(2.0f32, 1 << 23, -22, 1); + /// check(-2.0f32, 1 << 23, -22, -1); + /// check(f32::INFINITY, 1 << 23, 105, 1); + /// check(f64::NEG_INFINITY, 1 << 52, 972, -1); + /// ``` fn integer_decode(self) -> (u64, i16, i8); } @@ -1275,7 +1771,6 @@ pub trait Float /// Returns the mantissa, base 2 exponent, and sign as integers, respectively. /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`. - /// The floating point encoding is documented in the [Reference][floating-point]. /// /// ``` /// use num_traits::Float; @@ -1293,7 +1788,6 @@ pub trait Float /// /// assert!(abs_difference < 1e-10); /// ``` - /// [floating-point]: ../../../../../reference.html#machine-types fn integer_decode(self) -> (u64, i16, i8); }