machina_softfloat/ops/
minmax.rs1use crate::env::{ExcFlags, FloatEnv};
5use crate::parts::{nan_propagate, round_pack, unpack, FloatClass};
6use crate::types::{
7 BFloat16, Float128, Float16, Float32, Float64, FloatFormat, FloatX80,
8};
9
10pub fn min<F: FloatFormat>(a: F, b: F, env: &mut FloatEnv) -> F {
15 let pa = unpack::<F>(a);
16 let pb = unpack::<F>(b);
17
18 if pa.cls == FloatClass::SNaN || pb.cls == FloatClass::SNaN {
20 env.raise(ExcFlags::INVALID);
21 }
22
23 if pa.is_nan() && pb.is_nan() {
24 let mut r = nan_propagate(&pa, &pb, env);
25 return round_pack::<F>(&mut r, env);
26 }
27
28 if pa.is_nan() {
29 return b;
30 }
31 if pb.is_nan() {
32 return a;
33 }
34
35 if pa.cls == FloatClass::Zero && pb.cls == FloatClass::Zero {
37 return if pb.sign { b } else { a };
38 }
39
40 let a_lt_b = if pa.sign != pb.sign {
42 pa.sign } else if pa.sign {
44 if pa.exp != pb.exp {
46 pa.exp > pb.exp
47 } else {
48 pa.frac > pb.frac
49 }
50 } else {
51 if pa.exp != pb.exp {
53 pa.exp < pb.exp
54 } else {
55 pa.frac < pb.frac
56 }
57 };
58
59 if a_lt_b {
60 a
61 } else {
62 b
63 }
64}
65
66pub fn max<F: FloatFormat>(a: F, b: F, env: &mut FloatEnv) -> F {
71 let pa = unpack::<F>(a);
72 let pb = unpack::<F>(b);
73
74 if pa.cls == FloatClass::SNaN || pb.cls == FloatClass::SNaN {
75 env.raise(ExcFlags::INVALID);
76 }
77
78 if pa.is_nan() && pb.is_nan() {
79 let mut r = nan_propagate(&pa, &pb, env);
80 return round_pack::<F>(&mut r, env);
81 }
82
83 if pa.is_nan() {
84 return b;
85 }
86 if pb.is_nan() {
87 return a;
88 }
89
90 if pa.cls == FloatClass::Zero && pb.cls == FloatClass::Zero {
92 return if pa.sign { b } else { a };
93 }
94
95 let a_gt_b = if pa.sign != pb.sign {
96 pb.sign } else if pa.sign {
98 if pa.exp != pb.exp {
100 pa.exp < pb.exp
101 } else {
102 pa.frac < pb.frac
103 }
104 } else {
105 if pa.exp != pb.exp {
107 pa.exp > pb.exp
108 } else {
109 pa.frac > pb.frac
110 }
111 };
112
113 if a_gt_b {
114 a
115 } else {
116 b
117 }
118}
119
120macro_rules! impl_minmax {
125 ($ty:ty) => {
126 impl $ty {
127 pub fn min(self, other: Self, env: &mut FloatEnv) -> Self {
128 min::<Self>(self, other, env)
129 }
130 pub fn max(self, other: Self, env: &mut FloatEnv) -> Self {
131 max::<Self>(self, other, env)
132 }
133 }
134 };
135}
136
137impl_minmax!(Float16);
138impl_minmax!(BFloat16);
139impl_minmax!(Float32);
140impl_minmax!(Float64);
141impl_minmax!(Float128);
142impl_minmax!(FloatX80);