use core::{marker::PhantomData, ops::{Div, Mul}};
use num_traits::{AsPrimitive, Inv, real::Real};
use crate::{dimension::*, units::traits::*, Value};
dummy!(
pub trait AnonScale: Value + AsPrimitive<f64>
);
#[derive(Clone, Copy, Hash, Eq, Ord, PartialOrd)]
#[repr(transparent)]
pub struct UnitAnon<D: DimType, S: AnonScale = f64>(pub S, PhantomData<D>);
impl<D: DimType, S: AnonScale> UnitAnon<D, S> {
pub const fn new(s: S) -> Self { Self(s, PhantomData) }
pub fn from_unit(u: impl Unit<Dim=D>) -> Self where
f64: AsPrimitive<S>,
{
Self::new(u.scale().as_())
}
}
impl<D: DimType, S: AnonScale> Default for UnitAnon<D, S> {
fn default() -> Self { Self::new(S::one()) }
}
impl<D: DimType, S: AnonScale> PartialEq for UnitAnon<D, S> {
fn eq(&self, other: &Self) -> bool { self.0.eq(&other.0) }
}
impl<D: DimType, S: AnonScale> Unit for UnitAnon<D, S> {
type Dim = D;
fn scale(&self) -> f64 { self.0.as_() }
}
impl<D: DimType, S: AnonScale> core::fmt::Debug for UnitAnon<D, S> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "UnitAnon({:?}, \"{}\")", self.0, self.dimension())
}
}
impl<D: DimType, S: AnonScale> core::fmt::Display for UnitAnon<D, S> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "*{}", self.0)
}
}
impl<D: DimType, S: AnonScale, U: Unit> Div<U> for UnitAnon<D, S> where
D: Div<<U as Unit>::Dim>,
<D as Div<<U as Unit>::Dim>>::Output:
DimType,
{
type Output = crate::units::UnitDiv<Self, U>;
fn div(self, rhs: U) -> Self::Output {
crate::units::UnitDiv::new(self, rhs)
}
}
impl<D: DimType, S: AnonScale, U: Unit> Mul<U> for UnitAnon<D, S> where
D: Mul<<U as Unit>::Dim>,
<D as Mul<<U as Unit>::Dim>>::Output:
DimType,
{
type Output = crate::units::UnitMul<Self, U>;
fn mul(self, rhs: U) -> Self::Output {
crate::units::UnitMul::new(self, rhs)
}
}
impl<D: DimType, S: AnonScale> Inv for UnitAnon<D, S> where
D: Inv, D::Output: DimType,
{
type Output = crate::units::compound::PerUnit<Self>;
fn inv(self) -> Self::Output {
crate::units::compound::PerUnit::new(self)
}
}
impl<D: DimType, S: AnonScale, const E: i32> CanPow<E> for UnitAnon<D, S> where
Exponent<E>: HasTypenum,
D: CanDimPowType<<Exponent<E> as HasTypenum>::Typenum>,
{
type Output = crate::units::UnitPow<Self, <Exponent<E> as HasTypenum>::Typenum>;
fn pow(self) -> Self::Output {
crate::units::UnitPow::new(self)
}
}
impl<D: DimType, S: AnonScale, const E: i32> CanRoot<E> for UnitAnon<D, S> where
D: CanDimRoot<E>,
S: Real + Inv<Output=S>,
{
type Output = UnitAnon<D::Output, S>;
fn root(self) -> Self::Output {
UnitAnon::new(self.0.powf(crate::_conv_i32::<S>(E).inv()))
}
}
impl<D: DimType, S: AnonScale> UnitStep for UnitAnon<D, S> {
fn step_down(&self) -> Option<Self> { None }
fn step_up(&self) -> Option<Self> { None }
}