From 0230b18624647601cee349b636e1c5f7ba4919be Mon Sep 17 00:00:00 2001 From: Jason Travis Smith Date: Sat, 1 Jul 2017 15:32:44 -0400 Subject: [PATCH] Fixed a lot of the cargo tests. This required Real functions to use libc. --- Cargo.lock | 44 ++ src/integer.rs | 164 ++++++- src/number.rs | 68 ++- src/real.rs | 1191 +++++++++++++++++++++++++++++----------------- src/trig/trig.rs | 138 +++--- src/vector.rs | 4 +- 6 files changed, 1080 insertions(+), 529 deletions(-) create mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..2622881 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,44 @@ +[root] +name = "sigils" +version = "0.1.0" +dependencies = [ + "binding 0.1.0 (git+ssh://git@gitlab.com/CyberMages/Core/binding)", + "pact 0.1.0 (git+ssh://git@gitlab.com/CyberMages/Core/pact)", +] + +[[package]] +name = "binding" +version = "0.1.0" +source = "git+ssh://git@gitlab.com/CyberMages/Core/binding#8b5d5a9c57a7f87b26bb741067babb7a0b765ae7" +dependencies = [ + "scribe 0.5.0 (git+ssh://git@gitlab.com/CyberMages/Core/scribe.git)", +] + +[[package]] +name = "pact" +version = "0.1.0" +source = "git+ssh://git@gitlab.com/CyberMages/Core/pact#6fc48f7a2d8c8bc049418d1f8ede206cb8818d53" +dependencies = [ + "binding 0.1.0 (git+ssh://git@gitlab.com/CyberMages/Core/binding)", + "scribe 0.5.0 (git+ssh://git@gitlab.com/CyberMages/Core/scribe.git)", + "weave 0.1.0 (git+ssh://git@gitlab.com/CyberMages/Core/weave.git)", +] + +[[package]] +name = "scribe" +version = "0.5.0" +source = "git+ssh://git@gitlab.com/CyberMages/Core/scribe.git#483ccd455c635e4975058a5d68b6fb4882bf5ddb" + +[[package]] +name = "weave" +version = "0.1.0" +source = "git+ssh://git@gitlab.com/CyberMages/Core/weave.git#b0f38fb13bc7d1ed937fa51e499b602cb175c52b" +dependencies = [ + "scribe 0.5.0 (git+ssh://git@gitlab.com/CyberMages/Core/scribe.git)", +] + +[metadata] +"checksum binding 0.1.0 (git+ssh://git@gitlab.com/CyberMages/Core/binding)" = "" +"checksum pact 0.1.0 (git+ssh://git@gitlab.com/CyberMages/Core/pact)" = "" +"checksum scribe 0.5.0 (git+ssh://git@gitlab.com/CyberMages/Core/scribe.git)" = "" +"checksum weave 0.1.0 (git+ssh://git@gitlab.com/CyberMages/Core/weave.git)" = "" diff --git a/src/integer.rs b/src/integer.rs index 96384d4..49ba7e3 100644 --- a/src/integer.rs +++ b/src/integer.rs @@ -1,4 +1,6 @@ -use super::number::Number; +use ::number::Number; +use ::one::One; +use ::zero::Zero; /// A trait that defines what is required to be considered @@ -24,23 +26,175 @@ use super::number::Number; /// [12]: https://doc.rust-lang.org/std/index.html pub trait Integer: Number { + /// Computes the absolute value of `self`. + /// Returns ::MIN if the number is ::MIN. + /// + /// ``` + /// use sigils::{Integer, Number}; + /// + /// let x = -75i32; + /// let y = 84i16; + /// + /// assert_eq!(x.abs(), 75i32); + /// assert_eq!(y.abs(), 84i16); + /// assert_eq!(u8::MIN.abs(), u8::MIN); + /// ``` + fn abs(self) -> Self; + + /// Returns a number that represents the sign of `self`. + /// + /// - `1` if the number is positive, `(0, MAX]` + /// - `0` if the number is zero, `[0]` + /// - `-1` if the number is negative, `[MIN, 0)` + /// + /// ``` + /// use sigils::Integer; + /// + /// let e = -3i32; + /// let f = 3u64; + /// let g = 0i64; + /// + /// assert_eq!(e.signum(), -1i32); + /// assert_eq!(f.signum(), 1u64); + /// assert_eq!(g.signum(), 0i64); + /// ``` + fn signum(self) -> Self; + + /// Returns `true` if `self` is positive and + /// 'false' if the Integer is zero or negative. + /// (0, MAX] + /// + /// ``` + /// use sigils::Integer; + /// + /// let e: i32; + /// let f: i32; + /// let g: u64; + /// + /// e = 5i32; + /// f = -33i32; + /// g = 782u64; + /// + /// assert!(e.is_sign_positive() == true); + /// assert!(f.is_sign_positive() == false); + /// assert!(g.is_sign_positive() == true); + /// ``` + fn is_sign_positive(self) -> bool; + + /// Returns `true` if `self` is negative and + /// 'false' if the Integer is zero or positive. + /// [MIN, 0) + /// + /// ``` + /// use sigils::Integer; + /// + /// let e: i32; + /// let f: i32; + /// let g: u64; + /// + /// e = 5i32; + /// f = -33i32; + /// g = 782u64; + /// + /// assert!(e.is_sign_negative() == false); + /// assert!(f.is_sign_negative() == true); + /// assert!(g.is_sign_negative() == false); + /// ``` + fn is_sign_negative(self) -> bool; } + // Create a macro to ease typing and reading. /// A macro to make implementing the trait easier for all the -/// base integer types in rust. -macro_rules! integer_trait_impl +/// base integer signed types in rust. +macro_rules! signed_trait_impl { ($traitName: ident for $($varType: ty)*) => ($( impl $traitName for $varType { + fn abs(self) -> Self + { + if self < Self::zero() + { + -self + } + else + { + self + } + } + + fn signum(self) -> Self + { + if self.is_sign_negative() == true + { + -1 + } + else if self.is_sign_positive() == true + { + Self::one() + } + else + { + Self::zero() + } + } + + fn is_sign_negative(self) -> bool + { + self < Self::zero() + } + + fn is_sign_positive(self) -> bool + { + self > Self::zero() + } + } + )*) +} + +/// A macro to make implementing the trait easier for all the +/// base integer unsigned types in rust. +macro_rules! unsigned_trait_impl +{ + ($traitName: ident for $($varType: ty)*) => + ($( + impl $traitName for $varType + { + fn abs(self) -> Self + { + self + } + + fn signum(self) -> Self + { + if self == Self::zero() + { + Self::zero() + } + else + { + Self::one() + } + } + + fn is_sign_negative(self) -> bool + { + false + } + + fn is_sign_positive(self) -> bool + { + self > Self::zero() + } } )*) } + // Implement the trait for the types that are Integers. -integer_trait_impl!(Integer for u8 u16 u32 u64 usize); -integer_trait_impl!(Integer for i8 i16 i32 i64 isize); +signed_trait_impl!(Integer for i8 i16 i32 i64 isize); +unsigned_trait_impl!(Integer for u8 u16 u32 u64 usize); diff --git a/src/number.rs b/src/number.rs index 999dc94..6a31880 100644 --- a/src/number.rs +++ b/src/number.rs @@ -21,6 +21,15 @@ pub trait Number : Zero + One + Add + Sub + type StrRadixError; + + /// The smallest number that can be stored in this type. + const MIN: Self; + + /// The largest number that can be stored in this type. + const MAX: Self; + + + /// Create a number from a given string and base radix. /// ///``` @@ -749,33 +758,45 @@ macro_rules! from_number_impl /// base integer types in rust. macro_rules! int_number_trait_impl { - ($traitName: ident for $($varType: ty)*) => - ($( + ($traitName: ident for $varType: ty, $min: expr, $max: expr) => + { impl $traitName for $varType { type StrRadixError = ::std::num::ParseIntError; + + const MIN: Self = $min; + const MAX: Self = $max; + + + fn from_str_radix(src: &str, radix: u32) -> Result { <$varType>::from_str_radix(src, radix) } } - )*) + } } /// A macro to make implementing the Number trait easier for all the /// base float types in rust. macro_rules! float_number_trait_impl { - ($traitName: ident for $($varType: ty, $numBytes: expr)*) => - ($( + ($traitName: ident for $varType: ty, $min: expr, $max: expr) => + { impl $traitName for $varType { type StrRadixError = ::std::num::ParseFloatError; + + const MIN: Self = $min; + const MAX: Self = $max; + + + fn from_str_radix(src: &str, radix: u32) -> Result { @@ -788,14 +809,43 @@ macro_rules! float_number_trait_impl <$varType>::from_str(src) } } - )*) + } } // Implement the Number trait for the types that are Numbers. -int_number_trait_impl!(Number for u8 u16 u32 u64 usize); -int_number_trait_impl!(Number for i8 i16 i32 i64 isize); -float_number_trait_impl!(Number for f32, 4 f64, 8); +int_number_trait_impl!(Number for u8, 0u8, 255u8); +int_number_trait_impl!(Number for u16, 0u16, 65535u16); +int_number_trait_impl!(Number for u32, 0u32, 4294967295u32); +int_number_trait_impl!(Number for u64, 0u64, 18446744073709551615u64); +int_number_trait_impl!(Number for i8, -128i8, 127i8); +int_number_trait_impl!(Number for i16, -32768i16, 32767i16); +int_number_trait_impl!(Number for i32, -2147483648i32, 2147483647i32); +int_number_trait_impl!(Number for i64, -9223372036854775808i64, + 9223372036854775807i64); +float_number_trait_impl!(Number for f32, -3.40282347e+38f32, + 3.40282347e+38f32); +float_number_trait_impl!(Number for f64, -1.7976931348623157e+308f64, + 1.7976931348623157e+308f64); + +#[cfg(target_pointer_width = "8")] +int_number_trait_impl!(Number for usize, 0usize, 255usize); +#[cfg(target_pointer_width = "16")] +int_number_trait_impl!(Number for usize, 0usize, 65535usize); +#[cfg(target_pointer_width = "32")] +int_number_trait_impl!(Number for usize, 0usize, 4294967295usize); +#[cfg(target_pointer_width = "64")] +int_number_trait_impl!(Number for usize, 0usize, 18446744073709551615usize); + +#[cfg(target_pointer_width = "8")] +int_number_trait_impl!(Number for isize, -128isize, 127isize); +#[cfg(target_pointer_width = "16")] +int_number_trait_impl!(Number for isize, -32768isize, 32767isize); +#[cfg(target_pointer_width = "32")] +int_number_trait_impl!(Number for isize, -2147483648isize, 2147483647isize); +#[cfg(target_pointer_width = "64")] +int_number_trait_impl!(Number for isize, -9223372036854775808isize, + 9223372036854775807isize); // Implement the ToNumber and FromNumber traits for // the types that are Numbers. The FromNumber trait needs diff --git a/src/real.rs b/src/real.rs index fc78117..c609ba2 100644 --- a/src/real.rs +++ b/src/real.rs @@ -1,8 +1,12 @@ +use ::binding::{CDouble, CFloat, CInt}; + use std::num::FpCategory; use std::ops::Neg; use ::constants::Constants; use ::number::Number; +use ::one::One; +use ::zero::Zero; @@ -22,56 +26,22 @@ use ::number::Number; /// [4]: https://doc.rust-lang.org/std/index.html pub trait Real : Number + Constants + Neg { - /// Returns the `NaN` value. - /// - /// ``` - /// use sigils::Real; - /// - /// let nan32: f32 = Real::nan(); - /// let nan64: f64 = Real::nan(); - /// - /// # assert!(nan32.is_nan()); - /// # assert!(nan64.is_nan()); - /// ``` - fn nan() -> Self; + /// Smallest positive normal f64 value. + const MIN_POSITIVE: Self; + + /// Difference between 1.0 and the next largest representable number. + const EPSILON: Self; + + /// Infinity (∞). + const INFINITY: Self; + + /// Negative infinity (-∞). + const NEG_INFINITY: Self; + + /// Not a Number (NaN). + const NAN: Self; - /// Returns the infinite value. - /// - /// ``` - /// use std::{f32, f64}; - /// use sigils::Real; - /// - /// let infinity32: f32 = Real::infinity(); - /// let infinity64: f64 = Real::infinity(); - /// - /// # assert!(infinity32.is_infinite()); - /// # assert!(!infinity32.is_finite()); - /// # assert!(infinity32 > f32::MAX); - /// - /// # assert!(infinity64.is_infinite()); - /// # assert!(!infinity64.is_finite()); - /// # assert!(infinity64 > f64::MAX); - /// ``` - fn infinity() -> Self; - /// Returns the negative infinite value. - /// - /// ``` - /// use std::{f32, f64}; - /// use sigils::Real; - /// - /// let neg_infinity32: f32 = Real::neg_infinity(); - /// let neg_infinity64: f64 = Real::neg_infinity(); - /// - /// # assert!(neg_infinity32.is_infinite()); - /// # assert!(!neg_infinity32.is_finite()); - /// # assert!(neg_infinity32 < f32::MIN); - /// - /// # assert!(neg_infinity64.is_infinite()); - /// # assert!(!neg_infinity64.is_finite()); - /// # assert!(neg_infinity64 < f64::MIN); - /// ``` - fn neg_infinity() -> Self; /// Returns `true` if this value is `NaN` and false otherwise. /// @@ -91,35 +61,6 @@ pub trait Real : Number + Constants + Neg /// ``` fn is_nan(self) -> bool; - /// Returns `true` if this value is positive - /// infinity or negative infinity and false otherwise. - /// - /// ``` - /// use std::{f32, f64}; - /// use sigils::Real; - /// - /// let val32 = 7.0f32; - /// let inf32: f32 = Real::infinity(); - /// let neg_inf32: f32 = Real::neg_infinity(); - /// let nan32: f32 = f32::NAN; - /// - /// let val64 = 7.0f64; - /// let inf64: f64 = Real::infinity(); - /// let neg_inf64: f64 = Real::neg_infinity(); - /// let nan64: f64 = f64::NAN; - /// - /// assert!(!val32.is_infinite()); - /// assert!(!nan32.is_infinite()); - /// assert!(inf32.is_infinite()); - /// assert!(neg_inf32.is_infinite()); - /// - /// assert!(!val64.is_infinite()); - /// assert!(!nan64.is_infinite()); - /// assert!(inf64.is_infinite()); - /// assert!(neg_inf64.is_infinite()); - /// ``` - fn is_infinite(self) -> bool; - /// Returns `true` if this number is neither infinite nor `NaN`. /// /// ``` @@ -127,14 +68,14 @@ pub trait Real : Number + Constants + Neg /// use sigils::Real; /// /// let val32 = 7.0f32; - /// let inf32: f32 = Real::infinity(); - /// let neg_inf32: f32 = Real::neg_infinity(); - /// let nan32: f32 = f32::NAN; + /// let inf32: f32 = Real::INFINITY; + /// let neg_inf32: f32 = Real::NEG_INFINITY; + /// let nan32: f32 = Real::NAN; /// /// let val64 = 7.0f64; - /// let inf64: f64 = Real::infinity(); - /// let neg_inf64: f64 = Real::neg_infinity(); - /// let nan64: f64 = f64::NAN; + /// let inf64: f64 = Real::INFINITY; + /// let neg_inf64: f64 = Real::NEG_INFINITY; + /// let nan64: f64 = Real::NAN; /// /// assert!(val32.is_finite()); /// assert!(!nan32.is_finite()); @@ -148,6 +89,35 @@ pub trait Real : Number + Constants + Neg /// ``` fn is_finite(self) -> bool; + /// Returns `true` if this value is positive + /// infinity or negative infinity and false otherwise. + /// + /// ``` + /// use std::{f32, f64}; + /// use sigils::Real; + /// + /// let val32 = 7.0f32; + /// let inf32: f32 = Real::INFINITY; + /// let neg_inf32: f32 = Real::NEG_INFINITY; + /// let nan32: f32 = Real::NAN; + /// + /// let val64 = 7.0f64; + /// let inf64: f64 = Real::INFINITY; + /// let neg_inf64: f64 = Real::NEG_INFINITY; + /// let nan64: f64 = Real::NAN; + /// + /// assert!(!val32.is_infinite()); + /// assert!(!nan32.is_infinite()); + /// assert!(inf32.is_infinite()); + /// assert!(neg_inf32.is_infinite()); + /// + /// assert!(!val64.is_infinite()); + /// assert!(!nan64.is_infinite()); + /// assert!(inf64.is_infinite()); + /// assert!(neg_inf64.is_infinite()); + /// ``` + fn is_infinite(self) -> bool; + /// Returns `true` if the number is neither zero, infinite, /// subnormal, or `NaN`. /// @@ -182,6 +152,82 @@ pub trait Real : Number + Constants + Neg /// ``` fn is_normal(self) -> bool; + /// Returns `true` if `self` is negative, including `-0.0` and + /// `Real::neg_infinity()`. + /// + /// ``` + /// use std::{f32, f64}; + /// use sigils::Real; + /// + /// let nan32: f32 = f32::NAN; + /// let f_val32 = 7.0f32; + /// let g_val32 = -7.0f32; + /// + /// let nan64: f64 = f64::NAN; + /// let f_val64 = 7.0f64; + /// let g_val64 = -7.0f64; + /// + /// // Requires both tests to determine if is `NaN` + /// assert!(!f_val32.is_sign_negative()); + /// assert!(g_val32.is_sign_negative()); + /// assert!(!nan32.is_sign_positive() && !nan32.is_sign_negative()); + /// + /// assert!(!f_val64.is_sign_negative()); + /// assert!(g_val64.is_sign_negative()); + /// assert!(!nan64.is_sign_positive() && !nan64.is_sign_negative()); + /// ``` + fn is_sign_negative(self) -> bool; + + /// Returns `true` if `self` is positive, including `+0.0` and + /// `Real::infinity()`. + /// + /// ``` + /// use std::{f32, f64}; + /// use sigils::Real; + /// + /// let nan32: f32 = f32::NAN; + /// let f_val32 = 7.0f32; + /// let g_val32 = -7.0f32; + /// + /// let nan64: f64 = f64::NAN; + /// let f_val64 = 7.0f64; + /// let g_val64 = -7.0f64; + /// + /// // Requires both tests to determine if is `NaN` + /// assert!(f_val32.is_sign_positive()); + /// assert!(!g_val32.is_sign_positive()); + /// assert!(!nan32.is_sign_positive() && !nan32.is_sign_negative()); + /// + /// assert!(f_val64.is_sign_positive()); + /// assert!(!g_val64.is_sign_positive()); + /// assert!(!nan64.is_sign_positive() && !nan64.is_sign_negative()); + /// ``` + fn is_sign_positive(self) -> bool; + + /// Returns a number that represents the sign of `self`. + /// + /// - `1.0` if the number is positive, `+0.0` or `Real::infinity()` + /// - `-1.0` if the number is negative, `-0.0` or `Real::neg_infinity()` + /// - `Real::nan()` if the number is `Real::nan()` + /// + /// ``` + /// use std::{f32, f64}; + /// use sigils::Real; + /// + /// let val32 = 3.5f32; + /// + /// let val64 = 3.5f64; + /// + /// assert_eq!(val32.signum(), 1.0f32); + /// assert_eq!(f32::NEG_INFINITY.signum(), -1.0f32); + /// assert!(f32::NAN.signum().is_nan()); + /// + /// assert_eq!(val64.signum(), 1.0f64); + /// assert_eq!(f64::NEG_INFINITY.signum(), -1.0f64); + /// assert!(f64::NAN.signum().is_nan()); + /// ``` + fn signum(self) -> Self; + /// 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. @@ -225,28 +271,50 @@ pub trait Real : Number + Constants + Neg /// let abs_difference = /// (sign_f * mantissa_f * exponent_f - num).abs(); /// - /// assert!(abs_difference < 1e-10); + /// assert!(abs_difference < Real::EPSILON); /// ``` fn integer_decode(self) -> (u64, i16, i8); - /// Returns the largest integer less than or equal to a number. + /// Fused multiply-add. Computes `(self * a) + b` with + /// only one rounding error. This produces a more accurate + /// result with better performance than a separate + /// multiplication operation followed by an add. /// /// ``` /// use sigils::Real; /// - /// let f_val32 = 3.99f32; - /// let g_val32 = 3.0f32; + /// let m32 = 10.0f32; + /// let x32 = 4.0f32; + /// let b32 = 60.0f32; + /// let abs_difference32 = + /// (m32.mul_add(x32, b32) - (m32*x32 + b32)).abs(); /// - /// let f_val64 = 3.99f64; - /// let g_val64 = 3.0f64; + /// let m64 = 10.0f64; + /// let x64 = 4.0f64; + /// let b64 = 60.0f64; + /// let abs_difference64 = + /// (m64.mul_add(x64, b64) - (m64*x64 + b64)).abs(); /// - /// assert_eq!(f_val32.floor(), 3.0f32); - /// assert_eq!(g_val32.floor(), 3.0f32); - /// - /// assert_eq!(f_val64.floor(), 3.0f64); - /// assert_eq!(g_val64.floor(), 3.0f64); + /// assert!(abs_difference32 < Real::EPSILON); + /// assert!(abs_difference64 < Real::EPSILON); /// ``` - fn floor(self) -> Self; + fn mul_add(self, a: Self, b: Self) -> Self; + + /// Raise a number to a floating point power. + /// + /// ``` + /// use sigils::Real; + /// + /// let x32 = 2.0f32; + /// let abs_difference32 = (x32.powf(2.0f32) - x32*x32).abs(); + /// + /// let x64 = 2.0f64; + /// let abs_difference64 = (x64.powf(2.0f64) - x64*x64).abs(); + /// + /// assert!(abs_difference32 < Real::EPSILON); + /// assert!(abs_difference64 < Real::EPSILON); + /// ``` + fn pow(self, n: Self) -> Self; /// Returns the smallest integer greater than or equal to a number. /// @@ -267,6 +335,25 @@ pub trait Real : Number + Constants + Neg /// ``` fn ceil(self) -> Self; + /// Returns the largest integer less than or equal to a number. + /// + /// ``` + /// use sigils::Real; + /// + /// let f_val32 = 3.99f32; + /// let g_val32 = 3.0f32; + /// + /// let f_val64 = 3.99f64; + /// let g_val64 = 3.0f64; + /// + /// assert_eq!(f_val32.floor(), 3.0f32); + /// assert_eq!(g_val32.floor(), 3.0f32); + /// + /// assert_eq!(f_val64.floor(), 3.0f64); + /// assert_eq!(g_val64.floor(), 3.0f64); + /// ``` + fn floor(self) -> Self; + /// Returns the nearest integer to a number. Round /// half-way cases away from `0.0`. /// @@ -321,11 +408,11 @@ pub trait Real : Number + Constants + Neg /// let abs_difference_x64 = (x64.fract() - 0.5f64).abs(); /// let abs_difference_y64 = (y64.fract() - (-0.5f64)).abs(); /// - /// assert!(abs_difference_x32 < 1e-10); - /// assert!(abs_difference_y32 < 1e-10); + /// assert!(abs_difference_x32 < Real::EPSILON); + /// assert!(abs_difference_y32 < Real::EPSILON); /// - /// assert!(abs_difference_x64 < 1e-10); - /// assert!(abs_difference_y64 < 1e-10); + /// assert!(abs_difference_x64 < Real::EPSILON); + /// assert!(abs_difference_y64 < Real::EPSILON); /// ``` fn fract(self) -> Self; @@ -346,117 +433,16 @@ pub trait Real : Number + Constants + Neg /// let abs_difference_x64 = (x64.abs() - x64).abs(); /// let abs_difference_y64 = (y64.abs() - (-y64)).abs(); /// - /// assert!(abs_difference_x32 < 1e-10); - /// assert!(abs_difference_y32 < 1e-10); + /// assert!(abs_difference_x32 < Real::EPSILON); + /// assert!(abs_difference_y32 < Real::EPSILON); /// assert!(f32::NAN.abs().is_nan()); /// - /// assert!(abs_difference_x64 < 1e-10); - /// assert!(abs_difference_y64 < 1e-10); + /// assert!(abs_difference_x64 < Real::EPSILON); + /// assert!(abs_difference_y64 < Real::EPSILON); /// assert!(f64::NAN.abs().is_nan()); /// ``` fn abs(self) -> Self; - /// Returns a number that represents the sign of `self`. - /// - /// - `1.0` if the number is positive, `+0.0` or `Real::infinity()` - /// - `-1.0` if the number is negative, `-0.0` or `Real::neg_infinity()` - /// - `Real::nan()` if the number is `Real::nan()` - /// - /// ``` - /// use std::{f32, f64}; - /// use sigils::Real; - /// - /// let val32 = 3.5f32; - /// - /// let val64 = 3.5f64; - /// - /// assert_eq!(val32.signum(), 1.0f32); - /// assert_eq!(f32::NEG_INFINITY.signum(), -1.0f32); - /// assert!(f32::NAN.signum().is_nan()); - /// - /// assert_eq!(val64.signum(), 1.0f64); - /// assert_eq!(f64::NEG_INFINITY.signum(), -1.0f64); - /// assert!(f64::NAN.signum().is_nan()); - /// ``` - fn signum(self) -> Self; - - /// Returns `true` if `self` is positive, including `+0.0` and - /// `Real::infinity()`. - /// - /// ``` - /// use std::{f32, f64}; - /// use sigils::Real; - /// - /// let nan32: f32 = f32::NAN; - /// let f_val32 = 7.0f32; - /// let g_val32 = -7.0f32; - /// - /// let nan64: f64 = f64::NAN; - /// let f_val64 = 7.0f64; - /// let g_val64 = -7.0f64; - /// - /// // Requires both tests to determine if is `NaN` - /// assert!(f_val32.is_sign_positive()); - /// assert!(!g_val32.is_sign_positive()); - /// assert!(!nan32.is_sign_positive() && !nan32.is_sign_negative()); - /// - /// assert!(f_val64.is_sign_positive()); - /// assert!(!g_val64.is_sign_positive()); - /// assert!(!nan64.is_sign_positive() && !nan64.is_sign_negative()); - /// ``` - fn is_sign_positive(self) -> bool; - - /// Returns `true` if `self` is negative, including `-0.0` and - /// `Real::neg_infinity()`. - /// - /// ``` - /// use std::{f32, f64}; - /// use sigils::Real; - /// - /// let nan32: f32 = f32::NAN; - /// let f_val32 = 7.0f32; - /// let g_val32 = -7.0f32; - /// - /// let nan64: f64 = f64::NAN; - /// let f_val64 = 7.0f64; - /// let g_val64 = -7.0f64; - /// - /// // Requires both tests to determine if is `NaN` - /// assert!(!f_val32.is_sign_negative()); - /// assert!(g_val32.is_sign_negative()); - /// assert!(!nan32.is_sign_positive() && !nan32.is_sign_negative()); - /// - /// assert!(!f_val64.is_sign_negative()); - /// assert!(g_val64.is_sign_negative()); - /// assert!(!nan64.is_sign_positive() && !nan64.is_sign_negative()); - /// ``` - fn is_sign_negative(self) -> bool; - - /// Fused multiply-add. Computes `(self * a) + b` with - /// only one rounding error. This produces a more accurate - /// result with better performance than a separate - /// multiplication operation followed by an add. - /// - /// ``` - /// use sigils::Real; - /// - /// let m32 = 10.0f32; - /// let x32 = 4.0f32; - /// let b32 = 60.0f32; - /// let abs_difference32 = - /// (m32.mul_add(x32, b32) - (m32*x32 + b32)).abs(); - /// - /// let m64 = 10.0f64; - /// let x64 = 4.0f64; - /// let b64 = 60.0f64; - /// let abs_difference64 = - /// (m64.mul_add(x64, b64) - (m64*x64 + b64)).abs(); - /// - /// assert!(abs_difference32 < 1e-10); - /// assert!(abs_difference64 < 1e-10); - /// ``` - fn mul_add(self, a: Self, b: Self) -> Self; - /// Take the reciprocal (inverse) of a number, `1/x`. /// /// ``` @@ -470,45 +456,11 @@ pub trait Real : Number + Constants + Neg /// let abs_difference64 = /// (x64.recip() - (1.0f64/x64)).abs(); /// - /// assert!(abs_difference32 < 1e-10); - /// assert!(abs_difference64 < 1e-10); + /// assert!(abs_difference32 < Real::EPSILON); + /// assert!(abs_difference64 < Real::EPSILON); /// ``` fn recip(self) -> Self; - /// Raise a number to an integer power. - /// - /// Using this function is generally faster than using `powf` - /// - /// ``` - /// use sigils::Real; - /// - /// let x32 = 2.0f32; - /// let abs_difference32 = (x32.powi(2i32) - x32*x32).abs(); - /// - /// let x64 = 2.0f64; - /// let abs_difference64 = (x64.powi(2i32) - x64*x64).abs(); - /// - /// assert!(abs_difference32 < 1e-10); - /// assert!(abs_difference64 < 1e-10); - /// ``` - fn powi(self, n: i32) -> Self; - - /// Raise a number to a floating point power. - /// - /// ``` - /// use sigils::Real; - /// - /// let x32 = 2.0f32; - /// let abs_difference32 = (x32.powf(2.0f32) - x32*x32).abs(); - /// - /// let x64 = 2.0f64; - /// let abs_difference64 = (x64.powf(2.0f64) - x64*x64).abs(); - /// - /// assert!(abs_difference32 < 1e-10); - /// assert!(abs_difference64 < 1e-10); - /// ``` - fn powf(self, n: Self) -> Self; - /// Take the square root of a number. /// /// Returns NaN if `self` is a negative number. @@ -516,29 +468,45 @@ pub trait Real : Number + Constants + Neg /// ``` /// use sigils::Real; /// - /// let positive = 4.0; - /// let negative = -4.0; + /// let positive = 4.0f32; + /// let negative = -4.0f32; /// /// let abs_difference = (positive.sqrt() - 2.0).abs(); /// - /// assert!(abs_difference < 1e-10); + /// assert!(abs_difference < Real::EPSILON); /// assert!(negative.sqrt().is_nan()); /// ``` fn sqrt(self) -> Self; + /// Take the cubic root of a number. + /// + /// ``` + /// use sigils::Real; + /// + /// let x: f64; + /// let abs_difference: f64; + /// + /// // x^(1/3) - 2 == 0 + /// x = 8.0; + /// abs_difference = (x.cbrt() - 2.0).abs(); + /// + /// assert!(abs_difference < Real::EPSILON); + /// ``` + fn cbrt(self) -> Self; + /// Returns `e^(self)`, (the exponential function). /// /// ``` /// use sigils::Real; /// - /// let one = 1.0; + /// let one = 1.0f64; /// // e^1 /// let e = one.exp(); /// /// // ln(e) - 1 == 0 /// let abs_difference = (e.ln() - 1.0).abs(); /// - /// assert!(abs_difference < 1e-10); + /// assert!(abs_difference < Real::EPSILON); /// ``` fn exp(self) -> Self; @@ -547,28 +515,45 @@ pub trait Real : Number + Constants + Neg /// ``` /// use sigils::Real; /// - /// let f = 2.0; + /// let f = 2.0f64; /// /// // 2^2 - 4 == 0 /// let abs_difference = (f.exp2() - 4.0).abs(); /// - /// assert!(abs_difference < 1e-10); + /// assert!(abs_difference < Real::EPSILON); /// ``` fn exp2(self) -> Self; + /// Returns `e^(self) - 1` in a way that is accurate even if the + /// number is close to zero. + /// + /// ``` + /// use sigils::Real; + /// + /// let x: f64; + /// let abs_difference: f64; + /// + /// // e^(ln(7)) - 1 + /// x = 7.0; + /// abs_difference = (x.ln().exp_m1() - 6.0).abs(); + /// + /// assert!(abs_difference < Real::EPSILON); + /// ``` + fn exp_m1(self) -> Self; + /// Returns the natural logarithm of the number. /// /// ``` /// use sigils::Real; /// - /// let one = 1.0; + /// let one = 1.0f64; /// // e^1 /// let e = one.exp(); /// /// // ln(e) - 1 == 0 /// let abs_difference = (e.ln() - 1.0).abs(); /// - /// assert!(abs_difference < 1e-10); + /// assert!(abs_difference < Real::EPSILON); /// ``` fn ln(self) -> Self; @@ -577,8 +562,8 @@ pub trait Real : Number + Constants + Neg /// ``` /// use sigils::Real; /// - /// let ten = 10.0; - /// let two = 2.0; + /// let ten = 10.0f32; + /// let two = 2.0f32; /// /// // log10(10) - 1 == 0 /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs(); @@ -586,8 +571,8 @@ pub trait Real : Number + Constants + Neg /// // log2(2) - 1 == 0 /// let abs_difference_2 = (two.log(2.0) - 1.0).abs(); /// - /// assert!(abs_difference_10 < 1e-10); - /// assert!(abs_difference_2 < 1e-10); + /// assert!(abs_difference_10 < Real::EPSILON); + /// assert!(abs_difference_2 < Real::EPSILON); /// ``` fn log(self, base: Self) -> Self; @@ -596,12 +581,12 @@ pub trait Real : Number + Constants + Neg /// ``` /// use sigils::Real; /// - /// let two = 2.0; + /// let two = 2.0f32; /// /// // log2(2) - 1 == 0 /// let abs_difference = (two.log2() - 1.0).abs(); /// - /// assert!(abs_difference < 1e-10); + /// assert!(abs_difference < Real::EPSILON); /// ``` fn log2(self) -> Self; @@ -610,87 +595,15 @@ pub trait Real : Number + Constants + Neg /// ``` /// use sigils::Real; /// - /// let ten = 10.0; + /// let ten = 10.0f64; /// /// // log10(10) - 1 == 0 /// let abs_difference = (ten.log10() - 1.0).abs(); /// - /// assert!(abs_difference < 1e-10); + /// assert!(abs_difference < Real::EPSILON); /// ``` fn log10(self) -> Self; - /// Returns the maximum of the two numbers. - /// - /// ``` - /// use sigils::Real; - /// - /// let x = 1.0; - /// let y = 2.0; - /// - /// assert_eq!(x.max(y), y); - /// ``` - fn max(self, other: Self) -> Self; - - /// Returns the minimum of the two numbers. - /// - /// ``` - /// use sigils::Real; - /// - /// let x = 1.0; - /// let y = 2.0; - /// - /// assert_eq!(x.min(y), x); - /// ``` - fn min(self, other: Self) -> Self; - - /// The positive difference of two numbers. - /// - /// * If `self <= other`: `0:0` - /// * Else: `self - other` - /// - /// ``` - /// use sigils::Real; - /// - /// let x = 3.0; - /// let y = -3.0; - /// - /// let abs_difference_x = (x.abs_sub(1.0) - 2.0).abs(); - /// let abs_difference_y = (y.abs_sub(1.0) - 0.0).abs(); - /// - /// assert!(abs_difference_x < 1e-10); - /// assert!(abs_difference_y < 1e-10); - /// ``` - fn abs_sub(self, other: Self) -> Self; - - /// Take the cubic root of a number. - /// - /// ``` - /// use sigils::Real; - /// - /// let x = 8.0; - /// - /// // x^(1/3) - 2 == 0 - /// let abs_difference = (x.cbrt() - 2.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - fn cbrt(self) -> Self; - - /// Returns `e^(self) - 1` in a way that is accurate even if the - /// number is close to zero. - /// - /// ``` - /// use sigils::Real; - /// - /// let x = 7.0; - /// - /// // e^(ln(7)) - 1 - /// let abs_difference = (x.ln().exp_m1() - 6.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - fn exp_m1(self) -> Self; - /// Returns `ln(1+n)` (natural logarithm) more accurately than if /// the operations were performed separately. /// @@ -707,134 +620,528 @@ pub trait Real : Number + Constants + Neg /// x64 -= 1.0f64; /// let abs_difference64 = (x64.ln_1p() - 1.0f64).abs(); /// - /// //assert!(abs_difference32 < 1e-10); - /// assert!(abs_difference64 < 1e-10); + /// //assert!(abs_difference32 < Real::EPSILON); + /// assert!(abs_difference64 < Real::EPSILON); /// ``` fn ln_1p(self) -> Self; } -// Create some macros to ease typing and reading. -/// -macro_rules! define_self_func + +impl Real for f32 { - ($varType: ident, $funcName: ident) => + /// + const MIN_POSITIVE: Self = 1.17549435e-38f32; + + /// + const EPSILON: Self = 1.19209290e-07f32; + + /// + const INFINITY: Self = 1.0f32 / 0.0f32; + + /// + const NEG_INFINITY: Self = -1.0f32 / 0.0f32; + + /// + const NAN: Self = 0.0f32 / 0.0f32; + + + + fn is_nan(self) -> bool { - fn $funcName(self) -> $varType + self == Self::NAN + } + + fn is_finite(self) -> bool + { + !self.is_infinite() && self != Self::NAN + } + + fn is_infinite(self) -> bool + { + self == Self::INFINITY || self == Self::NEG_INFINITY + } + + fn is_normal(self) -> bool + { + self.is_finite() && self != Self::zero() && + self <= -Self::MIN_POSITIVE && self >= Self::MIN_POSITIVE + } + + fn is_sign_negative(self) -> bool + { + self.is_finite() && self < Self::zero() + } + + fn is_sign_positive(self) -> bool + { + self.is_finite() && self > Self::zero() + } + + fn signum(self) -> Self + { + if self.is_nan() == true { - <$varType>::$funcName(self) + Self::NAN + } + else if self >= Self::zero() || self == Self::INFINITY + { + Self::one() + } + else if self <= -Self::zero() || self == Self::NEG_INFINITY + { + -Self::one() + } + else + { + Self::zero() + } + } + + fn classify(self) -> FpCategory + { + ::classify(self) + } + + fn integer_decode(self) -> (u64, i16, i8) + { + let bits: u32; + let sign: i8; + let mantissa: u32; + let mut exponent: i16; + + bits = unsafe { ::std::mem::transmute(self) }; + if bits >> 31 == 0 + { + sign = 1; + } + else + { + sign = -1; + }; + + exponent = ((bits >> 23) & 0xff) as i16; + if exponent == 0 + { + mantissa = (bits & 0x7fffff) << 1; + } + else + { + mantissa = (bits & 0x7fffff) | 0x800000; + } + + // Exponent bias + mantissa shift + exponent -= 127 + 23; + + (mantissa as u64, exponent, sign) + } + + fn mul_add(self, a: Self, b: Self) -> Self + { + unsafe + { + ::pact::fmaf(self as CFloat, a as CFloat, b as CFloat) as Self + } + } + + fn pow(self, n: Self) -> Self + { + unsafe + { + ::pact::powf(self as CFloat, n as CFloat) as Self + } + } + + fn ceil(self) -> Self + { + unsafe + { + ::pact::ceilf(self as CFloat) as Self + } + } + + fn floor(self) -> Self + { + unsafe + { + ::pact::floorf(self as CFloat) as Self + } + } + + fn round(self) -> Self + { + unsafe + { + ::pact::roundf(self as CFloat) as Self + } + } + + fn trunc(self) -> Self + { + unsafe + { + ::pact::truncf(self as CFloat) as Self + } + } + + fn fract(self) -> Self + { + let mut integer: CInt; + + integer = 0; + + unsafe + { + ::pact::modff(self as CFloat, &mut integer) as Self + } + } + + fn abs(self) -> Self + { + unsafe + { + ::pact::fabsf(self as CFloat) as Self + } + } + + fn recip(self) -> Self + { + 1.0f32 / self + } + + fn sqrt(self) -> Self + { + unsafe + { + ::pact::sqrtf(self as CFloat) as Self + } + } + + fn cbrt(self) -> Self + { + unsafe + { + ::pact::cbrtf(self as CFloat) as Self + } + } + + fn exp(self) -> Self + { + unsafe + { + ::pact::expf(self as CFloat) as Self + } + } + + fn exp2(self) -> Self + { + unsafe + { + ::pact::exp2f(self as CFloat) as Self + } + } + + fn exp_m1(self) -> Self + { + unsafe + { + ::pact::expm1f(self as CFloat) as Self + } + } + + fn ln(self) -> Self + { + unsafe + { + ::pact::logf(self as CFloat) as Self + } + } + + fn log(self, base: Self) -> Self + { + self.ln() / base.ln() + } + + fn log2(self) -> Self + { + unsafe + { + ::pact::log2f(self as CFloat) as Self + } + } + + fn log10(self) -> Self + { + unsafe + { + ::pact::log10f(self as CFloat) as Self + } + } + + fn ln_1p(self) -> Self + { + unsafe + { + ::pact::log1pf(self as CFloat) as Self } } } -/// -macro_rules! define_self_bool_func +impl Real for f64 { - ($varType: ident, $funcName: ident) => + /// + const MIN_POSITIVE: Self = 2.2250738585072014e-308f64; + + /// + const EPSILON: Self = 2.2204460492503131e-16f64; + + /// + const INFINITY: Self = 1.0f64 / 0.0f64; + + /// + const NEG_INFINITY: Self = -1.0f64 / 0.0f64; + + /// + const NAN: Self = 0.0f64 / 0.0f64; + + + + fn is_nan(self) -> bool { - fn $funcName(self) -> bool + self == Self::NAN + } + + fn is_finite(self) -> bool + { + !self.is_infinite() && self != Self::NAN + } + + fn is_infinite(self) -> bool + { + self == Self::INFINITY || self == Self::NEG_INFINITY + } + + fn is_normal(self) -> bool + { + self.is_finite() && self != Self::zero() && + self <= -Self::MIN_POSITIVE && self >= Self::MIN_POSITIVE + } + + fn is_sign_negative(self) -> bool + { + self.is_finite() && self < Self::zero() + } + + fn is_sign_positive(self) -> bool + { + self.is_finite() && self > Self::zero() + } + + fn signum(self) -> Self + { + if self.is_nan() == true { - <$varType>::$funcName(self) + Self::NAN + } + else if self >= Self::zero() || self == Self::INFINITY + { + Self::one() + } + else if self <= -Self::zero() || self == Self::NEG_INFINITY + { + -Self::one() + } + else + { + Self::zero() + } + } + + fn classify(self) -> FpCategory + { + ::classify(self) + } + + fn integer_decode(self) -> (u64, i16, i8) + { + let bits: u64; + let sign: i8; + let mantissa: u64; + let mut exponent: i16; + + bits = unsafe { ::std::mem::transmute(self) }; + if bits >> 63 == 0 + { + sign = 1; + } + else + { + sign = -1; + } + + exponent = ((bits >> 52) & 0x7ff) as i16; + if exponent == 0 + { + mantissa = (bits & 0xfffffffffffff) << 1; + } + else + { + mantissa = (bits & 0xfffffffffffff) | 0x10000000000000; + } + + // Exponent bias + mantissa shift + exponent -= 1023 + 52; + + (mantissa, exponent, sign) + } + + fn mul_add(self, a: Self, b: Self) -> Self + { + unsafe + { + ::pact::fma(self as CDouble, a as CDouble, b as CDouble) as Self + } + } + + fn pow(self, n: Self) -> Self + { + unsafe + { + ::pact::pow(self as CDouble, n as CDouble) as Self + } + } + + fn ceil(self) -> Self + { + unsafe + { + ::pact::ceil(self as CDouble) as Self + } + } + + fn floor(self) -> Self + { + unsafe + { + ::pact::floor(self as CDouble) as Self + } + } + + fn round(self) -> Self + { + unsafe + { + ::pact::round(self as CDouble) as Self + } + } + + fn trunc(self) -> Self + { + unsafe + { + ::pact::trunc(self as CDouble) as Self + } + } + + fn fract(self) -> Self + { + let mut integer: CInt; + + integer = 0; + + unsafe + { + ::pact::modf(self as CDouble, &mut integer) as Self + } + } + + fn abs(self) -> Self + { + unsafe + { + ::pact::fabs(self as CDouble) as Self + } + } + + fn recip(self) -> Self + { + 1.0f64 / self + } + + fn sqrt(self) -> Self + { + unsafe + { + ::pact::sqrt(self as CDouble) as Self + } + } + + fn cbrt(self) -> Self + { + unsafe + { + ::pact::cbrt(self as CDouble) as Self + } + } + + fn exp(self) -> Self + { + unsafe + { + ::pact::exp(self as CDouble) as Self + } + } + + fn exp2(self) -> Self + { + unsafe + { + ::pact::exp2(self as CDouble) as Self + } + } + + fn exp_m1(self) -> Self + { + unsafe + { + ::pact::expm1(self as CDouble) as Self + } + } + + fn ln(self) -> Self + { + unsafe + { + ::pact::log(self as CDouble) as Self + } + } + + fn log(self, base: Self) -> Self + { + self.ln() / base.ln() + } + + fn log2(self) -> Self + { + unsafe + { + ::pact::log2(self as CDouble) as Self + } + } + + fn log10(self) -> Self + { + unsafe + { + ::pact::log10(self as CDouble) as Self + } + } + + fn ln_1p(self) -> Self + { + unsafe + { + ::pact::log1p(self as CDouble) as Self } } } - -/// -macro_rules! define_self_other_func -{ - ($varType: ident, $funcName: ident) => - { - fn $funcName(self, other: $varType) -> $varType - { - <$varType>::$funcName(self, other) - } - } -} - -/// A macro to make implementing the trait easier for all the -/// base float types in rust. -macro_rules! real_trait_impl -{ - ($traitName: ident for $($varType: ident)*) => - ($( - impl Real for $varType - { - fn nan() -> $varType - { - ::std::$varType::NAN - } - - fn infinity() -> $varType - { - ::std::$varType::INFINITY - } - - fn neg_infinity() -> $varType - { - ::std::$varType::NEG_INFINITY - } - - fn classify(self) -> FpCategory - { - <$varType>::classify(self) - } - - fn integer_decode(self) -> (u64, i16, i8) - { - <$varType>::integer_decode(self) - } - - fn mul_add(self, a: $varType, b: $varType) -> $varType - { - <$varType>::mul_add(self, a, b) - } - - fn powi(self, n: i32) -> $varType - { - <$varType>::powi(self, n) - } - - fn powf(self, n: $varType) -> $varType - { - <$varType>::powf(self, n) - } - - define_self_bool_func!($varType, is_nan); - define_self_bool_func!($varType, is_infinite); - define_self_bool_func!($varType, is_finite); - define_self_bool_func!($varType, is_normal); - define_self_bool_func!($varType, is_sign_positive); - define_self_bool_func!($varType, is_sign_negative); - define_self_func!($varType, signum); - - define_self_func!($varType, floor); - define_self_func!($varType, ceil); - define_self_func!($varType, round); - define_self_func!($varType, trunc); - - define_self_func!($varType, fract); - define_self_func!($varType, abs); - define_self_other_func!($varType, abs_sub); - define_self_func!($varType, recip); - define_self_func!($varType, sqrt); - define_self_func!($varType, cbrt); - define_self_func!($varType, exp); - define_self_func!($varType, exp2); - define_self_func!($varType, exp_m1); - define_self_func!($varType, ln_1p); - - define_self_other_func!($varType, min); - define_self_other_func!($varType, max); - - define_self_func!($varType, ln); - define_self_other_func!($varType, log); - define_self_func!($varType, log2); - define_self_func!($varType, log10); - } - )*) -} - - -// Implement the trait for the types that are Real numbers. -real_trait_impl!(Real for f32); -real_trait_impl!(Real for f64); diff --git a/src/trig/trig.rs b/src/trig/trig.rs index af4a7c6..c787190 100644 --- a/src/trig/trig.rs +++ b/src/trig/trig.rs @@ -11,12 +11,13 @@ pub trait Trig: Real /// Computes the cosine of this angle. /// /// ``` - /// use sigils::Radian; - /// use std::f64; + /// use sigils::{Constants, Radian, Trig}; /// - /// let x: Radian = Radian::from(2.0*f64::consts::PI); + /// let abs_difference: f64; + /// let radians: Radian; /// - /// let abs_difference = (x.cos() - 1.0).abs(); + /// radians = Radian::new(2.0f64 * f64::PI); + /// abs_difference = (Trig::cos(radians) - 1.0f64).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` @@ -26,12 +27,13 @@ pub trait Trig: Real /// Computes the sine of this angle. /// /// ``` - /// use sigils::Radian; - /// use std::f64; + /// use sigils::{Constants, Radian, Trig}; /// - /// let x: Radian = Radian::from(f64::consts::PI/2.0); + /// let abs_difference: f64; + /// let radians: Radian; /// - /// let abs_difference = (x.sin() - 1.0).abs(); + /// let radians: Radian = Radian::new(f64::PI / 2.0f64); + /// let abs_difference = (Trig::sin(radians) - 1.0f64).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` @@ -41,12 +43,13 @@ pub trait Trig: Real /// Computes the tangent of this angle. /// /// ``` - /// use sigils::Radian; - /// use std::f64; + /// use sigils::{Constants, Radian, Trig}; /// - /// let x: Radian = Radian::from(f64::consts::PI/4.0); + /// let abs_difference: f64; + /// let radians: Radian; /// - /// let abs_difference = (x.tan() - 1.0).abs(); + /// radians = Radian::new(f64::PI / 4.0f64); + /// abs_difference = (Trig::tan(radians) - 1.0f64).abs(); /// /// assert!(abs_difference < 1e-14); /// ``` @@ -58,12 +61,17 @@ pub trait Trig: Real /// [-1, 1]. /// ///``` - /// use sigils::{Constants, Radian, Real}; + /// use sigils::{Constants, Radian, Trig}; /// - /// let f: Radian; + /// let angle: f64; + /// let radians: Radian; + /// let test: Radian; /// - /// f = Radian::from(f64::PI / 4.0f64); - /// assert!(((f64::PI / 4.0f64) - *Radian::acos(f.cos())) < 1e-10); + /// angle = f64::PI / 4.0f64; + /// radians = Radian::new(angle); + /// test = Trig::acos(Trig::cos(radians)); + /// + /// assert!((angle - *test) < 1e-10); ///``` fn acos(arg: Self) -> T where T: From>; @@ -73,12 +81,17 @@ pub trait Trig: Real /// outside the range [-1, 1]. /// ///``` - /// use sigils::{Constants, Radian, Real}; + /// use sigils::{Constants, Radian, Trig}; /// - /// let f: Radian; + /// let angle: f64; + /// let radians: Radian; + /// let test: Radian; /// - /// f = Radian::from(f64::PI / 4.0f64); - /// assert!(((f64::PI / 4.0f64) - *Radian::asin(f.sin())) < 1e-10); + /// angle = f64::PI / 4.0f64; + /// radians = Radian::new(angle); + /// test = Trig::asin(Trig::sin(radians)); + /// + /// assert!((angle - *test) < 1e-10); ///``` fn asin(arg: Self) -> T where T: From>; @@ -87,12 +100,17 @@ pub trait Trig: Real /// range [-pi/2, pi/2]; /// ///``` - /// use sigils::{Constants, Radian, Real}; + /// use sigils::{Constants, Radian, Trig}; /// - /// let f: Radian; + /// let angle: f64; + /// let radians: Radian; + /// let test: Radian; /// - /// f = Radian::from(f64::PI / 4.0f64); - /// assert!(((f64::PI / 4.0f64) - *Radian::atan(f.tan())) < 1e-10); + /// angle = f64::PI / 4.0f64; + /// radians = Radian::new(angle); + /// test = Trig::atan(Trig::tan(radians)); + /// + /// assert!((angle - *test) < 1e-10); ///``` fn atan(arg: Self) -> T where T: From>; @@ -105,76 +123,54 @@ pub trait Trig: Real /// Hyperbolic cosine function. /// /// ``` - /// use sigils::Radian; - /// use sigils::Constants; + /// use sigils::{Constants, Trig}; /// - /// let e32: f32 = Constants::E; - /// let x32: Radian = Radian::new(1.0f32); - /// let f_val32 = x32.cosh(); - /// let g_val32 = (e32*e32 + 1.0f32)/(2.0f32*e32); - /// let abs_difference32 = (f_val32 - g_val32).abs(); + /// let f_val: f32; + /// let g_val: f32; + /// let abs_difference: f32; /// - /// let e64: f64 = Constants::E; - /// let x64: Radian = Radian::new(1.0f64); - /// let f_val64 = x64.cosh(); - /// let g_val64 = (e64*e64 + 1.0f64)/(2.0f64*e64); - /// let abs_difference64 = (f_val64 - g_val64).abs(); + /// f_val = Trig::cosh(1.0f32); + /// g_val = (f32::E * f32::E + 1.0f32) / (2.0f32 * f32::E); + /// abs_difference = (f_val - g_val).abs(); /// /// // Solving cosh() at 1 gives this result - /// //assert!(abs_difference32 < 1.0e-10); - /// assert!(abs_difference64 < 1.0e-10); + /// assert!(abs_difference < 1.0e-10); /// ``` fn cosh(arg: Self) -> Self; /// Hyperbolic sine function. /// /// ``` - /// use sigils::Radian; - /// use sigils::Constants; + /// use sigils::{Constants, Trig}; /// - /// let e32: f32 = Constants::E; - /// let x32: Radian = Radian::from(1.0f32); + /// let f_val: f32; + /// let g_val: f32; + /// let abs_difference: f32; /// - /// let f_val32 = x32.sinh(); - /// let g_val32 = (e32*e32 - 1.0f32)/(2.0f32*e32); - /// let abs_difference32 = (f_val32 - g_val32).abs(); - /// - /// let e64: f64 = Constants::E; - /// let x64: Radian = Radian::from(1.0f64); - /// - /// let f_val64 = x64.sinh(); - /// let g_val64 = (e64*e64 - 1.0f64)/(2.0f64*e64); - /// let abs_difference64 = (f_val64 - g_val64).abs(); + /// f_val = Trig::sinh(1.0f32); + /// g_val = (f32::E * f32::E - 1.0f32) / (2.0f32 * f32::E); + /// abs_difference = (f_val - g_val).abs(); /// /// // Solving sinh() at 1 gives `(e^2-1)/(2e)` - /// //assert!(abs_difference32 < 1e-10); - /// assert!(abs_difference64 < 1e-10); + /// assert!(abs_difference < 1e-10); /// ``` fn sinh(arg: Self) -> Self; /// Hyperbolic tangent function. /// /// ``` - /// use sigils::Radian; - /// use sigils::Constants; + /// use sigils::{Constants, Trig}; /// - /// let e32: f32 = Constants::E; - /// let x32: Radian = Radian::from(1.0f32); - /// - /// let f_val32 = x32.tanh(); - /// let g_val32 = (1.0f32 - e32.powi(-2i32))/(1.0f32 + e32.powi(-2i32)); - /// let abs_difference32 = (f_val32 - g_val32).abs(); - /// - /// let e64: f64 = Constants::E; - /// let x64: Radian = Radian::from(1.0f64); - /// - /// let f_val64 = x64.tanh(); - /// let g_val64 = (1.0f64 - e64.powi(-2i32))/(1.0f64 + e64.powi(-2i32)); - /// let abs_difference64 = (f_val64 - g_val64).abs(); + /// let f_val: f32; + /// let g_val: f32; + /// let abs_difference: f32; + + /// f_val = Trig::tanh(1.0f32); + /// g_val = (1.0f32 - f32::E.powi(-2i32)) / (1.0f32 + f32::E.powi(-2i32)); + /// abs_difference = (f_val - g_val).abs(); /// /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))` - /// //assert!(abs_difference32 < 1.0e-10); - /// assert!(abs_difference64 < 1.0e-10); + /// assert!(abs_difference < 1.0e-6); /// ``` fn tanh(arg: Self) -> Self; diff --git a/src/vector.rs b/src/vector.rs index 13aa453..f9f06ce 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -269,8 +269,8 @@ pub trait Vector: Debug + Display + Clone + Default + Zero + One /// /// let vector: Vector3 = Vector3::::from_value(3i32); /// let vector_two: Vector3 = Vector3::::from_value(3i32); - /// let dotProduct: i64 = vector.dot(&vector_two); - /// # assert_eq!(dotProduct, 27i64); + /// let dotProduct: i32 = vector.dot(&vector_two); + /// # assert_eq!(dotProduct, 27i32); ///``` fn dot(&self, vector: &Self) -> T; }