#![allow(non_upper_case_globals)]
use core::marker::PhantomData;
use crate::dimension::Dimensions;
#[macro_use]
mod macros;
mod ops;
pub mod prefix;
pub mod si;
pub trait UnitDef {
type Dim: Dimensions;
const SCALE_NUM: i128;
const SCALE_DEN: i128;
const OFFSET_NUM: i128;
const OFFSET_DEN: i128;
const PREFIX: &'static str = "";
const SYMBOL: &'static str;
#[doc(hidden)]
const VALID: () = assert!(
Self::SCALE_NUM > 0 && Self::SCALE_DEN > 0 && Self::OFFSET_DEN != 0,
"invalid unit: scale must be positive and offset denominator non-zero",
);
}
pub struct Unit<M> {
_phantom: PhantomData<M>,
}
impl<M: UnitDef> Unit<M> {
#[inline]
pub const fn new() -> Self {
let () = M::VALID;
Self {
_phantom: PhantomData,
}
}
}
impl<M: UnitDef> Default for Unit<M> {
fn default() -> Self {
Self::new()
}
}
impl<M> Clone for Unit<M> {
fn clone(&self) -> Self {
*self
}
}
impl<M> Copy for Unit<M> {}
impl<M: UnitDef> core::fmt::Debug for Unit<M> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Unit({}{})", M::PREFIX, M::SYMBOL)
}
}
const fn gcd(mut a: i128, mut b: i128) -> i128 {
while b != 0 {
let r = a % b;
a = b;
b = r;
}
a
}
pub const fn reduce_num(n: i128, d: i128) -> i128 {
assert!(n > 0 && d > 0, "unit scale must be positive");
n / gcd(n, d)
}
pub const fn reduce_den(n: i128, d: i128) -> i128 {
assert!(n > 0 && d > 0, "unit scale must be positive");
d / gcd(n, d)
}