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