xref: /openbmc/linux/arch/mips/math-emu/dp_fmin.c (revision d8bcaabe)
1 /*
2  * IEEE754 floating point arithmetic
3  * double precision: MIN{,A}.f
4  * MIN : Scalar Floating-Point Minimum
5  * MINA: Scalar Floating-Point argument with Minimum Absolute Value
6  *
7  * MIN.D : FPR[fd] = minNum(FPR[fs],FPR[ft])
8  * MINA.D: FPR[fd] = maxNumMag(FPR[fs],FPR[ft])
9  *
10  * MIPS floating point support
11  * Copyright (C) 2015 Imagination Technologies, Ltd.
12  * Author: Markos Chandras <markos.chandras@imgtec.com>
13  *
14  *  This program is free software; you can distribute it and/or modify it
15  *  under the terms of the GNU General Public License as published by the
16  *  Free Software Foundation; version 2 of the License.
17  */
18 
19 #include "ieee754dp.h"
20 
21 union ieee754dp ieee754dp_fmin(union ieee754dp x, union ieee754dp y)
22 {
23 	COMPXDP;
24 	COMPYDP;
25 
26 	EXPLODEXDP;
27 	EXPLODEYDP;
28 
29 	FLUSHXDP;
30 	FLUSHYDP;
31 
32 	ieee754_clearcx();
33 
34 	switch (CLPAIR(xc, yc)) {
35 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
36 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
37 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
38 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
39 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
40 		return ieee754dp_nanxcpt(y);
41 
42 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
43 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
44 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
45 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
46 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
47 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
48 		return ieee754dp_nanxcpt(x);
49 
50 	/*
51 	 * Quiet NaN handling
52 	 */
53 
54 	/*
55 	 *    The case of both inputs quiet NaNs
56 	 */
57 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
58 		return x;
59 
60 	/*
61 	 *    The cases of exactly one input quiet NaN (numbers
62 	 *    are here preferred as returned values to NaNs)
63 	 */
64 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
65 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
66 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
67 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
68 		return x;
69 
70 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
71 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
72 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
73 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
74 		return y;
75 
76 	/*
77 	 * Infinity and zero handling
78 	 */
79 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
80 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
81 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
82 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
83 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
84 		return xs ? x : y;
85 
86 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
87 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
88 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
89 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
90 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
91 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
92 		return ys ? y : x;
93 
94 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
95 		return ieee754dp_zero(xs | ys);
96 
97 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
98 		DPDNORMX;
99 
100 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
101 		DPDNORMY;
102 		break;
103 
104 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
105 		DPDNORMX;
106 	}
107 
108 	/* Finally get to do some computation */
109 
110 	assert(xm & DP_HIDDEN_BIT);
111 	assert(ym & DP_HIDDEN_BIT);
112 
113 	/* Compare signs */
114 	if (xs > ys)
115 		return x;
116 	else if (xs < ys)
117 		return y;
118 
119 	/* Signs of inputs are the same, let's compare exponents */
120 	if (xs == 0) {
121 		/* Inputs are both positive */
122 		if (xe > ye)
123 			return y;
124 		else if (xe < ye)
125 			return x;
126 	} else {
127 		/* Inputs are both negative */
128 		if (xe > ye)
129 			return x;
130 		else if (xe < ye)
131 			return y;
132 	}
133 
134 	/* Signs and exponents of inputs are equal, let's compare mantissas */
135 	if (xs == 0) {
136 		/* Inputs are both positive, with equal signs and exponents */
137 		if (xm <= ym)
138 			return x;
139 		return y;
140 	}
141 	/* Inputs are both negative, with equal signs and exponents */
142 	if (xm <= ym)
143 		return y;
144 	return x;
145 }
146 
147 union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y)
148 {
149 	COMPXDP;
150 	COMPYDP;
151 
152 	EXPLODEXDP;
153 	EXPLODEYDP;
154 
155 	FLUSHXDP;
156 	FLUSHYDP;
157 
158 	ieee754_clearcx();
159 
160 	switch (CLPAIR(xc, yc)) {
161 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
162 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
163 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
164 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
165 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
166 		return ieee754dp_nanxcpt(y);
167 
168 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
169 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
170 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
171 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
172 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
173 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
174 		return ieee754dp_nanxcpt(x);
175 
176 	/*
177 	 * Quiet NaN handling
178 	 */
179 
180 	/*
181 	 *    The case of both inputs quiet NaNs
182 	 */
183 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
184 		return x;
185 
186 	/*
187 	 *    The cases of exactly one input quiet NaN (numbers
188 	 *    are here preferred as returned values to NaNs)
189 	 */
190 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
191 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
192 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
193 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
194 		return x;
195 
196 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
197 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
198 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
199 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
200 		return y;
201 
202 	/*
203 	 * Infinity and zero handling
204 	 */
205 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
206 		return ieee754dp_inf(xs | ys);
207 
208 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
209 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
210 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
211 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
212 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
213 		return y;
214 
215 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
216 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
217 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
218 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
219 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
220 		return x;
221 
222 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
223 		return ieee754dp_zero(xs | ys);
224 
225 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
226 		DPDNORMX;
227 
228 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
229 		DPDNORMY;
230 		break;
231 
232 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
233 		DPDNORMX;
234 	}
235 
236 	/* Finally get to do some computation */
237 
238 	assert(xm & DP_HIDDEN_BIT);
239 	assert(ym & DP_HIDDEN_BIT);
240 
241 	/* Compare exponent */
242 	if (xe > ye)
243 		return y;
244 	else if (xe < ye)
245 		return x;
246 
247 	/* Compare mantissa */
248 	if (xm < ym)
249 		return x;
250 	else if (xm > ym)
251 		return y;
252 	else if (xs == 1)
253 		return x;
254 	return y;
255 }
256