use num::{Zero, complex::Complex};
use uom::si::*;
use super::{DynQuantity, F64RealOrComplex};
use crate::error::{ConversionError, NotConvertibleFromComplexF64};
use crate::unit::Unit;
#[cfg(feature = "uom")]
impl<L, M, T, I, Th, N, J, K> crate::unit::UnitFromType
for uom::si::Quantity<uom::si::ISQ<L, M, T, I, Th, N, J, K>, uom::si::SI<f64>, f64>
where
L: uom::typenum::Integer,
M: uom::typenum::Integer,
T: uom::typenum::Integer,
I: uom::typenum::Integer,
Th: uom::typenum::Integer,
N: uom::typenum::Integer,
J: uom::typenum::Integer,
K: ?Sized,
{
fn unit_from_type() -> Unit {
return Unit {
second: T::to_i32(),
meter: L::to_i32(),
kilogram: M::to_i32(),
ampere: I::to_i32(),
kelvin: Th::to_i32(),
mol: N::to_i32(),
candela: J::to_i32(),
};
}
}
impl<L, M, T, I, Th, N, J, K, V> TryFrom<DynQuantity<V>>
for uom::si::Quantity<uom::si::ISQ<L, M, T, I, Th, N, J, K>, uom::si::SI<f64>, f64>
where
L: uom::typenum::Integer,
M: uom::typenum::Integer,
T: uom::typenum::Integer,
I: uom::typenum::Integer,
Th: uom::typenum::Integer,
N: uom::typenum::Integer,
J: uom::typenum::Integer,
K: ?Sized,
V: F64RealOrComplex,
{
type Error = ConversionError;
fn try_from(quantity: DynQuantity<V>) -> Result<Self, Self::Error> {
let expected = Unit {
second: T::to_i32(),
meter: L::to_i32(),
kilogram: M::to_i32(),
ampere: I::to_i32(),
kelvin: Th::to_i32(),
mol: N::to_i32(),
candela: J::to_i32(),
};
if expected != quantity.unit {
return Err(ConversionError::UnitMismatch {
expected,
found: quantity.unit,
});
}
let value = quantity.value.to_complexf64();
if !value.im.is_zero() {
return Err(ConversionError::NotConvertibleFromComplexF64(
NotConvertibleFromComplexF64 {
source: value,
target_type: "f64",
},
));
}
return Ok(uom::si::Quantity {
dimension: std::marker::PhantomData,
units: std::marker::PhantomData,
value: value.re,
});
}
}
impl<L, M, T, I, Th, N, J, K, V> TryFrom<DynQuantity<V>>
for uom::si::Quantity<
uom::si::ISQ<L, M, T, I, Th, N, J, K>,
uom::si::SI<Complex<f64>>,
Complex<f64>,
>
where
L: uom::typenum::Integer,
M: uom::typenum::Integer,
T: uom::typenum::Integer,
I: uom::typenum::Integer,
Th: uom::typenum::Integer,
N: uom::typenum::Integer,
J: uom::typenum::Integer,
K: ?Sized,
V: F64RealOrComplex,
{
type Error = ConversionError;
fn try_from(quantity: DynQuantity<V>) -> Result<Self, Self::Error> {
let expected = Unit {
second: T::to_i32(),
meter: L::to_i32(),
kilogram: M::to_i32(),
ampere: I::to_i32(),
kelvin: Th::to_i32(),
mol: N::to_i32(),
candela: J::to_i32(),
};
if expected != quantity.unit {
return Err(ConversionError::UnitMismatch {
expected,
found: quantity.unit,
});
}
let value = quantity.value.to_complexf64();
return Ok(uom::si::Quantity {
dimension: std::marker::PhantomData,
units: std::marker::PhantomData,
value,
});
}
}
impl<L, M, T, I, Th, N, J, K, V>
From<uom::si::Quantity<uom::si::ISQ<L, M, T, I, Th, N, J, K>, uom::si::SI<f64>, f64>>
for DynQuantity<V>
where
L: uom::typenum::Integer,
M: uom::typenum::Integer,
T: uom::typenum::Integer,
I: uom::typenum::Integer,
Th: uom::typenum::Integer,
N: uom::typenum::Integer,
J: uom::typenum::Integer,
K: ?Sized,
V: F64RealOrComplex,
{
fn from(
quantity: uom::si::Quantity<uom::si::ISQ<L, M, T, I, Th, N, J, K>, uom::si::SI<f64>, f64>,
) -> Self {
return Self::from(&quantity);
}
}
impl<L, M, T, I, Th, N, J, K, V>
From<&uom::si::Quantity<uom::si::ISQ<L, M, T, I, Th, N, J, K>, uom::si::SI<f64>, f64>>
for DynQuantity<V>
where
L: uom::typenum::Integer,
M: uom::typenum::Integer,
T: uom::typenum::Integer,
I: uom::typenum::Integer,
Th: uom::typenum::Integer,
N: uom::typenum::Integer,
J: uom::typenum::Integer,
K: ?Sized,
V: F64RealOrComplex,
{
fn from(
quantity: &uom::si::Quantity<uom::si::ISQ<L, M, T, I, Th, N, J, K>, uom::si::SI<f64>, f64>,
) -> Self {
let exponents = Unit {
second: T::to_i32(),
meter: L::to_i32(),
kilogram: M::to_i32(),
ampere: I::to_i32(),
kelvin: Th::to_i32(),
mol: N::to_i32(),
candela: J::to_i32(),
};
return DynQuantity::new(V::from_f64(quantity.value.clone()), exponents);
}
}
impl<L, M, T, I, Th, N, J, K, V>
TryFrom<
uom::si::Quantity<
uom::si::ISQ<L, M, T, I, Th, N, J, K>,
uom::si::SI<Complex<f64>>,
Complex<f64>,
>,
> for DynQuantity<V>
where
L: uom::typenum::Integer,
M: uom::typenum::Integer,
T: uom::typenum::Integer,
I: uom::typenum::Integer,
Th: uom::typenum::Integer,
N: uom::typenum::Integer,
J: uom::typenum::Integer,
K: ?Sized,
V: F64RealOrComplex,
{
type Error = NotConvertibleFromComplexF64;
fn try_from(
quantity: uom::si::Quantity<
uom::si::ISQ<L, M, T, I, Th, N, J, K>,
uom::si::SI<Complex<f64>>,
Complex<f64>,
>,
) -> Result<Self, Self::Error> {
let value = V::try_from_complexf64(quantity.value)?;
let exponents = Unit {
second: T::to_i32(),
meter: L::to_i32(),
kilogram: M::to_i32(),
ampere: I::to_i32(),
kelvin: Th::to_i32(),
mol: N::to_i32(),
candela: J::to_i32(),
};
return Ok(DynQuantity::new(value, exponents));
}
}