Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  complex_float.rs

  Sprache: Rust
 

// Keeps us from accidentally creating a recursive impl rather than a real one.
#![deny(unconditional_recursion)]

use core::ops::Neg;

use num_traits::{Float, FloatConst, Num, NumCast};

use crate::Complex;

mod private {
    use num_traits::{Float, FloatConst};

    use crate::Complex;

    pub trait Seal {}

    impl<T> Seal for T where T: Float + FloatConst {}
    impl<T: Float + FloatConst> Seal for Complex<T> {}
}

/// Generic trait for floating point complex numbers.
///
/// This trait defines methods which are common to complex floating point
/// numbers and regular floating point numbers.
///
/// This trait is sealed to prevent it from being implemented by anything other
/// than floating point scalars and [Complex] floats.
pub trait ComplexFloat: Num + NumCast + Copy + Neg<Output = Self> + private::Seal {
    /// The type used to represent the real coefficients of this complex number.
    type Real: Float + FloatConst;

    /// Returns `true` if this value is `NaN` and false otherwise.
    fn is_nan(self) -> bool;

    /// Returns `true` if this value is positive infinity or negative infinity and
    /// false otherwise.
    fn is_infinite(self) -> bool;

    /// Returns `true` if this number is neither infinite nor `NaN`.
    fn is_finite(self) -> bool;

    /// Returns `true` if the number is neither zero, infinite,
    /// [subnormal](http://en.wikipedia.org/wiki/Denormal_number), or `NaN`.
    fn is_normal(self) -> bool;

    /// Take the reciprocal (inverse) of a number, `1/x`. See also [Complex::finv].
    fn recip(self) -> Self;

    /// Raises `self` to a signed integer power.
    fn powi(self, exp: i32) -> Self;

    /// Raises `self` to a real power.
    fn powf(self, exp: Self::Real) -> Self;

    /// Raises `self` to a complex power.
    fn powc(self, exp: Complex<Self::Real>) -> Complex<Self::Real>;

    /// Take the square root of a number.
    fn sqrt(self) -> Self;

    /// Returns `e^(self)`, (the exponential function).
    fn exp(self) -> Self;

    /// Returns `2^(self)`.
    fn exp2(self) -> Self;

    /// Returns `base^(self)`.
    fn expf(self, base: Self::Real) -> Self;

    /// Returns the natural logarithm of the number.
    fn ln(self) -> Self;

    /// Returns the logarithm of the number with respect to an arbitrary base.
    fn log(self, base: Self::Real) -> Self;

    /// Returns the base 2 logarithm of the number.
    fn log2(self) -> Self;

    /// Returns the base 10 logarithm of the number.
    fn log10(self) -> Self;

    /// Take the cubic root of a number.
    fn cbrt(self) -> Self;

    /// Computes the sine of a number (in radians).
    fn sin(self) -> Self;

    /// Computes the cosine of a number (in radians).
    fn cos(self) -> Self;

    /// Computes the tangent of a number (in radians).
    fn tan(self) -> Self;

    /// Computes the arcsine of a number. Return value is in radians in
    /// the range [-pi/2, pi/2] or NaN if the number is outside the range
    /// [-1, 1].
    fn asin(self) -> Self;

    /// Computes the arccosine of a number. Return value is in radians in
    /// the range [0, pi] or NaN if the number is outside the range
    /// [-1, 1].
    fn acos(self) -> Self;

    /// Computes the arctangent of a number. Return value is in radians in the
    /// range [-pi/2, pi/2];
    fn atan(self) -> Self;

    /// Hyperbolic sine function.
    fn sinh(self) -> Self;

    /// Hyperbolic cosine function.
    fn cosh(self) -> Self;

    /// Hyperbolic tangent function.
    fn tanh(self) -> Self;

    /// Inverse hyperbolic sine function.
    fn asinh(self) -> Self;

    /// Inverse hyperbolic cosine function.
    fn acosh(self) -> Self;

    /// Inverse hyperbolic tangent function.
    fn atanh(self) -> Self;

    /// Returns the real part of the number.
    fn re(self) -> Self::Real;

    /// Returns the imaginary part of the number.
    fn im(self) -> Self::Real;

    /// Returns the absolute value of the number. See also [Complex::norm]
    fn abs(self) -> Self::Real;

    /// Returns the L1 norm `|re| + |im|` -- the [Manhattan distance] from the origin.
    ///
    /// [Manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry
    fn l1_norm(&self) -> Self::Real;

    /// Computes the argument of the number.
    fn arg(self) -> Self::Real;

    /// Computes the complex conjugate of the number.
    ///
    /// Formula: `a+bi -> a-bi`
    fn conj(self) -> Self;
}

macro_rules! forward {
    ($( $base:ident :: $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*)
        => {$(
            #[inline]
            fn $method(self $( , $arg : $ty )* ) -> $ret {
                $base::$method(self $( , $arg )* )
            }
        )*};
}

macro_rules! forward_ref {
    ($( Self :: $method:ident ( & self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*)
        => {$(
            #[inline]
            fn $method(self $( , $arg : $ty )* ) -> $ret {
                Self::$method(&self $( , $arg )* )
            }
        )*};
}

impl<T> ComplexFloat for T
where
    T: Float + FloatConst,
{
    type Real = T;

    fn re(self) -> Self::Real {
        self
    }

    fn im(self) -> Self::Real {
        T::zero()
    }

    fn l1_norm(&self) -> Self::Real {
        self.abs()
    }

    fn arg(self) -> Self::Real {
        if self.is_nan() {
            self
        } else if self.is_sign_negative() {
            T::PI()
        } else {
            T::zero()
        }
    }

    fn powc(self, exp: Complex<Self::Real>) -> Complex<Self::Real> {
        Complex::new(self, T::zero()).powc(exp)
    }

    fn conj(self) -> Self {
        self
    }

    fn expf(self, base: Self::Real) -> Self {
        base.powf(self)
    }

    forward! {
        Float::is_normal(self) -> bool;
        Float::is_infinite(self) -> bool;
        Float::is_finite(self) -> bool;
        Float::is_nan(self) -> bool;
        Float::recip(self) -> Self;
        Float::powi(self, n: i32) -> Self;
        Float::powf(self, f: Self) -> Self;
        Float::sqrt(self) -> Self;
        Float::cbrt(self) -> Self;
        Float::exp(self) -> Self;
        Float::exp2(self) -> Self;
        Float::ln(self) -> Self;
        Float::log(self, base: Self) -> Self;
        Float::log2(self) -> Self;
        Float::log10(self) -> Self;
        Float::sin(self) -> Self;
        Float::cos(self) -> Self;
        Float::tan(self) -> Self;
        Float::asin(self) -> Self;
        Float::acos(self) -> Self;
        Float::atan(self) -> Self;
        Float::sinh(self) -> Self;
        Float::cosh(self) -> Self;
        Float::tanh(self) -> Self;
        Float::asinh(self) -> Self;
        Float::acosh(self) -> Self;
        Float::atanh(self) -> Self;
        Float::abs(self) -> Self;
    }
}

impl<T: Float + FloatConst> ComplexFloat for Complex<T> {
    type Real = T;

    fn re(self) -> Self::Real {
        self.re
    }

    fn im(self) -> Self::Real {
        self.im
    }

    fn abs(self) -> Self::Real {
        self.norm()
    }

    fn recip(self) -> Self {
        self.finv()
    }

    // `Complex::l1_norm` uses `Signed::abs` to let it work
    // for integers too, but we can just use `Float::abs`.
    fn l1_norm(&self) -> Self::Real {
        self.re.abs() + self.im.abs()
    }

    // `Complex::is_*` methods use `T: FloatCore`, but we
    // have `T: Float` that can do them as well.
    fn is_nan(self) -> bool {
        self.re.is_nan() || self.im.is_nan()
    }

    fn is_infinite(self) -> bool {
        !self.is_nan() && (self.re.is_infinite() || self.im.is_infinite())
    }

    fn is_finite(self) -> bool {
        self.re.is_finite() && self.im.is_finite()
    }

    fn is_normal(self) -> bool {
        self.re.is_normal() && self.im.is_normal()
    }

    forward! {
        Complex::arg(self) -> Self::Real;
        Complex::powc(self, exp: Complex<Self::Real>) -> Complex<Self::Real>;
        Complex::exp2(self) -> Self;
        Complex::log(self, base: Self::Real) -> Self;
        Complex::log2(self) -> Self;
        Complex::log10(self) -> Self;
        Complex::powf(self, f: Self::Real) -> Self;
        Complex::sqrt(self) -> Self;
        Complex::cbrt(self) -> Self;
        Complex::exp(self) -> Self;
        Complex::expf(self, base: Self::Real) -> Self;
        Complex::ln(self) -> Self;
        Complex::sin(self) -> Self;
        Complex::cos(self) -> Self;
        Complex::tan(self) -> Self;
        Complex::asin(self) -> Self;
        Complex::acos(self) -> Self;
        Complex::atan(self) -> Self;
        Complex::sinh(self) -> Self;
        Complex::cosh(self) -> Self;
        Complex::tanh(self) -> Self;
        Complex::asinh(self) -> Self;
        Complex::acosh(self) -> Self;
        Complex::atanh(self) -> Self;
    }

    forward_ref! {
        Self::powi(&self, n: i32) -> Self;
        Self::conj(&self) -> Self;
    }
}

#[cfg(test)]
mod test {
    use crate::{
        complex_float::ComplexFloat,
        test::{_0_0i, _0_1i, _1_0i, _1_1i, float::close},
        Complex,
    };
    use std::f64; // for constants before Rust 1.43.

    fn closef(a: f64, b: f64) -> bool {
        close_to_tolf(a, b, 1e-10)
    }

    fn close_to_tolf(a: f64, b: f64, tol: f64) -> bool {
        // returns true if a and b are reasonably close
        let close = (a == b) || (a - b).abs() < tol;
        if !close {
            println!("{:?} != {:?}", a, b);
        }
        close
    }

    #[test]
    fn test_exp2() {
        assert!(close(ComplexFloat::exp2(_0_0i), _1_0i));
        assert!(closef(<f64 as ComplexFloat>::exp2(0.), 1.));
    }

    #[test]
    fn test_exp() {
        assert!(close(ComplexFloat::exp(_0_0i), _1_0i));
        assert!(closef(ComplexFloat::exp(0.), 1.));
    }

    #[test]
    fn test_powi() {
        assert!(close(ComplexFloat::powi(_0_1i, 4), _1_0i));
        assert!(closef(ComplexFloat::powi(-1., 4), 1.));
    }

    #[test]
    fn test_powz() {
        assert!(close(ComplexFloat::powc(_1_0i, _0_1i), _1_0i));
        assert!(close(ComplexFloat::powc(1., _0_1i), _1_0i));
    }

    #[test]
    fn test_log2() {
        assert!(close(ComplexFloat::log2(_1_0i), _0_0i));
        assert!(closef(ComplexFloat::log2(1.), 0.));
    }

    #[test]
    fn test_log10() {
        assert!(close(ComplexFloat::log10(_1_0i), _0_0i));
        assert!(closef(ComplexFloat::log10(1.), 0.));
    }

    #[test]
    fn test_conj() {
        assert_eq!(ComplexFloat::conj(_0_1i), Complex::new(0., -1.));
        assert_eq!(ComplexFloat::conj(1.), 1.);
    }

    #[test]
    fn test_is_nan() {
        assert!(!ComplexFloat::is_nan(_1_0i));
        assert!(!ComplexFloat::is_nan(1.));

        assert!(ComplexFloat::is_nan(Complex::new(f64::NAN, f64::NAN)));
        assert!(ComplexFloat::is_nan(f64::NAN));
    }

    #[test]
    fn test_is_infinite() {
        assert!(!ComplexFloat::is_infinite(_1_0i));
        assert!(!ComplexFloat::is_infinite(1.));

        assert!(ComplexFloat::is_infinite(Complex::new(
            f64::INFINITY,
            f64::INFINITY
        )));
        assert!(ComplexFloat::is_infinite(f64::INFINITY));
    }

    #[test]
    fn test_is_finite() {
        assert!(ComplexFloat::is_finite(_1_0i));
        assert!(ComplexFloat::is_finite(1.));

        assert!(!ComplexFloat::is_finite(Complex::new(
            f64::INFINITY,
            f64::INFINITY
        )));
        assert!(!ComplexFloat::is_finite(f64::INFINITY));
    }

    #[test]
    fn test_is_normal() {
        assert!(ComplexFloat::is_normal(_1_1i));
        assert!(ComplexFloat::is_normal(1.));

        assert!(!ComplexFloat::is_normal(Complex::new(
            f64::INFINITY,
            f64::INFINITY
        )));
        assert!(!ComplexFloat::is_normal(f64::INFINITY));
    }

    #[test]
    fn test_arg() {
        assert!(closef(
            ComplexFloat::arg(_0_1i),
            core::f64::consts::FRAC_PI_2
        ));

        assert!(closef(ComplexFloat::arg(-1.), core::f64::consts::PI));
        assert!(closef(ComplexFloat::arg(-0.), core::f64::consts::PI));
        assert!(closef(ComplexFloat::arg(0.), 0.));
        assert!(closef(ComplexFloat::arg(1.), 0.));
        assert!(ComplexFloat::arg(f64::NAN).is_nan());
    }
}

Messung V0.5 in Prozent
C=87 H=100 G=93

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=752002