#![feature(const_generics, const_evaluatable_checked, doc_cfg)]
#![allow(incomplete_features)]
#![cfg_attr(feature = "non_ascii", feature(non_ascii_idents))]
use std::ops;
pub mod units;
pub mod values;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[allow(non_snake_case)]
pub struct SiUnit {
m: i8,
kg: i8,
s: i8,
A: i8,
K: i8,
mol: i8,
cd: i8,
}
impl SiUnit {
const fn neg(self) -> Self {
Self {
m: -self.m,
kg: -self.kg,
s: -self.s,
A: -self.A,
K: -self.K,
mol: -self.mol,
cd: -self.cd,
}
}
const fn unit_mul(self, rhs: Self) -> Self {
Self {
m: self.m + rhs.m,
kg: self.kg + rhs.kg,
s: self.s + rhs.s,
A: self.A + rhs.A,
K: self.K + rhs.K,
mol: self.mol + rhs.mol,
cd: self.cd + rhs.cd,
}
}
const fn unit_div(self, rhs: Self) -> Self {
Self {
m: self.m - rhs.m,
kg: self.kg - rhs.kg,
s: self.s - rhs.s,
A: self.A - rhs.A,
K: self.K - rhs.K,
mol: self.mol - rhs.mol,
cd: self.cd - rhs.cd,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct Quantity<const U: SiUnit> {
pub raw_value: f64,
}
impl<const U: SiUnit> ops::Add for Quantity<U> {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Self { raw_value: self.raw_value + rhs.raw_value }
}
}
impl<const U: SiUnit> ops::AddAssign for Quantity<U> {
fn add_assign(&mut self, rhs: Self) {
self.raw_value += rhs.raw_value;
}
}
impl<const U: SiUnit> ops::Sub for Quantity<U> {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
Self { raw_value: self.raw_value - rhs.raw_value }
}
}
impl<const U: SiUnit> ops::SubAssign for Quantity<U> {
fn sub_assign(&mut self, rhs: Self) {
self.raw_value -= rhs.raw_value;
}
}
impl<const U: SiUnit> ops::Mul<f64> for Quantity<U> {
type Output = Quantity<U>;
fn mul(self, rhs: f64) -> Self::Output {
Quantity { raw_value: self.raw_value * rhs }
}
}
impl<const U: SiUnit> ops::Mul<Quantity<U>> for f64 {
type Output = Quantity<U>;
fn mul(self, rhs: Quantity<U>) -> Self::Output {
Quantity { raw_value: self * rhs.raw_value }
}
}
impl<const UL: SiUnit, const UR: SiUnit> ops::Mul<Quantity<UR>> for Quantity<UL>
where
Quantity<{ UL.unit_mul(UR) }>: ,
{
type Output = Quantity<{ UL.unit_mul(UR) }>;
fn mul(self, rhs: Quantity<UR>) -> Self::Output {
Quantity { raw_value: self.raw_value * rhs.raw_value }
}
}
impl<const U: SiUnit> ops::MulAssign<f64> for Quantity<U> {
fn mul_assign(&mut self, rhs: f64) {
self.raw_value *= rhs;
}
}
impl<const U: SiUnit> ops::Div<f64> for Quantity<U> {
type Output = Quantity<U>;
fn div(self, rhs: f64) -> Self::Output {
Quantity { raw_value: self.raw_value / rhs }
}
}
impl<const U: SiUnit> ops::Div<Quantity<U>> for f64
where
Quantity<{ U.neg() }>: ,
{
type Output = Quantity<{ U.neg() }>;
fn div(self, rhs: Quantity<U>) -> Self::Output {
Quantity { raw_value: self / rhs.raw_value }
}
}
impl<const UL: SiUnit, const UR: SiUnit> ops::Div<Quantity<UR>> for Quantity<UL>
where
Quantity<{ UL.unit_div(UR) }>: ,
{
type Output = Quantity<{ UL.unit_div(UR) }>;
fn div(self, rhs: Quantity<UR>) -> Self::Output {
Quantity { raw_value: self.raw_value / rhs.raw_value }
}
}
impl<const U: SiUnit> ops::DivAssign<f64> for Quantity<U> {
fn div_assign(&mut self, rhs: f64) {
self.raw_value /= rhs;
}
}