machina_softfloat/ops/
compare.rs1use core::cmp::Ordering;
5
6use crate::env::{ExcFlags, FloatEnv};
7use crate::parts::{unpack, FloatClass};
8use crate::types::{
9 BFloat16, Float128, Float16, Float32, Float64, FloatFormat, FloatX80,
10};
11
12pub fn compare<F: FloatFormat>(
15 a: F,
16 b: F,
17 env: &mut FloatEnv,
18) -> Option<Ordering> {
19 let pa = unpack::<F>(a);
20 let pb = unpack::<F>(b);
21
22 if pa.is_nan() || pb.is_nan() {
23 env.raise(ExcFlags::INVALID);
24 return None;
25 }
26
27 compare_ordered(&pa, &pb)
28}
29
30pub fn compare_quiet<F: FloatFormat>(
33 a: F,
34 b: F,
35 env: &mut FloatEnv,
36) -> Option<Ordering> {
37 let pa = unpack::<F>(a);
38 let pb = unpack::<F>(b);
39
40 if pa.is_nan() || pb.is_nan() {
41 if pa.cls == FloatClass::SNaN || pb.cls == FloatClass::SNaN {
42 env.raise(ExcFlags::INVALID);
43 }
44 return None;
45 }
46
47 compare_ordered(&pa, &pb)
48}
49
50fn compare_ordered(
51 a: &crate::parts::FloatParts,
52 b: &crate::parts::FloatParts,
53) -> Option<Ordering> {
54 if a.cls == FloatClass::Zero && b.cls == FloatClass::Zero {
56 return Some(Ordering::Equal);
57 }
58
59 if a.sign != b.sign {
61 return if a.sign {
63 Some(Ordering::Less)
64 } else {
65 Some(Ordering::Greater)
66 };
67 }
68
69 let raw_ord = if a.cls == FloatClass::Inf && b.cls == FloatClass::Inf {
71 Ordering::Equal
72 } else if a.cls == FloatClass::Inf {
73 Ordering::Greater
74 } else if b.cls == FloatClass::Inf {
75 Ordering::Less
76 } else if a.cls == FloatClass::Zero {
77 Ordering::Less
79 } else if b.cls == FloatClass::Zero {
80 Ordering::Greater
81 } else {
82 match a.exp.cmp(&b.exp) {
84 Ordering::Equal => a.frac.cmp(&b.frac),
85 other => other,
86 }
87 };
88
89 if a.sign {
91 Some(raw_ord.reverse())
92 } else {
93 Some(raw_ord)
94 }
95}
96
97pub fn eq<F: FloatFormat>(a: F, b: F, env: &mut FloatEnv) -> bool {
99 compare_quiet::<F>(a, b, env) == Some(Ordering::Equal)
100}
101
102pub fn lt<F: FloatFormat>(a: F, b: F, env: &mut FloatEnv) -> bool {
104 compare::<F>(a, b, env) == Some(Ordering::Less)
105}
106
107pub fn le<F: FloatFormat>(a: F, b: F, env: &mut FloatEnv) -> bool {
109 matches!(
110 compare::<F>(a, b, env),
111 Some(Ordering::Less) | Some(Ordering::Equal)
112 )
113}
114
115macro_rules! impl_compare {
120 ($ty:ty) => {
121 impl $ty {
122 pub fn compare(
123 self,
124 other: Self,
125 env: &mut FloatEnv,
126 ) -> Option<Ordering> {
127 compare::<Self>(self, other, env)
128 }
129 pub fn compare_quiet(
130 self,
131 other: Self,
132 env: &mut FloatEnv,
133 ) -> Option<Ordering> {
134 compare_quiet::<Self>(self, other, env)
135 }
136 pub fn eq(self, other: Self, env: &mut FloatEnv) -> bool {
137 eq::<Self>(self, other, env)
138 }
139 pub fn lt(self, other: Self, env: &mut FloatEnv) -> bool {
140 lt::<Self>(self, other, env)
141 }
142 pub fn le(self, other: Self, env: &mut FloatEnv) -> bool {
143 le::<Self>(self, other, env)
144 }
145 }
146 };
147}
148
149impl_compare!(Float16);
150impl_compare!(BFloat16);
151impl_compare!(Float32);
152impl_compare!(Float64);
153impl_compare!(Float128);
154impl_compare!(FloatX80);