Eine aufbereitete Darstellung der Quelle

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

Benutzer

Quelle  arithmetic_impls.rs

  Sprache: Rust
 

// #[rustfmt::skip] is being used because `rustfmt` poorly formats `#[doc = concat!(..)]`. See
// https://github.com/rust-lang/rustfmt/issues/5062 for more information.

use crate::{decimal::CalculationResult, ops, Decimal};
use core::ops::{Add, Div, Mul, Rem, Sub};
use num_traits::{CheckedAdd, CheckedDiv, CheckedMul, CheckedRem, CheckedSub, Inv};

// Macros and `Decimal` implementations

#[rustfmt::skip]
macro_rules! impl_checked {
    ($long:literal, $short:literal, $fun:ident, $impl:ident) => {
        #[doc = concat!(
            "Checked ",
            $long,
            ". Computes `self ",
            $short,
            " other`, returning `None` if overflow occurred."
        )]
        #[inline(always)]
        #[must_use]
        pub fn $fun(self, other: Decimal) -> Option<Decimal> {
            match ops::$impl(&self, &other) {
                CalculationResult::Ok(result) => Some(result),
                _ => None,
            }
        }
    };
}

#[rustfmt::skip]
macro_rules! impl_saturating {
    ($long:literal, $short:literal, $fun:ident, $impl:ident, $cmp:ident) => {
        #[doc = concat!(
            "Saturating ",
            $long,
            ". Computes `self ",
            $short,
            " other`, saturating at the relevant upper or lower boundary.",
        )]
        #[inline(always)]
        #[must_use]
        pub fn $fun(self, other: Decimal) -> Decimal {
            if let Some(elem) = self.$impl(other) {
                elem
            } else {
                $cmp(&self, &other)
            }
        }
    };
}

macro_rules! impl_checked_and_saturating {
    (
        $op_long:literal,
        $op_short:literal,
        $checked_fun:ident,
        $checked_impl:ident,

        $saturating_fun:ident,
        $saturating_cmp:ident
    ) => {
        impl_checked!($op_long, $op_short, $checked_fun, $checked_impl);
        impl_saturating!(
            $op_long,
            $op_short,
            $saturating_fun,
            $checked_fun,
            $saturating_cmp
        );
    };
}

impl Decimal {
    impl_checked_and_saturating!(
        "addition",
        "+",
        checked_add,
        add_impl,
        saturating_add,
        if_a_is_positive_then_max
    );
    impl_checked_and_saturating!(
        "multiplication",
        "*",
        checked_mul,
        mul_impl,
        saturating_mul,
        if_xnor_then_max
    );
    impl_checked_and_saturating!(
        "subtraction",
        "-",
        checked_sub,
        sub_impl,
        saturating_sub,
        if_a_is_positive_then_max
    );

    impl_checked!("division""/", checked_div, div_impl);
    impl_checked!("remainder""%", checked_rem, rem_impl);
}

// Macros and trait implementations

macro_rules! forward_all_binop {
    (impl $imp:ident for $res:ty, $method:ident) => {
        forward_val_val_binop!(impl $imp for $res, $method);
        forward_ref_val_binop!(impl $imp for $res, $method);
        forward_val_ref_binop!(impl $imp for $res, $method);
    };
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident for $res:ty, $method:ident) => {
        impl<'a> $imp<$res> for &'a $res {
            type Output = $res;

            #[inline]
            fn $method(self, other: $res) -> $res {
                self.$method(&other)
            }
        }
    };
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident for $res:ty, $method:ident) => {
        impl<'a> $imp<&'a $res> for $res {
            type Output = $res;

            #[inline]
            fn $method(self, other: &$res) -> $res {
                (&self).$method(other)
            }
        }
    };
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident for $res:ty, $method:ident) => {
        impl $imp<$res> for $res {
            type Output = $res;

            #[inline]
            fn $method(self, other: $res) -> $res {
                (&self).$method(&other)
            }
        }
    };
}

forward_all_binop!(impl Add for Decimal, add);
impl<'a, 'b> Add<&'b Decimal> for &'a Decimal {
    type Output = Decimal;

    #[inline(always)]
    fn add(self, other: &Decimal) -> Decimal {
        match ops::add_impl(self, other) {
            CalculationResult::Ok(sum) => sum,
            _ => panic!("Addition overflowed"),
        }
    }
}

impl CheckedAdd for Decimal {
    #[inline]
    fn checked_add(&self, v: &Decimal) -> Option<Decimal> {
        Decimal::checked_add(*self, *v)
    }
}

impl CheckedSub for Decimal {
    #[inline]
    fn checked_sub(&self, v: &Decimal) -> Option<Decimal> {
        Decimal::checked_sub(*self, *v)
    }
}

impl CheckedMul for Decimal {
    #[inline]
    fn checked_mul(&self, v: &Decimal) -> Option<Decimal> {
        Decimal::checked_mul(*self, *v)
    }
}

impl CheckedDiv for Decimal {
    #[inline]
    fn checked_div(&self, v: &Decimal) -> Option<Decimal> {
        Decimal::checked_div(*self, *v)
    }
}

impl CheckedRem for Decimal {
    #[inline]
    fn checked_rem(&self, v: &Decimal) -> Option<Decimal> {
        Decimal::checked_rem(*self, *v)
    }
}

impl Inv for Decimal {
    type Output = Self;

    #[inline]
    fn inv(self) -> Self {
        Decimal::ONE / self
    }
}

forward_all_binop!(impl Div for Decimal, div);
impl<'a, 'b> Div<&'b Decimal> for &'a Decimal {
    type Output = Decimal;

    #[inline]
    fn div(self, other: &Decimal) -> Decimal {
        match ops::div_impl(self, other) {
            CalculationResult::Ok(quot) => quot,
            CalculationResult::Overflow => panic!("Division overflowed"),
            CalculationResult::DivByZero => panic!("Division by zero"),
        }
    }
}

forward_all_binop!(impl Mul for Decimal, mul);
impl<'a, 'b> Mul<&'b Decimal> for &'a Decimal {
    type Output = Decimal;

    #[inline]
    fn mul(self, other: &Decimal) -> Decimal {
        match ops::mul_impl(self, other) {
            CalculationResult::Ok(prod) => prod,
            _ => panic!("Multiplication overflowed"),
        }
    }
}

forward_all_binop!(impl Rem for Decimal, rem);
impl<'a, 'b> Rem<&'b Decimal> for &'a Decimal {
    type Output = Decimal;

    #[inline]
    fn rem(self, other: &Decimal) -> Decimal {
        match ops::rem_impl(self, other) {
            CalculationResult::Ok(rem) => rem,
            CalculationResult::Overflow => panic!("Division overflowed"),
            CalculationResult::DivByZero => panic!("Division by zero"),
        }
    }
}

forward_all_binop!(impl Sub for Decimal, sub);
impl<'a, 'b> Sub<&'b Decimal> for &'a Decimal {
    type Output = Decimal;

    #[inline(always)]
    fn sub(self, other: &Decimal) -> Decimal {
        match ops::sub_impl(self, other) {
            CalculationResult::Ok(sum) => sum,
            _ => panic!("Subtraction overflowed"),
        }
    }
}

// This function signature is expected by `impl_saturating`, thus the reason of `_b`.
#[inline(always)]
const fn if_a_is_positive_then_max(a: &Decimal, _b: &Decimal) -> Decimal {
    if a.is_sign_positive() {
        Decimal::MAX
    } else {
        Decimal::MIN
    }
}

// Used by saturating multiplications.
//
// If the `a` and `b` combination represents a XNOR bit operation, returns MAX. Otherwise,
// returns MIN.
#[inline(always)]
const fn if_xnor_then_max(a: &Decimal, b: &Decimal) -> Decimal {
    match (a.is_sign_positive(), b.is_sign_positive()) {
        (truetrue) => Decimal::MAX,
        (truefalse) => Decimal::MIN,
        (falsetrue) => Decimal::MIN,
        (falsefalse) => Decimal::MAX,
    }
}

#[cfg(test)]
mod tests {
    use crate::Decimal;

    #[test]
    fn checked_methods_have_correct_output() {
        assert_eq!(Decimal::MAX.checked_add(Decimal::MAX), None);
        assert_eq!(Decimal::MAX.checked_add(Decimal::MIN), Some(Decimal::ZERO));
        assert_eq!(Decimal::MAX.checked_div(Decimal::ZERO), None);
        assert_eq!(Decimal::MAX.checked_mul(Decimal::MAX), None);
        assert_eq!(Decimal::MAX.checked_mul(Decimal::MIN), None);
        assert_eq!(Decimal::MAX.checked_rem(Decimal::ZERO), None);
        assert_eq!(Decimal::MAX.checked_sub(Decimal::MAX), Some(Decimal::ZERO));
        assert_eq!(Decimal::MAX.checked_sub(Decimal::MIN), None);

        assert_eq!(Decimal::MIN.checked_add(Decimal::MAX), Some(Decimal::ZERO));
        assert_eq!(Decimal::MIN.checked_add(Decimal::MIN), None);
        assert_eq!(Decimal::MIN.checked_div(Decimal::ZERO), None);
        assert_eq!(Decimal::MIN.checked_mul(Decimal::MAX), None);
        assert_eq!(Decimal::MIN.checked_mul(Decimal::MIN), None);
        assert_eq!(Decimal::MIN.checked_rem(Decimal::ZERO), None);
        assert_eq!(Decimal::MIN.checked_sub(Decimal::MAX), None);
        assert_eq!(Decimal::MIN.checked_sub(Decimal::MIN), Some(Decimal::ZERO));
    }

    #[test]
    fn saturated_methods_have_correct_output() {
        assert_eq!(Decimal::MAX.saturating_add(Decimal::MAX), Decimal::MAX);
        assert_eq!(Decimal::MAX.saturating_add(Decimal::MIN), Decimal::ZERO);
        assert_eq!(Decimal::MAX.saturating_mul(Decimal::MAX), Decimal::MAX);
        assert_eq!(Decimal::MAX.saturating_mul(Decimal::MIN), Decimal::MIN);
        assert_eq!(Decimal::MAX.saturating_sub(Decimal::MAX), Decimal::ZERO);
        assert_eq!(Decimal::MAX.saturating_sub(Decimal::MIN), Decimal::MAX);

        assert_eq!(Decimal::MIN.saturating_add(Decimal::MAX), Decimal::ZERO);
        assert_eq!(Decimal::MIN.saturating_add(Decimal::MIN), Decimal::MIN);
        assert_eq!(Decimal::MIN.saturating_mul(Decimal::MAX), Decimal::MIN);
        assert_eq!(Decimal::MIN.saturating_mul(Decimal::MIN), Decimal::MAX);
        assert_eq!(Decimal::MIN.saturating_sub(Decimal::MAX), Decimal::MIN);
        assert_eq!(Decimal::MIN.saturating_sub(Decimal::MIN), Decimal::ZERO);
    }
}

Messung V0.5 in Prozent
C=98 H=100 G=98

¤ Dauer der Verarbeitung: 0.19 Sekunden  (vorverarbeitet am  2026-06-26) ¤

*© 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

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik