rust_3d/
non_negative.rs

1/*
2Copyright 2017 Martin Buck
3
4Permission is hereby granted, free of charge, to any person obtaining a copy
5of this software and associated documentation files (the "Software"),
6to deal in the Software without restriction, including without limitation the
7rights to use, copy, modify, merge, publish, distribute, sublicense,
8and/or sell copies of the Software, and to permit persons to whom the Software
9is furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall
12be included all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
20OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21*/
22
23//! NonNegative, a wrapper for a f64 value, ensuring it is always >= 0
24
25use std::{
26    fmt,
27    hash::{Hash, Hasher},
28    ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign},
29};
30
31use crate::*;
32
33//------------------------------------------------------------------------------
34
35#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
36/// NonNegative, a wrapper for a f64 value, ensuring it is always >= 0
37pub struct NonNegative {
38    val: f64,
39}
40
41impl NonNegative {
42    /// Creates a new NonNegative if input >= 0, fails otherwise
43    pub fn new(val: f64) -> Result<NonNegative> {
44        if val >= 0.0 {
45            return Ok(NonNegative { val });
46        }
47        Err(ErrorKind::NumberInWrongRange)
48    }
49    /// Creates a new NonNegative with value 0
50    pub fn zero() -> NonNegative {
51        NonNegative { val: 0.0 }
52    }
53    /// Creates a new NonNegative with value 1
54    pub fn one() -> NonNegative {
55        NonNegative { val: 1.0 }
56    }
57    /// Returns the wrapped value
58    pub fn get(&self) -> f64 {
59        self.val
60    }
61    /// Returns the square root
62    pub fn sqrt(&self) -> NonNegative {
63        NonNegative {
64            val: self.val.sqrt(),
65        }
66    }
67}
68
69//------------------------------------------------------------------------------
70
71impl From<Positive> for NonNegative {
72    fn from(x: Positive) -> Self {
73        NonNegative { val: x.get() }
74    }
75}
76
77impl Eq for NonNegative {}
78
79impl Hash for NonNegative {
80    #[inline(always)]
81    fn hash<H: Hasher>(&self, state: &mut H) {
82        hash_f64(self.val, state);
83    }
84}
85
86impl Add for NonNegative {
87    type Output = NonNegative;
88
89    fn add(self, other: NonNegative) -> NonNegative {
90        NonNegative {
91            val: self.val + other.val,
92        }
93    }
94}
95
96impl Add<Positive> for NonNegative {
97    type Output = NonNegative;
98
99    fn add(self, other: Positive) -> NonNegative {
100        NonNegative {
101            val: self.val + other.get(),
102        }
103    }
104}
105
106impl AddAssign for NonNegative {
107    fn add_assign(&mut self, other: NonNegative) {
108        self.val += other.val;
109    }
110}
111
112impl AddAssign<Positive> for NonNegative {
113    fn add_assign(&mut self, other: Positive) {
114        self.val += other.get();
115    }
116}
117
118impl Mul for NonNegative {
119    type Output = NonNegative;
120
121    fn mul(self, other: NonNegative) -> NonNegative {
122        NonNegative {
123            val: self.val * other.val,
124        }
125    }
126}
127
128impl Mul<Positive> for NonNegative {
129    type Output = NonNegative;
130
131    fn mul(self, other: Positive) -> NonNegative {
132        NonNegative {
133            val: self.val * other.get(),
134        }
135    }
136}
137
138impl MulAssign for NonNegative {
139    fn mul_assign(&mut self, other: NonNegative) {
140        self.val *= other.val;
141    }
142}
143
144impl MulAssign<Positive> for NonNegative {
145    fn mul_assign(&mut self, other: Positive) {
146        self.val *= other.get();
147    }
148}
149
150impl Div for NonNegative {
151    type Output = NonNegative;
152
153    fn div(self, other: NonNegative) -> NonNegative {
154        NonNegative {
155            val: self.val / other.val,
156        }
157    }
158}
159
160impl Div<Positive> for NonNegative {
161    type Output = NonNegative;
162
163    fn div(self, other: Positive) -> NonNegative {
164        NonNegative {
165            val: self.val / other.get(),
166        }
167    }
168}
169
170impl DivAssign for NonNegative {
171    fn div_assign(&mut self, other: NonNegative) {
172        self.val /= other.val;
173    }
174}
175
176impl DivAssign<Positive> for NonNegative {
177    fn div_assign(&mut self, other: Positive) {
178        self.val /= other.get();
179    }
180}
181
182impl Into<f64> for NonNegative {
183    fn into(self) -> f64 {
184        self.val
185    }
186}
187
188impl AsRef<f64> for NonNegative {
189    fn as_ref(&self) -> &f64 {
190        &self.val
191    }
192}
193
194impl Default for NonNegative {
195    fn default() -> Self {
196        Self::zero()
197    }
198}
199
200impl fmt::Display for NonNegative {
201    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
202        write!(f, "{}", self.val)
203    }
204}