typed Time

This commit is contained in:
Quaternions 2025-01-07 21:46:22 -08:00
parent 24787fede5
commit 86cf7e74b1

View File

@ -2,19 +2,25 @@ pub use fixed_wide::fixed::{Fixed,Fix};
pub use ratio_ops::ratio::{Ratio,Divide}; pub use ratio_ops::ratio::{Ratio,Divide};
//integer units //integer units
/// specific example of a "default" time type
#[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)] #[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)]
pub struct Time(i64); pub enum TimeInner{}
impl Time{ pub type RawTime=Time<TimeInner>;
pub const MIN:Self=Self(i64::MIN);
pub const MAX:Self=Self(i64::MAX); #[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)]
pub const ZERO:Self=Self(0); pub struct Time<T>(i64,core::marker::PhantomData<T>);
pub const ONE_SECOND:Self=Self(1_000_000_000); impl<T> Time<T>{
pub const ONE_MILLISECOND:Self=Self(1_000_000); pub const MIN:Self=Self::raw(i64::MIN);
pub const ONE_MICROSECOND:Self=Self(1_000); pub const MAX:Self=Self::raw(i64::MAX);
pub const ONE_NANOSECOND:Self=Self(1); pub const ZERO:Self=Self::raw(0);
pub const ONE_SECOND:Self=Self::raw(1_000_000_000);
pub const ONE_MILLISECOND:Self=Self::raw(1_000_000);
pub const ONE_MICROSECOND:Self=Self::raw(1_000);
pub const ONE_NANOSECOND:Self=Self::raw(1);
#[inline] #[inline]
pub const fn raw(num:i64)->Self{ pub const fn raw(num:i64)->Self{
Self(num) Self(num,core::marker::PhantomData)
} }
#[inline] #[inline]
pub const fn get(self)->i64{ pub const fn get(self)->i64{
@ -22,19 +28,19 @@ impl Time{
} }
#[inline] #[inline]
pub const fn from_secs(num:i64)->Self{ pub const fn from_secs(num:i64)->Self{
Self(Self::ONE_SECOND.0*num) Self::raw(Self::ONE_SECOND.0*num)
} }
#[inline] #[inline]
pub const fn from_millis(num:i64)->Self{ pub const fn from_millis(num:i64)->Self{
Self(Self::ONE_MILLISECOND.0*num) Self::raw(Self::ONE_MILLISECOND.0*num)
} }
#[inline] #[inline]
pub const fn from_micros(num:i64)->Self{ pub const fn from_micros(num:i64)->Self{
Self(Self::ONE_MICROSECOND.0*num) Self::raw(Self::ONE_MICROSECOND.0*num)
} }
#[inline] #[inline]
pub const fn from_nanos(num:i64)->Self{ pub const fn from_nanos(num:i64)->Self{
Self(Self::ONE_NANOSECOND.0*num) Self::raw(Self::ONE_NANOSECOND.0*num)
} }
//should I have checked subtraction? force all time variables to be positive? //should I have checked subtraction? force all time variables to be positive?
#[inline] #[inline]
@ -45,14 +51,18 @@ impl Time{
pub const fn to_ratio(self)->Ratio<Planar64,Planar64>{ pub const fn to_ratio(self)->Ratio<Planar64,Planar64>{
Ratio::new(Planar64::raw(self.0),Planar64::raw(1_000_000_000)) Ratio::new(Planar64::raw(self.0),Planar64::raw(1_000_000_000))
} }
}
impl From<Planar64> for Time{
#[inline] #[inline]
fn from(value:Planar64)->Self{ pub const fn coerce<U>(self)->Time<U>{
Time((value*Planar64::raw(1_000_000_000)).fix_1().to_raw()) Time::raw(self.0)
} }
} }
impl<Num,Den,N1,T1> From<Ratio<Num,Den>> for Time impl<T> From<Planar64> for Time<T>{
#[inline]
fn from(value:Planar64)->Self{
Self::raw((value*Planar64::raw(1_000_000_000)).fix_1().to_raw())
}
}
impl<T,Num,Den,N1,T1> From<Ratio<Num,Den>> for Time<T>
where where
Num:core::ops::Mul<Planar64,Output=N1>, Num:core::ops::Mul<Planar64,Output=N1>,
N1:Divide<Den,Output=T1>, N1:Divide<Den,Output=T1>,
@ -60,34 +70,34 @@ impl<Num,Den,N1,T1> From<Ratio<Num,Den>> for Time
{ {
#[inline] #[inline]
fn from(value:Ratio<Num,Den>)->Self{ fn from(value:Ratio<Num,Den>)->Self{
Time((value*Planar64::raw(1_000_000_000)).divide().fix().to_raw()) Self::raw((value*Planar64::raw(1_000_000_000)).divide().fix().to_raw())
} }
} }
impl std::fmt::Display for Time{ impl<T> std::fmt::Display for Time<T>{
#[inline] #[inline]
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
write!(f,"{}s+{:09}ns",self.0/Self::ONE_SECOND.0,self.0%Self::ONE_SECOND.0) write!(f,"{}s+{:09}ns",self.0/Self::ONE_SECOND.0,self.0%Self::ONE_SECOND.0)
} }
} }
impl std::default::Default for Time{ impl<T> std::default::Default for Time<T>{
fn default()->Self{ fn default()->Self{
Self(0) Self::raw(0)
} }
} }
impl std::ops::Neg for Time{ impl<T> std::ops::Neg for Time<T>{
type Output=Time; type Output=Self;
#[inline] #[inline]
fn neg(self)->Self::Output { fn neg(self)->Self::Output {
Time(-self.0) Self::raw(-self.0)
} }
} }
macro_rules! impl_time_additive_operator { macro_rules! impl_time_additive_operator {
($trait:ty, $method:ident) => { ($trait:ty, $method:ident) => {
impl $trait for Time{ impl<T> $trait for Time<T>{
type Output=Time; type Output=Self;
#[inline] #[inline]
fn $method(self,rhs:Self)->Self::Output { fn $method(self,rhs:Self)->Self::Output {
Time(self.0.$method(rhs.0)) Self::raw(self.0.$method(rhs.0))
} }
} }
}; };
@ -97,7 +107,7 @@ impl_time_additive_operator!(core::ops::Sub,sub);
impl_time_additive_operator!(core::ops::Rem,rem); impl_time_additive_operator!(core::ops::Rem,rem);
macro_rules! impl_time_additive_assign_operator { macro_rules! impl_time_additive_assign_operator {
($trait:ty, $method:ident) => { ($trait:ty, $method:ident) => {
impl $trait for Time{ impl<T> $trait for Time<T>{
#[inline] #[inline]
fn $method(&mut self,rhs:Self){ fn $method(&mut self,rhs:Self){
self.0.$method(rhs.0) self.0.$method(rhs.0)
@ -108,53 +118,60 @@ macro_rules! impl_time_additive_assign_operator {
impl_time_additive_assign_operator!(core::ops::AddAssign,add_assign); impl_time_additive_assign_operator!(core::ops::AddAssign,add_assign);
impl_time_additive_assign_operator!(core::ops::SubAssign,sub_assign); impl_time_additive_assign_operator!(core::ops::SubAssign,sub_assign);
impl_time_additive_assign_operator!(core::ops::RemAssign,rem_assign); impl_time_additive_assign_operator!(core::ops::RemAssign,rem_assign);
impl std::ops::Mul for Time{ impl<T> std::ops::Mul for Time<T>{
type Output=Ratio<fixed_wide::fixed::Fixed<2,64>,fixed_wide::fixed::Fixed<2,64>>; type Output=Ratio<fixed_wide::fixed::Fixed<2,64>,fixed_wide::fixed::Fixed<2,64>>;
#[inline] #[inline]
fn mul(self,rhs:Self)->Self::Output{ fn mul(self,rhs:Self)->Self::Output{
Ratio::new(Fixed::raw(self.0)*Fixed::raw(rhs.0),Fixed::raw_digit(1_000_000_000i64.pow(2))) Ratio::new(Fixed::raw(self.0)*Fixed::raw(rhs.0),Fixed::raw_digit(1_000_000_000i64.pow(2)))
} }
} }
impl std::ops::Div<i64> for Time{ impl<T> std::ops::Div<i64> for Time<T>{
type Output=Time; type Output=Self;
#[inline] #[inline]
fn div(self,rhs:i64)->Self::Output{ fn div(self,rhs:i64)->Self::Output{
Time(self.0/rhs) Self::raw(self.0/rhs)
} }
} }
impl std::ops::Mul<i64> for Time{ impl<T> std::ops::Mul<i64> for Time<T>{
type Output=Time; type Output=Self;
#[inline] #[inline]
fn mul(self,rhs:i64)->Self::Output{ fn mul(self,rhs:i64)->Self::Output{
Time(self.0*rhs) Self::raw(self.0*rhs)
} }
} }
impl core::ops::Mul<Time> for Planar64{ impl<T> core::ops::Mul<Time<T>> for Planar64{
type Output=Ratio<Fixed<2,64>,Planar64>; type Output=Ratio<Fixed<2,64>,Planar64>;
fn mul(self,rhs:Time)->Self::Output{ fn mul(self,rhs:Time<T>)->Self::Output{
Ratio::new(self*Fixed::raw(rhs.0),Planar64::raw(1_000_000_000)) Ratio::new(self*Fixed::raw(rhs.0),Planar64::raw(1_000_000_000))
} }
} }
#[test] #[cfg(test)]
fn time_from_planar64(){ mod test_time{
let a:Time=Planar64::from(1).into(); use super::*;
assert_eq!(a,Time::ONE_SECOND); #[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)]
} struct Test;
#[test] type Time=super::Time<Test>;
fn time_from_ratio(){ #[test]
let a:Time=Ratio::new(Planar64::from(1),Planar64::from(1)).into(); fn time_from_planar64(){
assert_eq!(a,Time::ONE_SECOND); let a:Time=Planar64::from(1).into();
} assert_eq!(a,Time::ONE_SECOND);
#[test] }
fn time_squared(){ #[test]
let a=Time::from_secs(2); fn time_from_ratio(){
assert_eq!(a*a,Ratio::new(Fixed::<2,64>::raw_digit(1_000_000_000i64.pow(2))*4,Fixed::<2,64>::raw_digit(1_000_000_000i64.pow(2)))); let a:Time=Ratio::new(Planar64::from(1),Planar64::from(1)).into();
} assert_eq!(a,Time::ONE_SECOND);
#[test] }
fn time_times_planar64(){ #[test]
let a=Time::from_secs(2); fn time_squared(){
let b=Planar64::from(2); let a=Time::from_secs(2);
assert_eq!(b*a,Ratio::new(Fixed::<2,64>::raw_digit(1_000_000_000*(1<<32))<<2,Fixed::<1,32>::raw_digit(1_000_000_000))); assert_eq!(a*a,Ratio::new(Fixed::<2,64>::raw_digit(1_000_000_000i64.pow(2))*4,Fixed::<2,64>::raw_digit(1_000_000_000i64.pow(2))));
}
#[test]
fn time_times_planar64(){
let a=Time::from_secs(2);
let b=Planar64::from(2);
assert_eq!(b*a,Ratio::new(Fixed::<2,64>::raw_digit(1_000_000_000*(1<<32))<<2,Fixed::<1,32>::raw_digit(1_000_000_000)));
}
} }
#[inline] #[inline]