rust_3d/
positive.rs

1/*
2Copyright 2016 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//! Positive, 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, Mul, MulAssign},
29};
30
31use crate::*;
32
33//------------------------------------------------------------------------------
34
35#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
36/// Positive, a wrapper for a f64 value, ensuring it is always > 0
37pub struct Positive {
38    val: f64,
39}
40
41impl Positive {
42    /// Creates a new Positive if input > 0, fails otherwise
43    pub fn new(val: f64) -> Result<Positive> {
44        if val > 0.0 {
45            return Ok(Positive { val });
46        }
47        Err(ErrorKind::NumberInWrongRange)
48    }
49    /// Creates a new Positive with value 1
50    pub fn one() -> Positive {
51        Positive { val: 1.0 }
52    }
53    /// Returns the wrapped value
54    pub fn get(&self) -> f64 {
55        self.val
56    }
57    /// Returns the square root
58    pub fn sqrt(&self) -> Positive {
59        Positive {
60            val: self.val.sqrt(),
61        }
62    }
63}
64
65//------------------------------------------------------------------------------
66
67impl Eq for Positive {}
68
69impl Hash for Positive {
70    #[inline(always)]
71    fn hash<H: Hasher>(&self, state: &mut H) {
72        hash_f64(self.val, state);
73    }
74}
75
76impl Add for Positive {
77    type Output = Positive;
78
79    fn add(self, other: Positive) -> Positive {
80        Positive {
81            val: self.val + other.val,
82        }
83    }
84}
85
86impl Add<NonNegative> for Positive {
87    type Output = Positive;
88
89    fn add(self, other: NonNegative) -> Positive {
90        Positive {
91            val: self.val + other.get(),
92        }
93    }
94}
95
96impl AddAssign for Positive {
97    fn add_assign(&mut self, other: Positive) {
98        self.val += other.val;
99    }
100}
101
102impl AddAssign<NonNegative> for Positive {
103    fn add_assign(&mut self, other: NonNegative) {
104        self.val += other.get();
105    }
106}
107
108impl Mul for Positive {
109    type Output = Positive;
110
111    fn mul(self, other: Positive) -> Positive {
112        Positive {
113            val: self.val * other.val,
114        }
115    }
116}
117
118impl Mul<NonNegative> for Positive {
119    type Output = NonNegative;
120
121    fn mul(self, other: NonNegative) -> NonNegative {
122        other * self
123    }
124}
125
126impl MulAssign for Positive {
127    fn mul_assign(&mut self, other: Positive) {
128        self.val *= other.get();
129    }
130}
131
132impl Div for Positive {
133    type Output = NonNegative;
134
135    fn div(self, other: Positive) -> NonNegative {
136        NonNegative::new(self.val / other.get()).unwrap() // safe
137    }
138}
139
140impl Div<NonNegative> for Positive {
141    type Output = NonNegative;
142
143    fn div(self, other: NonNegative) -> NonNegative {
144        NonNegative::new(self.val / other.get()).unwrap() // safe
145    }
146}
147
148impl Into<f64> for Positive {
149    fn into(self) -> f64 {
150        self.val
151    }
152}
153
154impl AsRef<f64> for Positive {
155    fn as_ref(&self) -> &f64 {
156        &self.val
157    }
158}
159
160impl Default for Positive {
161    fn default() -> Self {
162        Self::one()
163    }
164}
165
166impl fmt::Display for Positive {
167    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
168        write!(f, "{}", self.val)
169    }
170}