pub mod error;
pub mod ops;
use crate::ty::*;
use microcad_core::*;
pub use error::*;
const OUTPUT_PRECISION: i32 = 14;
#[derive(Clone, Debug)]
pub struct Quantity {
pub value: Scalar,
pub quantity_type: QuantityType,
pub unit: Unit,
}
impl PartialEq for Quantity {
fn eq(&self, other: &Self) -> bool {
if self.quantity_type != other.quantity_type {
return false;
}
let epsilon = 10.0_f64.powi(-OUTPUT_PRECISION);
(self.value - other.value).abs() < epsilon
}
}
impl Quantity {
pub fn new(value: Scalar, quantity_type: QuantityType) -> Self {
Self {
value,
unit: quantity_type.base_unit(),
quantity_type,
}
}
pub fn map<F>(self, f: F) -> Self
where
F: FnOnce(Scalar) -> Scalar,
{
Self {
value: f(self.value),
quantity_type: self.quantity_type,
unit: self.unit,
}
}
pub fn scalar(value: Scalar) -> Self {
Quantity::new(value, QuantityType::Scalar)
}
pub fn length(length: Scalar) -> Self {
Quantity::new(length, QuantityType::Length)
}
pub fn pow(&self, rhs: &Quantity) -> Self {
match (&self.quantity_type, &rhs.quantity_type) {
(QuantityType::Scalar, QuantityType::Scalar) => {
Quantity::new(self.value.powf(rhs.value), QuantityType::Scalar)
}
_ => todo!(),
}
}
pub fn pow_int(&self, rhs: &Integer) -> Self {
match &self.quantity_type {
QuantityType::Scalar => {
Quantity::new(self.value.powi(*rhs as i32), QuantityType::Scalar)
}
QuantityType::Length => todo!(),
QuantityType::Area => todo!(),
QuantityType::Volume => todo!(),
QuantityType::Density => todo!(),
QuantityType::Angle => todo!(),
QuantityType::Weight => todo!(),
QuantityType::Invalid => todo!(),
}
}
}
impl PartialOrd for Quantity {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
if self.quantity_type == other.quantity_type {
self.value.partial_cmp(&other.value)
} else {
None
}
}
}
impl From<Scalar> for Quantity {
fn from(value: Scalar) -> Self {
Self::new(value, QuantityType::Scalar)
}
}
impl From<Integer> for Quantity {
fn from(value: Integer) -> Self {
Self::new(value as Scalar, QuantityType::Scalar)
}
}
impl From<Length> for Quantity {
fn from(length: Length) -> Self {
Self::new(*length, QuantityType::Length)
}
}
impl Ty for Quantity {
fn ty(&self) -> Type {
Type::Quantity(self.quantity_type.clone())
}
}
impl std::fmt::Display for Quantity {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}{}",
round::round(self.unit.denormalize(self.value), OUTPUT_PRECISION),
self.unit
)
}
}
impl std::hash::Hash for Quantity {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
bytemuck::bytes_of(&self.value).hash(state);
self.quantity_type.hash(state)
}
}