typed_floats/types/f64/non_nan_finite.rs
1use crate::types::{f64, InvalidNumber, NonNaNFinite};
2use const_fn::const_fn;
3
4impl NonNaNFinite<f64> {
5 /// Creates a new value from a primitive type
6 /// It adds a little overhead compared to `new_unchecked`
7 /// because it checks that the value is valid
8 ///
9 /// # Examples
10 ///
11 /// ```
12 /// # use typed_floats::tf64::NonNaNFinite;
13 /// let x = NonNaNFinite::new(3.0).unwrap();
14 ///
15 /// assert_eq!(x, 3.0);
16 /// ```
17 ///
18 /// # Errors
19 /// Returns an error if the value is not valid
20 #[inline]
21 #[const_fn("1.83")]
22 pub const fn new(value: f64) -> Result<Self, InvalidNumber> {
23 if value.is_nan() {
24 return Err(InvalidNumber::NaN);
25 }
26
27 if value.is_infinite() {
28 return Err(InvalidNumber::Infinite);
29 }
30
31 Ok(Self(value))
32 }
33
34 /// Creates a new value from a primitive type with zero overhead (in release mode).
35 /// It is up to the caller to ensure that the value is valid
36 ///
37 /// # Examples
38 ///
39 /// ```
40 /// # use typed_floats::tf64::NonNaNFinite;
41 /// let x = unsafe { NonNaNFinite::new_unchecked(3.0) };
42 ///
43 /// assert_eq!(x, 3.0);
44 /// ```
45 /// # Safety
46 /// The caller must ensure that the value is valid.
47 /// It will panic in debug mode if the value is not valid,
48 /// but in release mode the behavior is undefined
49 #[inline]
50 #[must_use]
51 #[const_fn("1.83")]
52 pub const unsafe fn new_unchecked(value: f64) -> Self {
53 crate::macros::new_unchecked!(value, NonNaNFinite)
54 }
55
56 /// Returns the value as a primitive type
57 ///
58 /// # Examples
59 ///
60 /// ```
61 /// use typed_floats::tf64::NonNaNFinite;
62 ///
63 /// let x = NonNaNFinite::new(3.0).unwrap();
64 ///
65 /// let y: f64 = x.into();
66 ///
67 /// assert_eq!(y, 3.0);
68 /// ```
69 #[inline]
70 #[must_use]
71 pub const fn get(&self) -> f64 {
72 self.0
73 }
74
75 /// Returns `true` if this value is NaN.
76 /// This is never the case for the provided types
77 ///
78 /// # Examples
79 ///
80 /// ```
81 /// use typed_floats::tf64::NonNaNFinite;
82 /// let x: NonNaNFinite = 3.0.try_into().unwrap();
83 ///
84 /// assert_eq!(x.is_nan(), false);
85 /// ```
86 ///
87 /// See [`f64::is_nan()`] for more details.
88 #[inline]
89 #[must_use]
90 #[const_fn("1.83")]
91 pub const fn is_nan(&self) -> bool {
92 false
93 }
94
95 /// Returns `true` if this value is positive infinity or negative infinity.
96 ///
97 /// # Examples
98 ///
99 /// ```
100 /// use typed_floats::tf64::NonNaNFinite;
101 /// let x: NonNaNFinite = 3.0.try_into().unwrap();
102 ///
103 /// assert_eq!(x.is_infinite(), false);
104 /// ```
105 ///
106 /// See [`f64::is_infinite()`] for more details.
107 #[inline]
108 #[must_use]
109 #[const_fn("1.83")]
110 pub const fn is_infinite(&self) -> bool {
111 false
112 }
113
114 /// Returns `true` if this number is positive infinity nor negative infinity.
115 ///
116 /// # Examples
117 ///
118 /// ```
119 /// use typed_floats::tf64::NonNaNFinite;
120 /// let x: NonNaNFinite = 3.0.try_into().unwrap();
121 ///
122 /// assert_eq!(x.is_finite(), true);
123 /// ```
124 ///
125 /// See [`f64::is_finite()`] for more details.
126 #[inline]
127 #[must_use]
128 #[const_fn("1.83")]
129 pub const fn is_finite(&self) -> bool {
130 true
131 }
132
133 /// Returns `true` if the number is [subnormal](https://en.wikipedia.org/wiki/Denormal_number).
134 ///
135 /// # Examples
136 ///
137 /// ```
138 /// use typed_floats::tf64::NonNaNFinite;
139 /// let x: NonNaNFinite = 3.0.try_into().unwrap();
140 ///
141 /// assert_eq!(x.is_subnormal(), false);
142 /// ```
143 ///
144 /// See [`f64::is_subnormal()`] for more details.
145 #[inline]
146 #[must_use]
147 #[const_fn("1.83")]
148 pub const fn is_subnormal(&self) -> bool {
149 self.0.is_subnormal()
150 }
151
152 /// Returns `true` if the number is neither zero, infinite or [subnormal](https://en.wikipedia.org/wiki/Denormal_number).
153 ///
154 /// # Examples
155 ///
156 /// ```
157 /// use typed_floats::tf64::NonNaNFinite;
158 /// let x: NonNaNFinite = 3.0.try_into().unwrap();
159 ///
160 /// assert_eq!(x.is_normal(), true);
161 /// ```
162 ///
163 /// See [`f64::is_normal()`] for more details.
164 #[inline]
165 #[must_use]
166 #[const_fn("1.83")]
167 pub const fn is_normal(&self) -> bool {
168 self.0.is_normal()
169 }
170
171 /// Returns the floating point category of the number. If only one property
172 /// is going to be tested, it is generally faster to use the specific
173 /// predicate instead.
174 ///
175 /// # Examples
176 ///
177 /// ```
178 /// use typed_floats::tf64::NonNaNFinite;
179 /// let x: NonNaNFinite = 3.0.try_into().unwrap();
180 ///
181 /// assert_eq!(x.classify(), core::num::FpCategory::Normal);
182 /// ```
183 ///
184 /// See [`f64::classify()`] for more details.
185 #[inline]
186 #[must_use]
187 #[const_fn("1.83")]
188 pub const fn classify(&self) -> core::num::FpCategory {
189 self.0.classify()
190 }
191
192 /// Returns `true` if `self` has a positive sign, including `+0.0` and positive infinity.
193 ///
194 /// # Examples
195 ///
196 /// ```
197 /// use typed_floats::tf64::NonNaNFinite;
198 /// let x: NonNaNFinite = 3.0.try_into().unwrap();
199 ///
200 /// assert_eq!(x.is_sign_positive(), true);
201 /// ```
202 ///
203 /// See [`f64::is_sign_positive()`] for more details.
204 #[inline]
205 #[must_use]
206 #[const_fn("1.83")]
207 pub const fn is_sign_positive(&self) -> bool {
208 self.0.is_sign_positive()
209 }
210
211 /// Returns `true` if `self` has a negative sign, including `-0.0` and negative infinity.
212 ///
213 /// # Examples
214 ///
215 /// ```
216 /// use typed_floats::tf64::NonNaNFinite;
217 /// let x: NonNaNFinite = 3.0.try_into().unwrap();
218 ///
219 /// assert_eq!(x.is_sign_negative(), false);
220 /// ```
221 ///
222 /// See [`f64::is_sign_negative()`] for more details.
223 #[inline]
224 #[must_use]
225 #[const_fn("1.83")]
226 pub const fn is_sign_negative(&self) -> bool {
227 self.0.is_sign_negative()
228 }
229
230 /// Returns `true` if the number is negative zero.
231 ///
232 /// # Examples
233 ///
234 /// ```
235 /// use typed_floats::tf64::NonNaNFinite;
236 /// let x: NonNaNFinite = 3.0.try_into().unwrap();
237 /// let y: NonNaNFinite = (-0.0).try_into().unwrap();
238 /// let z: NonNaNFinite = 0.0.try_into().unwrap();
239 ///
240 /// assert_eq!(x.is_negative_zero(), false);
241 /// assert_eq!(y.is_negative_zero(), true);
242 /// assert_eq!(z.is_negative_zero(), false);
243 /// ```
244 #[inline]
245 #[must_use]
246 #[const_fn("1.83")]
247 pub const fn is_negative_zero(&self) -> bool {
248 self.0 == 0.0 && self.0.is_sign_negative()
249 }
250
251 /// Returns `true` if the number is positive zero.
252 ///
253 /// # Examples
254 ///
255 /// ```
256 /// use typed_floats::tf64::NonNaNFinite;
257 /// let x: NonNaNFinite = 3.0.try_into().unwrap();
258 /// let y: NonNaNFinite = (-0.0).try_into().unwrap();
259 /// let z: NonNaNFinite = 0.0.try_into().unwrap();
260 ///
261 /// assert_eq!(x.is_positive_zero(), false);
262 /// assert_eq!(y.is_positive_zero(), false);
263 /// assert_eq!(z.is_positive_zero(), true);
264 /// ```
265 #[inline]
266 #[must_use]
267 #[const_fn("1.83")]
268 pub const fn is_positive_zero(&self) -> bool {
269 self.0 == 0.0 && self.0.is_sign_positive()
270 }
271}