hoomd_utility/valid/
positive_real.rs1use serde::{Deserialize, Serialize};
7use std::{
8 cmp::Ordering,
9 fmt,
10 ops::{Div, DivAssign, Mul, MulAssign},
11};
12
13use super::Error;
14
15#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
28pub struct PositiveReal(f64);
29
30impl PositiveReal {
31 #[must_use]
45 #[inline]
46 pub fn get(&self) -> f64 {
47 self.0
48 }
49}
50
51impl Eq for PositiveReal {}
52
53impl PartialOrd for PositiveReal {
54 #[inline]
55 fn partial_cmp(&self, other: &PositiveReal) -> Option<Ordering> {
56 Some(self.cmp(other))
57 }
58}
59
60impl Ord for PositiveReal {
61 #[inline]
62 fn cmp(&self, other: &Self) -> Ordering {
63 self.get().total_cmp(&other.get())
64 }
65}
66
67impl TryFrom<f64> for PositiveReal {
68 type Error = Error;
69
70 #[inline]
100 fn try_from(v: f64) -> Result<PositiveReal, Error> {
101 if !v.is_finite() {
102 Err(Error::NotFinite(v))
103 } else if v <= 0.0 {
104 Err(Error::NotPositive(v))
105 } else {
106 Ok(PositiveReal(v))
107 }
108 }
109}
110
111impl Default for PositiveReal {
112 #[inline]
114 fn default() -> Self {
115 PositiveReal(1.0)
116 }
117}
118
119impl fmt::Display for PositiveReal {
120 #[inline]
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 self.0.fmt(f)
123 }
124}
125
126impl Mul for PositiveReal {
127 type Output = Self;
128
129 #[inline]
130 fn mul(self, rhs: Self) -> Self {
131 Self(self.0 * rhs.0)
132 }
133}
134
135impl MulAssign<PositiveReal> for PositiveReal {
136 #[inline]
137 fn mul_assign(&mut self, rhs: PositiveReal) {
138 self.0 *= rhs.0;
139 }
140}
141
142impl Div for PositiveReal {
143 type Output = Self;
144
145 #[inline]
146 fn div(self, rhs: Self) -> Self {
147 Self(self.0 / rhs.0)
148 }
149}
150
151impl DivAssign<PositiveReal> for PositiveReal {
152 #[inline]
153 fn div_assign(&mut self, rhs: PositiveReal) {
154 self.0 /= rhs.0;
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161 use assert2::check;
162
163 #[test]
164 fn positive_real_validation() {
165 let result = PositiveReal::try_from(f64::INFINITY);
166 check!(result == Err(Error::NotFinite(f64::INFINITY)));
167
168 let result = PositiveReal::try_from(-f64::INFINITY);
169 check!(result == Err(Error::NotFinite(-f64::INFINITY)));
170
171 let result = PositiveReal::try_from(f64::NAN);
172 check!(matches!(result, Err(Error::NotFinite(_))));
173
174 let result = PositiveReal::try_from(0.0);
175 check!(result == Err(Error::NotPositive(0.0)));
176
177 let result = PositiveReal::try_from(-1.0);
178 check!(result == Err(Error::NotPositive(-1.0)));
179 }
180}