sim_lib_stream_clock/
instant.rs1use sim_kernel::{Error, Result};
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
24pub struct Instant {
25 numerator: i128,
26 denominator: i128,
27}
28
29impl Instant {
30 pub fn new(numerator: i128, denominator: i128) -> Result<Self> {
36 if denominator == 0 {
37 return Err(Error::Eval(
38 "instant denominator must be non-zero".to_owned(),
39 ));
40 }
41 let mut numerator = numerator;
42 let mut denominator = denominator;
43 if denominator < 0 {
44 numerator = numerator
45 .checked_neg()
46 .ok_or_else(|| Error::Eval("instant numerator overflowed".to_owned()))?;
47 denominator = denominator
48 .checked_neg()
49 .ok_or_else(|| Error::Eval("instant denominator overflowed".to_owned()))?;
50 }
51 if numerator < 0 {
52 return Err(Error::Eval(
53 "stream instants must be non-negative".to_owned(),
54 ));
55 }
56 let divisor = gcd(numerator, denominator);
57 Ok(Self {
58 numerator: numerator / divisor,
59 denominator: denominator / divisor,
60 })
61 }
62
63 pub fn seconds(seconds: u64) -> Self {
65 Self {
66 numerator: i128::from(seconds),
67 denominator: 1,
68 }
69 }
70
71 pub fn numerator(self) -> i128 {
73 self.numerator
74 }
75
76 pub fn denominator(self) -> i128 {
79 self.denominator
80 }
81
82 pub fn checked_add(self, other: Self) -> Result<Self> {
86 let numerator = self
87 .numerator
88 .checked_mul(other.denominator)
89 .and_then(|left| {
90 other
91 .numerator
92 .checked_mul(self.denominator)
93 .and_then(|right| left.checked_add(right))
94 })
95 .ok_or_else(|| Error::Eval("instant addition overflowed".to_owned()))?;
96 let denominator = self
97 .denominator
98 .checked_mul(other.denominator)
99 .ok_or_else(|| Error::Eval("instant denominator overflowed".to_owned()))?;
100 Self::new(numerator, denominator)
101 }
102
103 pub fn checked_sub(self, other: Self) -> Result<Self> {
108 let numerator = self
109 .numerator
110 .checked_mul(other.denominator)
111 .and_then(|left| {
112 other
113 .numerator
114 .checked_mul(self.denominator)
115 .and_then(|right| left.checked_sub(right))
116 })
117 .ok_or_else(|| Error::Eval("instant subtraction overflowed".to_owned()))?;
118 let denominator = self
119 .denominator
120 .checked_mul(other.denominator)
121 .ok_or_else(|| Error::Eval("instant denominator overflowed".to_owned()))?;
122 Self::new(numerator, denominator)
123 }
124}
125
126fn gcd(mut left: i128, mut right: i128) -> i128 {
127 left = left.abs();
128 right = right.abs();
129 while right != 0 {
130 let remainder = left % right;
131 left = right;
132 right = remainder;
133 }
134 left.max(1)
135}