1use core::num::FpCategory;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum NumberCategory {
8 Nan,
10 Infinite,
12 Zero,
14 Subnormal,
16 Normal,
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum NumberSign {
23 Negative,
25 Zero,
27 Positive,
29}
30
31#[must_use]
33pub const fn classify_number(value: f64) -> NumberCategory {
34 match value.classify() {
35 FpCategory::Nan => NumberCategory::Nan,
36 FpCategory::Infinite => NumberCategory::Infinite,
37 FpCategory::Zero => NumberCategory::Zero,
38 FpCategory::Subnormal => NumberCategory::Subnormal,
39 FpCategory::Normal => NumberCategory::Normal,
40 }
41}
42
43#[must_use]
45pub const fn classify_number_sign(value: f64) -> Option<NumberSign> {
46 if value.is_nan() {
47 None
48 } else if matches!(value.classify(), FpCategory::Zero) {
49 Some(NumberSign::Zero)
50 } else if value.is_sign_negative() {
51 Some(NumberSign::Negative)
52 } else {
53 Some(NumberSign::Positive)
54 }
55}
56
57#[must_use]
59pub const fn is_finite_number(value: f64) -> bool {
60 value.is_finite()
61}
62
63#[cfg(test)]
64mod tests {
65 use super::{
66 NumberCategory, NumberSign, classify_number, classify_number_sign, is_finite_number,
67 };
68
69 #[test]
70 fn classifies_floating_point_categories() {
71 assert_eq!(classify_number(f64::NAN), NumberCategory::Nan);
72 assert_eq!(classify_number(f64::INFINITY), NumberCategory::Infinite);
73 assert_eq!(classify_number(0.0), NumberCategory::Zero);
74 assert_eq!(
75 classify_number(f64::from_bits(1)),
76 NumberCategory::Subnormal
77 );
78 assert_eq!(classify_number(-4.0), NumberCategory::Normal);
79 }
80
81 #[test]
82 fn classifies_signs_without_hiding_nan() {
83 assert_eq!(classify_number_sign(-12.0), Some(NumberSign::Negative));
84 assert_eq!(classify_number_sign(-0.0), Some(NumberSign::Zero));
85 assert_eq!(classify_number_sign(18.0), Some(NumberSign::Positive));
86 assert_eq!(classify_number_sign(f64::NAN), None);
87 }
88
89 #[test]
90 fn reports_finiteness() {
91 assert!(is_finite_number(1.25));
92 assert!(!is_finite_number(f64::NEG_INFINITY));
93 assert!(!is_finite_number(f64::NAN));
94 }
95}