uom icon indicating copy to clipboard operation
uom copied to clipboard

Quantity-Aware access parts of quantity with complex storage type

Open mkalte666 opened this issue 6 months ago • 2 comments

It can be interesting (or needed) to access only the real or imaginary part of a complex quantity.

Currently, i have solved this for my codebase like this, but it would be nice to have this available in uom directly as well. For all i know, its already there; im known to miss the most obvious functions out there :D

/// Helper trait to grab real or complex parts of Quantities
pub trait ComplexAccess {
    type VT;
    type AT;
    /// Get the real part of Self
    fn real(&self) -> Self::VT;

    /// Get the imaginary part of Self
    fn imag(&self) -> Self::VT;

    /// Get the norm of Self
    fn norm(&self) -> Self::VT;

    /// Get the argument of Self
    fn arg(&self) -> Self::AT;
}

use uom::{storage_type_complex32, storage_type_complex64};

storage_types! {
    pub types: Complex;

    impl<D> crate::ComplexAccess for uom::si::Quantity<D,uom::si::SI<V>,V>
    where
        D: uom::si::Dimension + ?Sized,
    {
        type VT = uom::si::Quantity<D,uom::si::SI<VV>,VV>;
        type AT = uom::si::angle::Angle<uom::si::SI::<VV>,VV>;
        fn real(&self) -> Self::VT {
            Self::VT {
                dimension: self.dimension,
                units: std::marker::PhantomData::default(),
                value: self.value.re
            }
        }

        fn imag(&self) -> Self::VT {
            Self::VT {
                dimension: self.dimension,
                units: std::marker::PhantomData::default(),
                value: self.value.im
            }
        }

        fn norm(&self) -> Self::VT
        {
            Self::VT {
                dimension: self.dimension,
                units: std::marker::PhantomData::default(),
                value: self.value.norm()
            }
        }

        fn arg(&self) -> Self::AT
        {
           Self::AT::new::<uom::si::angle::radian>(self.value.arg())
        }
    }
}

Example usage would be somthing like this:

let z = si::complex64::ElectricalResistance::new::<ohm>(Complex64::new(123.0,321.0));
let im : si::f64::ElectricalResistance = z.real(); 
assert_eq!(im.get::<ohm>(), 321.0);
// do something with re; i.e compute a capacitance or whatever else 

mkalte666 avatar Jan 17 '24 06:01 mkalte666