xref: /openbmc/linux/arch/mips/math-emu/dp_fmin.c (revision a61127c2)
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 		/* fall through */
100 
101 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
102 		DPDNORMY;
103 		break;
104 
105 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
106 		DPDNORMX;
107 	}
108 
109 	/* Finally get to do some computation */
110 
111 	assert(xm & DP_HIDDEN_BIT);
112 	assert(ym & DP_HIDDEN_BIT);
113 
114 	/* Compare signs */
115 	if (xs > ys)
116 		return x;
117 	else if (xs < ys)
118 		return y;
119 
120 	/* Signs of inputs are the same, let's compare exponents */
121 	if (xs == 0) {
122 		/* Inputs are both positive */
123 		if (xe > ye)
124 			return y;
125 		else if (xe < ye)
126 			return x;
127 	} else {
128 		/* Inputs are both negative */
129 		if (xe > ye)
130 			return x;
131 		else if (xe < ye)
132 			return y;
133 	}
134 
135 	/* Signs and exponents of inputs are equal, let's compare mantissas */
136 	if (xs == 0) {
137 		/* Inputs are both positive, with equal signs and exponents */
138 		if (xm <= ym)
139 			return x;
140 		return y;
141 	}
142 	/* Inputs are both negative, with equal signs and exponents */
143 	if (xm <= ym)
144 		return y;
145 	return x;
146 }
147 
148 union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y)
149 {
150 	COMPXDP;
151 	COMPYDP;
152 
153 	EXPLODEXDP;
154 	EXPLODEYDP;
155 
156 	FLUSHXDP;
157 	FLUSHYDP;
158 
159 	ieee754_clearcx();
160 
161 	switch (CLPAIR(xc, yc)) {
162 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
163 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
164 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
165 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
166 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
167 		return ieee754dp_nanxcpt(y);
168 
169 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
170 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
171 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
172 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
173 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
174 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
175 		return ieee754dp_nanxcpt(x);
176 
177 	/*
178 	 * Quiet NaN handling
179 	 */
180 
181 	/*
182 	 *    The case of both inputs quiet NaNs
183 	 */
184 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
185 		return x;
186 
187 	/*
188 	 *    The cases of exactly one input quiet NaN (numbers
189 	 *    are here preferred as returned values to NaNs)
190 	 */
191 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
192 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
193 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
194 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
195 		return x;
196 
197 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
198 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
199 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
200 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
201 		return y;
202 
203 	/*
204 	 * Infinity and zero handling
205 	 */
206 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
207 		return ieee754dp_inf(xs | ys);
208 
209 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
210 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
211 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
212 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
213 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
214 		return y;
215 
216 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
217 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
218 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
219 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
220 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
221 		return x;
222 
223 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
224 		return ieee754dp_zero(xs | ys);
225 
226 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
227 		DPDNORMX;
228 		/* fall through */
229 
230 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
231 		DPDNORMY;
232 		break;
233 
234 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
235 		DPDNORMX;
236 	}
237 
238 	/* Finally get to do some computation */
239 
240 	assert(xm & DP_HIDDEN_BIT);
241 	assert(ym & DP_HIDDEN_BIT);
242 
243 	/* Compare exponent */
244 	if (xe > ye)
245 		return y;
246 	else if (xe < ye)
247 		return x;
248 
249 	/* Compare mantissa */
250 	if (xm < ym)
251 		return x;
252 	else if (xm > ym)
253 		return y;
254 	else if (xs == 1)
255 		return x;
256 	return y;
257 }
258