infinitable/lib.rs
1//! Infinity for types without infinite values
2//!
3//! Infinitable introduces the notion of "infinity" and "negative infinity"
4//! to numeric types, such as integers, that do not have infinite values.
5//!
6//! A representation of infinity is useful for graph algorithms such as
7//! Dijkstra's algorithm, as well as for representing a graph with an
8//! adjacency matrix.
9//!
10//! # Basic Usage
11//!
12//! ```
13//! use infinitable::*;
14//!
15//! let finite = Finite(5);
16//! let infinity = Infinity;
17//! let negative_infinity = NegativeInfinity;
18//!
19//! assert!(finite < infinity);
20//! assert!(finite > negative_infinity);
21//! ```
22
23#![cfg_attr(not(test), no_std)]
24
25use core::cmp::Ordering;
26use core::fmt;
27use core::fmt::{Display, Formatter};
28use core::ops::{Add, Div, Mul, Neg, Sub};
29use num_traits::Zero;
30
31/// An "infinitable" value, one that can be either finite or infinite
32///
33/// # Versioning
34///
35/// Available since 1.0.0. Variants are re-exported since 1.3.0.
36#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
37pub enum Infinitable<T> {
38 /// A finite value `T`
39 Finite(T),
40 /// Positive infinity, which compares greater than all other values
41 Infinity,
42 /// Negative infinity, which compares less than all other values
43 NegativeInfinity,
44}
45
46pub use Infinitable::{Finite, Infinity, NegativeInfinity};
47
48impl<T> Infinitable<T> {
49 /// Returns `true` if the value is [`Finite`].
50 ///
51 /// # Examples
52 ///
53 /// ```
54 /// use infinitable::*;
55 ///
56 /// let finite = Finite(5);
57 /// assert!(finite.is_finite());
58 /// let infinite: Infinitable<i32> = Infinity;
59 /// assert!(!infinite.is_finite());
60 /// ```
61 ///
62 /// # Versioning
63 ///
64 /// Available since 1.0.0.
65 #[must_use]
66 pub fn is_finite(&self) -> bool {
67 match self {
68 Finite(_) => true,
69 _ => false,
70 }
71 }
72
73 /// Converts from an `Infinitable<T>` to an [`Option<T>`].
74 ///
75 /// Converts `self` into an [`Option<T>`] possibly containing
76 /// a finite value, consuming `self`.
77 ///
78 /// # Examples
79 ///
80 /// ```
81 /// use infinitable::*;
82 ///
83 /// let finite = Finite(5);
84 /// assert_eq!(Some(5), finite.finite());
85 /// let infinite: Infinitable<i32> = Infinity;
86 /// assert_eq!(None, infinite.finite());
87 /// ```
88 ///
89 /// # Versioning
90 ///
91 /// Available since 1.1.0.
92 #[must_use]
93 pub fn finite(self) -> Option<T> {
94 match self {
95 Finite(x) => Some(x),
96 _ => None,
97 }
98 }
99
100 /// Converts from [`Option<T>`] to [`Finite`] or [`Infinity`].
101 ///
102 /// <code>[Some]\(T)</code> is converted to <code>[Finite]\(T)</code>,
103 /// and [`None`] is converted to [`Infinity`].
104 ///
105 /// # Examples
106 ///
107 /// ```
108 /// use infinitable::*;
109 ///
110 /// let finite = Finite(5);
111 /// assert_eq!(finite, Infinitable::finite_or_infinity(Some(5)));
112 /// let infinite: Infinitable<i32> = Infinity;
113 /// assert_eq!(infinite, Infinitable::finite_or_infinity(None));
114 /// ```
115 ///
116 /// # Versioning
117 ///
118 /// Available since 1.3.0.
119 #[must_use]
120 pub fn finite_or_infinity(option: Option<T>) -> Infinitable<T> {
121 match option {
122 Some(x) => Finite(x),
123 None => Infinity,
124 }
125 }
126
127 /// Converts from [`Option<T>`] to [`Finite`] or [`NegativeInfinity`].
128 ///
129 /// <code>[Some]\(T)</code> is converted to <code>[Finite]\(T)</code>,
130 /// and [`None`] is converted to [`NegativeInfinity`].
131 ///
132 /// # Examples
133 ///
134 /// ```
135 /// use infinitable::*;
136 ///
137 /// let finite = Finite(5);
138 /// assert_eq!(finite, Infinitable::finite_or_negative_infinity(Some(5)));
139 /// let infinite: Infinitable<i32> = NegativeInfinity;
140 /// assert_eq!(infinite, Infinitable::finite_or_negative_infinity(None));
141 /// ```
142 ///
143 /// # Versioning
144 ///
145 /// Available since 1.3.0.
146 #[must_use]
147 pub fn finite_or_negative_infinity(option: Option<T>) -> Infinitable<T> {
148 match option {
149 Some(x) => Finite(x),
150 None => NegativeInfinity,
151 }
152 }
153
154 /// Converts the value into a different type, based on the conversion of the
155 /// underlying type `T`.
156 ///
157 /// Infinite values are preserved as is, while finite values are converted
158 /// using [`into`] on the underlying value.
159 ///
160 /// [`into`]: Into::into
161 ///
162 /// # Examples
163 ///
164 /// ```
165 /// use infinitable::*;
166 /// let finite = Finite(5);
167 /// let finite64: Infinitable<i64> = finite.convert_into();
168 /// assert_eq!(Finite(5i64), finite64);
169 /// let infinite: Infinitable<i32> = Infinity;
170 /// let infinite64: Infinitable<i64> = infinite.convert_into();
171 /// assert_eq!(Infinity, infinite64);
172 /// ```
173 ///
174 /// # Versioning
175 ///
176 /// Available since 1.6.0.
177 #[must_use]
178 pub fn convert_into<U>(self) -> Infinitable<U>
179 where
180 T: Into<U>,
181 {
182 match self {
183 Finite(x) => Finite(x.into()),
184 Infinity => Infinity,
185 NegativeInfinity => NegativeInfinity,
186 }
187 }
188
189 /// Converts the value into a different type, based on the conversion of the
190 /// underlying type `T`.
191 ///
192 /// Infinite values are preserved as is, while finite values are converted
193 /// using [`try_into`] on the underlying value. Conversion of infinite
194 /// values always succeeds, while conversion of finite values may fail.
195 ///
196 /// [`try_into`]: TryInto::try_into
197 ///
198 /// # Examples
199 ///
200 /// ```
201 /// use infinitable::*;
202 /// use std::num::TryFromIntError;
203 /// let finite = Finite(1000);
204 /// let finite8: Result<Infinitable<i8>, TryFromIntError>
205 /// = finite.try_convert_into();
206 /// assert!(finite8.is_err());
207 /// let infinite: Infinitable<i32> = Infinity;
208 /// let infinite8: Result<Infinitable<i8>, TryFromIntError>
209 /// = infinite.try_convert_into();
210 /// assert_eq!(Ok(Infinity), infinite8);
211 /// ```
212 ///
213 /// # Versioning
214 ///
215 /// Available since 1.6.0.
216 #[must_use]
217 pub fn try_convert_into<U>(self) -> Result<Infinitable<U>, T::Error>
218 where
219 T: TryInto<U>,
220 {
221 match self {
222 Finite(x) => x.try_into().map(|y| Finite(y)),
223 Infinity => Ok(Infinity),
224 NegativeInfinity => Ok(NegativeInfinity),
225 }
226 }
227}
228
229impl<T> From<T> for Infinitable<T> {
230 /// Converts from a value `T` to [`Finite`] containing the underlying value.
231 ///
232 /// Note that there is no special handling for pre-existing infinite values.
233 /// Consider using [`from_f32`] or [`from_f64`] for floating-point numbers.
234 ///
235 /// # Examples
236 ///
237 /// ```
238 /// use infinitable::*;
239 ///
240 /// let finite = Infinitable::from(5);
241 /// assert_eq!(Finite(5), finite);
242 ///
243 /// // Warning: There is no special handling for pre-existing infinite values
244 /// let fp_infinity = Infinitable::from(f32::INFINITY);
245 /// assert_eq!(Finite(f32::INFINITY), fp_infinity);
246 /// assert_ne!(Infinity, fp_infinity);
247 /// ```
248 ///
249 /// # Versioning
250 ///
251 /// Available since 1.2.0.
252 fn from(value: T) -> Infinitable<T> {
253 Finite(value)
254 }
255}
256
257/// Partial order, when the underlying type `T` implements a partial order.
258///
259/// [`NegativeInfinity`] compares less than all other values,
260/// and [`Infinity`] compares greater than all other values.
261///
262/// # Examples
263///
264/// ```
265/// use infinitable::*;
266/// use std::cmp::Ordering;
267///
268/// let finite = Finite(5);
269/// let infinity = Infinity;
270/// let negative_infinity = NegativeInfinity;
271///
272/// assert_eq!(Some(Ordering::Less), finite.partial_cmp(&infinity));
273/// assert_eq!(Some(Ordering::Greater), finite.partial_cmp(&negative_infinity));
274/// ```
275///
276/// # Versioning
277///
278/// Available since 1.0.0.
279impl<T> PartialOrd for Infinitable<T>
280where
281 T: PartialOrd,
282{
283 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
284 match cmp_initial(self, other) {
285 CmpInitialResult::Infinite(o) => Some(o),
286 CmpInitialResult::Finite(x, y) => x.partial_cmp(y),
287 }
288 }
289}
290
291/// Total order, when the underlying type `T` implements a total order.
292///
293/// [`NegativeInfinity`] compares less than all other values,
294/// and [`Infinity`] compares greater than all other values.
295///
296/// # Examples
297///
298/// ```
299/// use infinitable::*;
300/// use std::cmp::Ordering;
301///
302/// let finite = Finite(5);
303/// let infinity = Infinity;
304/// let negative_infinity = NegativeInfinity;
305///
306/// assert_eq!(Ordering::Less, finite.cmp(&infinity));
307/// assert_eq!(Ordering::Greater, finite.cmp(&negative_infinity));
308/// ```
309///
310/// # Versioning
311///
312/// Available since 1.0.0.
313impl<T> Ord for Infinitable<T>
314where
315 T: Ord,
316{
317 fn cmp(&self, other: &Self) -> Ordering {
318 match cmp_initial(self, other) {
319 CmpInitialResult::Infinite(o) => o,
320 CmpInitialResult::Finite(x, y) => x.cmp(y),
321 }
322 }
323}
324
325enum CmpInitialResult<'a, T> {
326 Infinite(Ordering),
327 Finite(&'a T, &'a T),
328}
329
330fn cmp_initial<'a, T>(x: &'a Infinitable<T>, y: &'a Infinitable<T>) -> CmpInitialResult<'a, T> {
331 match (x, y) {
332 (Infinity, Infinity) | (NegativeInfinity, NegativeInfinity) => {
333 CmpInitialResult::Infinite(Ordering::Equal)
334 }
335 (Infinity, _) | (_, NegativeInfinity) => CmpInitialResult::Infinite(Ordering::Greater),
336 (NegativeInfinity, _) | (_, Infinity) => CmpInitialResult::Infinite(Ordering::Less),
337 (Finite(xf), Finite(yf)) => CmpInitialResult::Finite(xf, yf),
338 }
339}
340
341impl<T> Add for Infinitable<T>
342where
343 T: Add,
344{
345 type Output = Infinitable<T::Output>;
346
347 /// Adds two values.
348 ///
349 /// The addition operation follows these rules:
350 ///
351 /// | self | rhs | result |
352 /// |--------------------|--------------------|-----------------------|
353 /// | `Finite` | `Finite` | `Finite` (add values) |
354 /// | `Finite` | `Infinity` | `Infinity` |
355 /// | `Finite` | `NegativeInfinity` | `NegativeInfinity` |
356 /// | `Infinity` | `Finite` | `Infinity` |
357 /// | `Infinity` | `Infinity` | `Infinity` |
358 /// | `Infinity` | `NegativeInfinity` | Undefined (panic) |
359 /// | `NegativeInfinity` | `Finite` | `NegativeInfinity` |
360 /// | `NegativeInfinity` | `Infinity` | Undefined (panic) |
361 /// | `NegativeInfinity` | `NegativeInfinity` | `NegativeInfinity` |
362 ///
363 /// # Examples
364 ///
365 /// ```
366 /// use infinitable::*;
367 ///
368 /// assert_eq!(Finite(5), Finite(2) + Finite(3));
369 /// assert_eq!(Infinity, Finite(1) + Infinity);
370 /// assert_eq!(NegativeInfinity, NegativeInfinity + Finite(1));
371 /// ```
372 ///
373 /// The addition operation panics with `Infinity` and `NegativeInfinity`:
374 ///
375 /// ```should_panic
376 /// use infinitable::*;
377 ///
378 /// let infinity: Infinitable<i32> = Infinity;
379 /// let negative_infinity: Infinitable<i32> = NegativeInfinity;
380 /// let _ = infinity + negative_infinity;
381 /// ```
382 ///
383 /// # Panics
384 ///
385 /// Panics if the operands consist of `Infinity` and `NegativeInfinity`.
386 ///
387 /// # Versioning
388 ///
389 /// Available since 1.5.0.
390 fn add(self, rhs: Infinitable<T>) -> Infinitable<T::Output> {
391 match (self, rhs) {
392 (Infinity, NegativeInfinity) | (NegativeInfinity, Infinity) => {
393 panic!("Cannot add infinity and negative infinity")
394 }
395 (Finite(lf), Finite(rf)) => Finite(lf.add(rf)),
396 (Infinity, _) | (_, Infinity) => Infinity,
397 (NegativeInfinity, _) | (_, NegativeInfinity) => NegativeInfinity,
398 }
399 }
400}
401
402impl<T> Sub for Infinitable<T>
403where
404 T: Sub,
405{
406 type Output = Infinitable<T::Output>;
407
408 /// Subtracts two values.
409 ///
410 /// The subtraction operation follows these rules:
411 ///
412 /// | self | rhs | result |
413 /// |--------------------|--------------------|----------------------------|
414 /// | `Finite` | `Finite` | `Finite` (subtract values) |
415 /// | `Finite` | `Infinity` | `NegativeInfinity` |
416 /// | `Finite` | `NegativeInfinity` | `Infinity` |
417 /// | `Infinity` | `Finite` | `Infinity` |
418 /// | `Infinity` | `Infinity` | Undefined (panic) |
419 /// | `Infinity` | `NegativeInfinity` | `Infinity` |
420 /// | `NegativeInfinity` | `Finite` | `NegativeInfinity` |
421 /// | `NegativeInfinity` | `Infinity` | `NegativeInfinity` |
422 /// | `NegativeInfinity` | `NegativeInfinity` | Undefined (panic) |
423 ///
424 /// # Examples
425 ///
426 /// ```
427 /// use infinitable::*;
428 ///
429 /// assert_eq!(Finite(3), Finite(5) - Finite(2));
430 /// assert_eq!(Infinity, Infinity - Finite(1));
431 /// assert_eq!(Infinity, Finite(1) - NegativeInfinity);
432 /// assert_eq!(NegativeInfinity, NegativeInfinity - Finite(1));
433 /// assert_eq!(NegativeInfinity, Finite(1) - Infinity);
434 /// ```
435 ///
436 /// The subraction operation panics when an infinite value is subtracted
437 /// from itself:
438 ///
439 /// ```should_panic
440 /// use infinitable::*;
441 ///
442 /// let infinity: Infinitable<i32> = Infinity;
443 /// let _ = infinity - infinity;
444 /// ```
445 ///
446 /// # Panics
447 ///
448 /// Panics if the operands are both `Infinity` or both `NegativeInfinity`.
449 ///
450 /// # Versioning
451 ///
452 /// Available since 1.5.0.
453 fn sub(self, rhs: Infinitable<T>) -> Infinitable<T::Output> {
454 match (self, rhs) {
455 (Infinity, Infinity) | (NegativeInfinity, NegativeInfinity) => {
456 panic!("Cannot subtract infinite value from itself")
457 }
458 (Finite(lf), Finite(rf)) => Finite(lf.sub(rf)),
459 (Infinity, _) | (_, NegativeInfinity) => Infinity,
460 (NegativeInfinity, _) | (_, Infinity) => NegativeInfinity,
461 }
462 }
463}
464
465impl<T> Mul for Infinitable<T>
466where
467 T: Mul + Zero + PartialOrd,
468{
469 type Output = Infinitable<<T as Mul>::Output>;
470
471 /// Multiplies two values.
472 ///
473 /// The multiplication operation follows these rules:
474 ///
475 /// | self | rhs | result |
476 /// |--------------------|--------------------|----------------------------|
477 /// | `Finite` | `Finite` | `Finite` (multiply values) |
478 /// | `Finite` (> 0) | `Infinity` | `Infinity` |
479 /// | `Finite` (~ 0) | `Infinity` | Undefined (panic) |
480 /// | `Finite` (< 0) | `Infinity` | `NegativeInfinity` |
481 /// | `Finite` (> 0) | `NegativeInfinity` | `NegativeInfinity` |
482 /// | `Finite` (~ 0) | `NegativeInfinity` | Undefined (panic) |
483 /// | `Finite` (< 0) | `NegativeInfinity` | `Infinity` |
484 /// | `Infinity` | `Finite` (> 0) | `Infinity` |
485 /// | `Infinity` | `Finite` (~ 0) | Undefined (panic) |
486 /// | `Infinity` | `Finite` (< 0) | `NegativeInfinity` |
487 /// | `Infinity` | `Infinity` | `Infinity` |
488 /// | `Infinity` | `NegativeInfinity` | `NegativeInfinity` |
489 /// | `NegativeInfinity` | `Finite` (> 0) | `NegativeInfinity` |
490 /// | `NegativeInfinity` | `Finite` (~ 0) | Undefined (panic) |
491 /// | `NegativeInfinity` | `Finite` (< 0) | `Infinity` |
492 /// | `NegativeInfinity` | `Infinity` | `NegativeInfinity` |
493 /// | `NegativeInfinity` | `NegativeInfinity` | `Infinity` |
494 ///
495 /// (In the table, "~ 0" refers to a value that is either equal to or
496 /// unordered with zero.)
497 ///
498 /// # Examples
499 ///
500 /// ```
501 /// use infinitable::*;
502 ///
503 /// assert_eq!(Finite(6), Finite(2) * Finite(3));
504 /// assert_eq!(Infinity, Infinity * Finite(2));
505 /// assert_eq!(Infinity, Finite(-1) * NegativeInfinity);
506 /// assert_eq!(NegativeInfinity, NegativeInfinity * Finite(2));
507 /// assert_eq!(NegativeInfinity, Finite(-1) * Infinity);
508 /// ```
509 ///
510 /// The multiplication operation panics when an infinite value is multiplied
511 /// with zero:
512 ///
513 /// ```should_panic
514 /// use infinitable::*;
515 ///
516 /// let infinity: Infinitable<i32> = Infinity;
517 /// let _ = infinity * Finite(0);
518 /// ```
519 ///
520 /// # Panics
521 ///
522 /// Panics if one of the operands is `Infinity` or `NegativeInfinity` and
523 /// the other is a `Finite` value with an underlying value equal to or
524 /// unordered with zero.
525 ///
526 /// # Versioning
527 ///
528 /// Available since 1.5.0.
529 fn mul(self, rhs: Infinitable<T>) -> Infinitable<<T as Mul>::Output> {
530 match (self, rhs) {
531 (Infinity, Infinity) | (NegativeInfinity, NegativeInfinity) => Infinity,
532 (Infinity, NegativeInfinity) | (NegativeInfinity, Infinity) => NegativeInfinity,
533 (Infinity, Finite(x)) | (Finite(x), Infinity) => match x.partial_cmp(&T::zero()) {
534 Some(Ordering::Greater) => Infinity,
535 Some(Ordering::Less) => NegativeInfinity,
536 _ => panic!("Cannot multiply infinite value and zero or unordered value"),
537 },
538 (NegativeInfinity, Finite(x)) | (Finite(x), NegativeInfinity) => {
539 match x.partial_cmp(&T::zero()) {
540 Some(Ordering::Greater) => NegativeInfinity,
541 Some(Ordering::Less) => Infinity,
542 _ => panic!("Cannot multiply infinite value and zero or unordered value"),
543 }
544 }
545 (Finite(lf), Finite(rf)) => Finite(lf.mul(rf)),
546 }
547 }
548}
549
550impl<T> Div for Infinitable<T>
551where
552 T: Div + Zero + PartialOrd,
553 <T as Div>::Output: Zero,
554{
555 type Output = Infinitable<<T as Div>::Output>;
556
557 /// Divides two values.
558 ///
559 /// The division operation follows these rules:
560 ///
561 /// | self | rhs | result |
562 /// |--------------------|--------------------|----------------------------|
563 /// | `Finite` (> 0) | `Finite` (~ 0) | `Infinity` |
564 /// | `Finite` (~ 0) | `Finite` (~ 0) | Undefined (panic) |
565 /// | `Finite` (< 0) | `Finite` (~ 0) | `NegativeInfinity` |
566 /// | `Finite` | `Finite` (<> 0) | `Finite` (divide values) |
567 /// | `Finite` | `Infinity` | Zero |
568 /// | `Finite` | `NegativeInfinity` | Zero |
569 /// | `Infinity` | `Finite` (> 0) | `Infinity` |
570 /// | `Infinity` | `Finite` (~ 0) | `Infinity` |
571 /// | `Infinity` | `Finite` (< 0) | `NegativeInfinity` |
572 /// | `Infinity` | `Infinity` | Undefined (panic) |
573 /// | `Infinity` | `NegativeInfinity` | Undefined (panic) |
574 /// | `NegativeInfinity` | `Finite` (> 0) | `NegativeInfinity` |
575 /// | `NegativeInfinity` | `Finite` (~ 0) | `NegativeInfinity` |
576 /// | `NegativeInfinity` | `Finite` (< 0) | `Infinity` |
577 /// | `NegativeInfinity` | `Infinity` | Undefined (panic) |
578 /// | `NegativeInfinity` | `NegativeInfinity` | Undefined (panic) |
579 ///
580 /// (In the table, "~ 0" refers to a value that is either equal to or
581 /// unordered with zero, and "<> 0" refers to a value that is either
582 /// greater than or less than zero.)
583 ///
584 /// # Examples
585 ///
586 /// ```
587 /// use infinitable::*;
588 ///
589 /// assert_eq!(Finite(3), Finite(6) / Finite(2));
590 /// assert_eq!(Infinity, Infinity / Finite(1));
591 /// assert_eq!(Infinity, NegativeInfinity / Finite(-2));
592 /// assert_eq!(NegativeInfinity, NegativeInfinity / Finite(1));
593 /// assert_eq!(NegativeInfinity, Infinity / Finite(-2));
594 /// assert_eq!(Finite(0), Finite(1) / Infinity);
595 /// assert_eq!(Finite(0), Finite(1) / NegativeInfinity);
596 /// ```
597 ///
598 /// The division operation panics when an infinite value is divided by
599 /// another infinite value, or when zero is divided by itself:
600 ///
601 /// ```should_panic
602 /// use infinitable::*;
603 ///
604 /// let infinity: Infinitable<i32> = Infinity;
605 /// let _ = infinity / infinity;
606 /// ```
607 ///
608 /// ```should_panic
609 /// use infinitable::*;
610 ///
611 /// let _ = Finite(0) / Finite(0);
612 /// ```
613 ///
614 /// # Panics
615 ///
616 /// Panics if both operands are either `Infinity` or `NegativeInfinity`, or
617 /// both operands are `Finite` with an underlying value equal to or
618 /// unordered with zero.
619 ///
620 /// # Versioning
621 ///
622 /// Available since 1.5.0.
623 fn div(self, rhs: Infinitable<T>) -> Infinitable<<T as Div>::Output> {
624 match (self, rhs) {
625 (Infinity, Infinity)
626 | (NegativeInfinity, NegativeInfinity)
627 | (Infinity, NegativeInfinity)
628 | (NegativeInfinity, Infinity) => panic!("Cannot divide two infinite values"),
629 (Infinity, Finite(x)) => match x.partial_cmp(&T::zero()) {
630 Some(Ordering::Less) => NegativeInfinity,
631 _ => Infinity,
632 },
633 (NegativeInfinity, Finite(x)) => match x.partial_cmp(&T::zero()) {
634 Some(Ordering::Less) => Infinity,
635 _ => NegativeInfinity,
636 },
637 (Finite(_), Infinity) | (Finite(_), NegativeInfinity) => {
638 Finite(<T as Div>::Output::zero())
639 }
640 (Finite(lf), Finite(rf)) => match rf.partial_cmp(&T::zero()) {
641 Some(Ordering::Greater) | Some(Ordering::Less) => Finite(lf.div(rf)),
642 _ => match lf.partial_cmp(&T::zero()) {
643 Some(Ordering::Greater) => Infinity,
644 Some(Ordering::Less) => NegativeInfinity,
645 _ => panic!("Cannot divide two zeros or unordered values"),
646 },
647 },
648 }
649 }
650}
651
652impl<T> Neg for Infinitable<T>
653where
654 T: Neg,
655{
656 type Output = Infinitable<T::Output>;
657
658 /// Negates the value, when the underlying type `T` supports negation.
659 ///
660 /// [`Infinity`] is negated to [`NegativeInfinity`] (and vice versa),
661 /// and [`Finite`] is negated based on the underlying value.
662 ///
663 /// # Examples
664 ///
665 /// ```
666 /// use infinitable::*;
667 ///
668 /// let finite = Finite(5);
669 /// assert_eq!(Finite(-5), -finite);
670 /// let infinity: Infinitable<i32> = Infinity;
671 /// assert_eq!(NegativeInfinity, -infinity);
672 /// let negative_infinity: Infinitable<i32> = NegativeInfinity;
673 /// assert_eq!(Infinity, -negative_infinity);
674 /// ```
675 ///
676 /// # Versioning
677 ///
678 /// Available since 1.3.0.
679 fn neg(self) -> Infinitable<T::Output> {
680 match self {
681 Finite(x) => Finite(-x),
682 Infinity => NegativeInfinity,
683 NegativeInfinity => Infinity,
684 }
685 }
686}
687
688impl<T> Display for Infinitable<T>
689where
690 T: Display,
691{
692 /// Formats the value, when the underlying type `T` supports formatting.
693 ///
694 /// [`Infinity`] is formatted to `"inf"`, [`NegativeInfinity`] is formatted
695 /// to `"-inf"`, and [`Finite`] is formatted based on the underlying value.
696 ///
697 /// # Examples
698 ///
699 /// ```
700 /// use infinitable::*;
701 ///
702 /// let finite = Finite(5);
703 /// assert_eq!("5", format!("{}", finite));
704 /// let infinity: Infinitable<i32> = Infinity;
705 /// assert_eq!("inf", format!("{}", infinity));
706 /// let negative_infinity: Infinitable<i32> = NegativeInfinity;
707 /// assert_eq!("-inf", format!("{}", negative_infinity));
708 /// ```
709 ///
710 /// # Versioning
711 ///
712 /// Available since 1.2.0.
713 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
714 match self {
715 Finite(x) => write!(f, "{}", x),
716 Infinity => write!(f, "inf"),
717 NegativeInfinity => write!(f, "-inf"),
718 }
719 }
720}
721
722/// Converts from [`f32`] value to an optional [`Infinitable<f32>`],
723/// accounting for floating-point infinities and NaN.
724///
725/// The value is converted as follows:
726///
727/// | value | result |
728/// |-------------------|------------------------------------------|
729/// | Finite value `x` | <code>[Some]\([Finite]\(x))</code> |
730/// | Positive infinity | <code>[Some]\([Infinity])</code> |
731/// | Negative infinity | <code>[Some]\([NegativeInfinity])</code> |
732/// | NaN | [`None`] |
733///
734/// # Examples
735///
736/// ```
737/// use infinitable::*;
738///
739/// let finite = from_f32(5.0);
740/// assert_eq!(Some(Finite(5.0)), finite);
741/// let infinity = from_f32(f32::INFINITY);
742/// assert_eq!(Some(Infinity), infinity);
743/// let nan = from_f32(f32::NAN);
744/// assert_eq!(None, nan);
745/// ```
746///
747/// # Versioning
748///
749/// Available since 1.5.0.
750pub fn from_f32(value: f32) -> Option<Infinitable<f32>> {
751 if value.is_finite() {
752 Some(Finite(value))
753 } else if value.is_nan() {
754 None
755 } else if value.is_sign_positive() {
756 Some(Infinity)
757 } else {
758 Some(NegativeInfinity)
759 }
760}
761
762/// Converts from [`f64`] value to an optional [`Infinitable<f64>`],
763/// accounting for floating-point infinities and NaN.
764///
765/// The value is converted as follows:
766///
767/// | value | result |
768/// |-------------------|------------------------------------------|
769/// | Finite value `x` | <code>[Some]\([Finite]\(x))</code> |
770/// | Positive infinity | <code>[Some]\([Infinity])</code> |
771/// | Negative infinity | <code>[Some]\([NegativeInfinity])</code> |
772/// | NaN | [`None`] |
773///
774/// # Examples
775///
776/// ```
777/// use infinitable::*;
778///
779/// let finite = from_f64(5.0);
780/// assert_eq!(Some(Finite(5.0)), finite);
781/// let infinity = from_f64(f64::INFINITY);
782/// assert_eq!(Some(Infinity), infinity);
783/// let nan = from_f64(f64::NAN);
784/// assert_eq!(None, nan);
785/// ```
786///
787/// # Versioning
788///
789/// Available since 1.5.0.
790pub fn from_f64(value: f64) -> Option<Infinitable<f64>> {
791 if value.is_finite() {
792 Some(Finite(value))
793 } else if value.is_nan() {
794 None
795 } else if value.is_sign_positive() {
796 Some(Infinity)
797 } else {
798 Some(NegativeInfinity)
799 }
800}