Mercurial > hg > CbC > CbC_gcc
comparison libgcc/config/libbid/bid128_minmax.c @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 04ced10e8804 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 /* Copyright (C) 2007, 2009 Free Software Foundation, Inc. | |
2 | |
3 This file is part of GCC. | |
4 | |
5 GCC is free software; you can redistribute it and/or modify it under | |
6 the terms of the GNU General Public License as published by the Free | |
7 Software Foundation; either version 3, or (at your option) any later | |
8 version. | |
9 | |
10 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
13 for more details. | |
14 | |
15 Under Section 7 of GPL version 3, you are granted additional | |
16 permissions described in the GCC Runtime Library Exception, version | |
17 3.1, as published by the Free Software Foundation. | |
18 | |
19 You should have received a copy of the GNU General Public License and | |
20 a copy of the GCC Runtime Library Exception along with this program; | |
21 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
22 <http://www.gnu.org/licenses/>. */ | |
23 | |
24 #define BID_128RES | |
25 #include "bid_internal.h" | |
26 | |
27 /***************************************************************************** | |
28 * BID128 minimum number | |
29 *****************************************************************************/ | |
30 | |
31 #if DECIMAL_CALL_BY_REFERENCE | |
32 void | |
33 bid128_minnum (UINT128 * pres, UINT128 * px, | |
34 UINT128 * py _EXC_FLAGS_PARAM) { | |
35 UINT128 x = *px; | |
36 UINT128 y = *py; | |
37 #else | |
38 UINT128 | |
39 bid128_minnum (UINT128 x, UINT128 y _EXC_FLAGS_PARAM) { | |
40 #endif | |
41 | |
42 UINT128 res; | |
43 int exp_x, exp_y; | |
44 int diff; | |
45 UINT128 sig_x, sig_y; | |
46 UINT192 sig_n_prime192; | |
47 UINT256 sig_n_prime256; | |
48 char x_is_zero = 0, y_is_zero = 0; | |
49 | |
50 BID_SWAP128 (x); | |
51 BID_SWAP128 (y); | |
52 | |
53 // check for non-canonical x | |
54 if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN | |
55 x.w[1] = x.w[1] & 0xfe003fffffffffffull; // clear out G[6]-G[16] | |
56 // check for non-canonical NaN payload | |
57 if (((x.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) || | |
58 (((x.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull) && | |
59 (x.w[0] > 0x38c15b09ffffffffull))) { | |
60 x.w[1] = x.w[1] & 0xffffc00000000000ull; | |
61 x.w[0] = 0x0ull; | |
62 } | |
63 } else if ((x.w[1] & MASK_ANY_INF) == MASK_INF) { // x = inf | |
64 x.w[1] = x.w[1] & (MASK_SIGN | MASK_INF); | |
65 x.w[0] = 0x0ull; | |
66 } else { // x is not special | |
67 // check for non-canonical values - treated as zero | |
68 if ((x.w[1] & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // G0_G1=11 | |
69 // non-canonical | |
70 x.w[1] = (x.w[1] & MASK_SIGN) | ((x.w[1] << 2) & MASK_EXP); | |
71 x.w[0] = 0x0ull; | |
72 } else { // G0_G1 != 11 | |
73 if ((x.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull || | |
74 ((x.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull | |
75 && x.w[0] > 0x378d8e63ffffffffull)) { | |
76 // x is non-canonical if coefficient is larger than 10^34 -1 | |
77 x.w[1] = (x.w[1] & MASK_SIGN) | (x.w[1] & MASK_EXP); | |
78 x.w[0] = 0x0ull; | |
79 } else { // canonical | |
80 ; | |
81 } | |
82 } | |
83 } | |
84 // check for non-canonical y | |
85 if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NAN | |
86 y.w[1] = y.w[1] & 0xfe003fffffffffffull; // clear out G[6]-G[16] | |
87 // check for non-canonical NaN payload | |
88 if (((y.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) || | |
89 (((y.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull) && | |
90 (y.w[0] > 0x38c15b09ffffffffull))) { | |
91 y.w[1] = y.w[1] & 0xffffc00000000000ull; | |
92 y.w[0] = 0x0ull; | |
93 } | |
94 } else if ((y.w[1] & MASK_ANY_INF) == MASK_INF) { // y = inf | |
95 y.w[1] = y.w[1] & (MASK_SIGN | MASK_INF); | |
96 y.w[0] = 0x0ull; | |
97 } else { // y is not special | |
98 // check for non-canonical values - treated as zero | |
99 if ((y.w[1] & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // G0_G1=11 | |
100 // non-canonical | |
101 y.w[1] = (y.w[1] & MASK_SIGN) | ((y.w[1] << 2) & MASK_EXP); | |
102 y.w[0] = 0x0ull; | |
103 } else { // G0_G1 != 11 | |
104 if ((y.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull || | |
105 ((y.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull | |
106 && y.w[0] > 0x378d8e63ffffffffull)) { | |
107 // y is non-canonical if coefficient is larger than 10^34 -1 | |
108 y.w[1] = (y.w[1] & MASK_SIGN) | (y.w[1] & MASK_EXP); | |
109 y.w[0] = 0x0ull; | |
110 } else { // canonical | |
111 ; | |
112 } | |
113 } | |
114 } | |
115 | |
116 // NaN (CASE1) | |
117 if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN | |
118 if ((x.w[1] & MASK_SNAN) == MASK_SNAN) { // x is SNaN | |
119 // if x is SNAN, then return quiet (x) | |
120 *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN | |
121 x.w[1] = x.w[1] & 0xfdffffffffffffffull; // quietize x | |
122 res = x; | |
123 } else { // x is QNaN | |
124 if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NAN | |
125 if ((y.w[1] & MASK_SNAN) == MASK_SNAN) { // y is SNAN | |
126 *pfpsf |= INVALID_EXCEPTION; // set invalid flag | |
127 } | |
128 res = x; | |
129 } else { | |
130 res = y; | |
131 } | |
132 } | |
133 BID_RETURN (res); | |
134 } else if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NaN, but x is not | |
135 if ((y.w[1] & MASK_SNAN) == MASK_SNAN) { | |
136 *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN | |
137 y.w[1] = y.w[1] & 0xfdffffffffffffffull; // quietize y | |
138 res = y; | |
139 } else { | |
140 // will return x (which is not NaN) | |
141 res = x; | |
142 } | |
143 BID_RETURN (res); | |
144 } | |
145 // SIMPLE (CASE2) | |
146 // if all the bits are the same, these numbers are equal (not Greater). | |
147 if (x.w[0] == y.w[0] && x.w[1] == y.w[1]) { | |
148 res = x; | |
149 BID_RETURN (res); | |
150 } | |
151 // INFINITY (CASE3) | |
152 if ((x.w[1] & MASK_INF) == MASK_INF) { | |
153 // if x is neg infinity, there is no way it is greater than y, return 0 | |
154 res = (((x.w[1] & MASK_SIGN) == MASK_SIGN)) ? x : y; | |
155 BID_RETURN (res); | |
156 } else if ((y.w[1] & MASK_INF) == MASK_INF) { | |
157 // x is finite, so if y is positive infinity, then x is less, return 0 | |
158 // if y is negative infinity, then x is greater, return 1 | |
159 res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x; | |
160 BID_RETURN (res); | |
161 } | |
162 // CONVERT X | |
163 sig_x.w[1] = x.w[1] & 0x0001ffffffffffffull; | |
164 sig_x.w[0] = x.w[0]; | |
165 exp_x = (x.w[1] >> 49) & 0x000000000003fffull; | |
166 | |
167 // CONVERT Y | |
168 exp_y = (y.w[1] >> 49) & 0x0000000000003fffull; | |
169 sig_y.w[1] = y.w[1] & 0x0001ffffffffffffull; | |
170 sig_y.w[0] = y.w[0]; | |
171 | |
172 // ZERO (CASE4) | |
173 // some properties: | |
174 // (+ZERO == -ZERO) => therefore ignore the sign | |
175 // (ZERO x 10^A == ZERO x 10^B) for any valid A, B => ignore the exponent | |
176 // field | |
177 // (Any non-canonical # is considered 0) | |
178 if ((sig_x.w[1] == 0) && (sig_x.w[0] == 0)) { | |
179 x_is_zero = 1; | |
180 } | |
181 if ((sig_y.w[1] == 0) && (sig_y.w[0] == 0)) { | |
182 y_is_zero = 1; | |
183 } | |
184 | |
185 if (x_is_zero && y_is_zero) { | |
186 // if both numbers are zero, neither is greater => return either number | |
187 res = x; | |
188 BID_RETURN (res); | |
189 } else if (x_is_zero) { | |
190 // is x is zero, it is greater if Y is negative | |
191 res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x; | |
192 BID_RETURN (res); | |
193 } else if (y_is_zero) { | |
194 // is y is zero, X is greater if it is positive | |
195 res = ((x.w[1] & MASK_SIGN) != MASK_SIGN) ? y : x; | |
196 BID_RETURN (res); | |
197 } | |
198 // OPPOSITE SIGN (CASE5) | |
199 // now, if the sign bits differ, x is greater if y is negative | |
200 if (((x.w[1] ^ y.w[1]) & MASK_SIGN) == MASK_SIGN) { | |
201 res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x; | |
202 BID_RETURN (res); | |
203 } | |
204 // REDUNDANT REPRESENTATIONS (CASE6) | |
205 // if exponents are the same, then we have a simple comparison of | |
206 // the significands | |
207 if (exp_y == exp_x) { | |
208 res = (((sig_x.w[1] > sig_y.w[1]) | |
209 || (sig_x.w[1] == sig_y.w[1] | |
210 && sig_x.w[0] >= sig_y.w[0])) ^ ((x.w[1] & MASK_SIGN) == | |
211 MASK_SIGN)) ? y : x; | |
212 BID_RETURN (res); | |
213 } | |
214 // if both components are either bigger or smaller, it is clear what | |
215 // needs to be done | |
216 if (sig_x.w[1] >= sig_y.w[1] && sig_x.w[0] >= sig_y.w[0] | |
217 && exp_x > exp_y) { | |
218 res = ((x.w[1] & MASK_SIGN) != MASK_SIGN) ? y : x; | |
219 BID_RETURN (res); | |
220 } | |
221 if (sig_x.w[1] <= sig_y.w[1] && sig_x.w[0] <= sig_y.w[0] | |
222 && exp_x < exp_y) { | |
223 res = ((x.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x; | |
224 BID_RETURN (res); | |
225 } | |
226 | |
227 diff = exp_x - exp_y; | |
228 | |
229 // if |exp_x - exp_y| < 33, it comes down to the compensated significand | |
230 if (diff > 0) { // to simplify the loop below, | |
231 // if exp_x is 33 greater than exp_y, no need for compensation | |
232 if (diff > 33) { | |
233 // difference cannot be greater than 10^33 | |
234 res = ((x.w[1] & MASK_SIGN) != MASK_SIGN) ? y : x; | |
235 BID_RETURN (res); | |
236 } | |
237 if (diff > 19) { //128 by 128 bit multiply -> 256 bits | |
238 __mul_128x128_to_256 (sig_n_prime256, sig_x, ten2k128[diff - 20]); | |
239 // if postitive, return whichever significand is larger | |
240 // (converse if negative) | |
241 res = ((((sig_n_prime256.w[3] > 0) || sig_n_prime256.w[2] > 0) | |
242 || (sig_n_prime256.w[1] > sig_y.w[1]) | |
243 || (sig_n_prime256.w[1] == sig_y.w[1] | |
244 && sig_n_prime256.w[0] > | |
245 sig_y.w[0])) ^ ((y.w[1] & MASK_SIGN) == | |
246 MASK_SIGN)) ? y : x; | |
247 BID_RETURN (res); | |
248 } | |
249 __mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_x); | |
250 // if postitive, return whichever significand is larger | |
251 // (converse if negative) | |
252 res = | |
253 (((sig_n_prime192.w[2] > 0) || (sig_n_prime192.w[1] > sig_y.w[1]) | |
254 || (sig_n_prime192.w[1] == sig_y.w[1] | |
255 && sig_n_prime192.w[0] > | |
256 sig_y.w[0])) ^ ((y.w[1] & MASK_SIGN) == MASK_SIGN)) ? y : x; | |
257 BID_RETURN (res); | |
258 } | |
259 diff = exp_y - exp_x; | |
260 // if exp_x is 33 less than exp_y, no need for compensation | |
261 if (diff > 33) { | |
262 res = ((x.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x; | |
263 BID_RETURN (res); | |
264 } | |
265 if (diff > 19) { //128 by 128 bit multiply -> 256 bits | |
266 // adjust the y significand upwards | |
267 __mul_128x128_to_256 (sig_n_prime256, sig_y, ten2k128[diff - 20]); | |
268 // if postitive, return whichever significand is larger | |
269 // (converse if negative) | |
270 res = | |
271 ((sig_n_prime256.w[3] != 0 || sig_n_prime256.w[2] != 0 | |
272 || (sig_n_prime256.w[1] > sig_x.w[1] | |
273 || (sig_n_prime256.w[1] == sig_x.w[1] | |
274 && sig_n_prime256.w[0] > | |
275 sig_x.w[0]))) ^ ((x.w[1] & MASK_SIGN) == | |
276 MASK_SIGN)) ? x : y; | |
277 BID_RETURN (res); | |
278 } | |
279 // adjust the y significand upwards | |
280 __mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_y); | |
281 // if postitive, return whichever significand is larger (converse if negative) | |
282 res = | |
283 ((sig_n_prime192.w[2] != 0 | |
284 || (sig_n_prime192.w[1] > sig_x.w[1] | |
285 || (sig_n_prime192.w[1] == sig_x.w[1] | |
286 && sig_n_prime192.w[0] > sig_x.w[0]))) | |
287 ^ ((y.w[1] & MASK_SIGN) == MASK_SIGN)) ? x : y; | |
288 BID_RETURN (res); | |
289 } | |
290 | |
291 /***************************************************************************** | |
292 * BID128 minimum magnitude function - returns greater of two numbers | |
293 *****************************************************************************/ | |
294 | |
295 #if DECIMAL_CALL_BY_REFERENCE | |
296 void | |
297 bid128_minnum_mag (UINT128 * pres, UINT128 * px, | |
298 UINT128 * py _EXC_FLAGS_PARAM) { | |
299 UINT128 x = *px; | |
300 UINT128 y = *py; | |
301 #else | |
302 UINT128 | |
303 bid128_minnum_mag (UINT128 x, UINT128 y _EXC_FLAGS_PARAM) { | |
304 #endif | |
305 | |
306 UINT128 res; | |
307 int exp_x, exp_y; | |
308 int diff; | |
309 UINT128 sig_x, sig_y; | |
310 UINT192 sig_n_prime192; | |
311 UINT256 sig_n_prime256; | |
312 | |
313 BID_SWAP128 (x); | |
314 BID_SWAP128 (y); | |
315 | |
316 // check for non-canonical x | |
317 if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN | |
318 x.w[1] = x.w[1] & 0xfe003fffffffffffull; // clear out G[6]-G[16] | |
319 // check for non-canonical NaN payload | |
320 if (((x.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) || | |
321 (((x.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull) && | |
322 (x.w[0] > 0x38c15b09ffffffffull))) { | |
323 x.w[1] = x.w[1] & 0xffffc00000000000ull; | |
324 x.w[0] = 0x0ull; | |
325 } | |
326 } else if ((x.w[1] & MASK_ANY_INF) == MASK_INF) { // x = inf | |
327 x.w[1] = x.w[1] & (MASK_SIGN | MASK_INF); | |
328 x.w[0] = 0x0ull; | |
329 } else { // x is not special | |
330 // check for non-canonical values - treated as zero | |
331 if ((x.w[1] & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // G0_G1=11 | |
332 // non-canonical | |
333 x.w[1] = (x.w[1] & MASK_SIGN) | ((x.w[1] << 2) & MASK_EXP); | |
334 x.w[0] = 0x0ull; | |
335 } else { // G0_G1 != 11 | |
336 if ((x.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull || | |
337 ((x.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull | |
338 && x.w[0] > 0x378d8e63ffffffffull)) { | |
339 // x is non-canonical if coefficient is larger than 10^34 -1 | |
340 x.w[1] = (x.w[1] & MASK_SIGN) | (x.w[1] & MASK_EXP); | |
341 x.w[0] = 0x0ull; | |
342 } else { // canonical | |
343 ; | |
344 } | |
345 } | |
346 } | |
347 // check for non-canonical y | |
348 if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NAN | |
349 y.w[1] = y.w[1] & 0xfe003fffffffffffull; // clear out G[6]-G[16] | |
350 // check for non-canonical NaN payload | |
351 if (((y.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) || | |
352 (((y.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull) && | |
353 (y.w[0] > 0x38c15b09ffffffffull))) { | |
354 y.w[1] = y.w[1] & 0xffffc00000000000ull; | |
355 y.w[0] = 0x0ull; | |
356 } | |
357 } else if ((y.w[1] & MASK_ANY_INF) == MASK_INF) { // y = inf | |
358 y.w[1] = y.w[1] & (MASK_SIGN | MASK_INF); | |
359 y.w[0] = 0x0ull; | |
360 } else { // y is not special | |
361 // check for non-canonical values - treated as zero | |
362 if ((y.w[1] & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // G0_G1=11 | |
363 // non-canonical | |
364 y.w[1] = (y.w[1] & MASK_SIGN) | ((y.w[1] << 2) & MASK_EXP); | |
365 y.w[0] = 0x0ull; | |
366 } else { // G0_G1 != 11 | |
367 if ((y.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull || | |
368 ((y.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull | |
369 && y.w[0] > 0x378d8e63ffffffffull)) { | |
370 // y is non-canonical if coefficient is larger than 10^34 -1 | |
371 y.w[1] = (y.w[1] & MASK_SIGN) | (y.w[1] & MASK_EXP); | |
372 y.w[0] = 0x0ull; | |
373 } else { // canonical | |
374 ; | |
375 } | |
376 } | |
377 } | |
378 | |
379 // NaN (CASE1) | |
380 if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN | |
381 if ((x.w[1] & MASK_SNAN) == MASK_SNAN) { // x is SNaN | |
382 // if x is SNAN, then return quiet (x) | |
383 *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN | |
384 x.w[1] = x.w[1] & 0xfdffffffffffffffull; // quietize x | |
385 res = x; | |
386 } else { // x is QNaN | |
387 if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NAN | |
388 if ((y.w[1] & MASK_SNAN) == MASK_SNAN) { // y is SNAN | |
389 *pfpsf |= INVALID_EXCEPTION; // set invalid flag | |
390 } | |
391 res = x; | |
392 } else { | |
393 res = y; | |
394 } | |
395 } | |
396 BID_RETURN (res); | |
397 } else if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NaN, but x is not | |
398 if ((y.w[1] & MASK_SNAN) == MASK_SNAN) { | |
399 *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN | |
400 y.w[1] = y.w[1] & 0xfdffffffffffffffull; // quietize y | |
401 res = y; | |
402 } else { | |
403 // will return x (which is not NaN) | |
404 res = x; | |
405 } | |
406 BID_RETURN (res); | |
407 } | |
408 // SIMPLE (CASE2) | |
409 // if all the bits are the same, these numbers are equal (not Greater). | |
410 if (x.w[0] == y.w[0] && x.w[1] == y.w[1]) { | |
411 res = y; | |
412 BID_RETURN (res); | |
413 } | |
414 // INFINITY (CASE3) | |
415 if ((x.w[1] & MASK_INF) == MASK_INF) { | |
416 // if x infinity, it has maximum magnitude. | |
417 // Check if magnitudes are equal. If x is negative, return it. | |
418 res = ((x.w[1] & MASK_SIGN) == MASK_SIGN | |
419 && (y.w[1] & MASK_INF) == MASK_INF) ? x : y; | |
420 BID_RETURN (res); | |
421 } else if ((y.w[1] & MASK_INF) == MASK_INF) { | |
422 // x is finite, so if y is infinity, then x is less in magnitude | |
423 res = x; | |
424 BID_RETURN (res); | |
425 } | |
426 // CONVERT X | |
427 sig_x.w[1] = x.w[1] & 0x0001ffffffffffffull; | |
428 sig_x.w[0] = x.w[0]; | |
429 exp_x = (x.w[1] >> 49) & 0x000000000003fffull; | |
430 | |
431 // CONVERT Y | |
432 exp_y = (y.w[1] >> 49) & 0x0000000000003fffull; | |
433 sig_y.w[1] = y.w[1] & 0x0001ffffffffffffull; | |
434 sig_y.w[0] = y.w[0]; | |
435 | |
436 // ZERO (CASE4) | |
437 // some properties: | |
438 // (+ZERO == -ZERO) => therefore ignore the sign | |
439 // (ZERO x 10^A == ZERO x 10^B) for any valid A, B => | |
440 // therefore ignore the exponent field | |
441 // (Any non-canonical # is considered 0) | |
442 if ((sig_x.w[1] == 0) && (sig_x.w[0] == 0)) { | |
443 res = x; | |
444 BID_RETURN (res); | |
445 } | |
446 if ((sig_y.w[1] == 0) && (sig_y.w[0] == 0)) { | |
447 res = y; | |
448 BID_RETURN (res); | |
449 } | |
450 // REDUNDANT REPRESENTATIONS (CASE6) | |
451 // check if exponents are the same and significands are the same | |
452 if (exp_y == exp_x && sig_x.w[1] == sig_y.w[1] | |
453 && sig_x.w[0] == sig_y.w[0]) { | |
454 if (x.w[1] & 0x8000000000000000ull) { // x is negative | |
455 res = x; | |
456 BID_RETURN (res); | |
457 } else { | |
458 res = y; | |
459 BID_RETURN (res); | |
460 } | |
461 } else if (((sig_x.w[1] > sig_y.w[1] || (sig_x.w[1] == sig_y.w[1] | |
462 && sig_x.w[0] > sig_y.w[0])) | |
463 && exp_x == exp_y) | |
464 || ((sig_x.w[1] > sig_y.w[1] | |
465 || (sig_x.w[1] == sig_y.w[1] | |
466 && sig_x.w[0] >= sig_y.w[0])) | |
467 && exp_x > exp_y)) { | |
468 // if both components are either bigger or smaller, it is clear what | |
469 // needs to be done; also if the magnitudes are equal | |
470 res = y; | |
471 BID_RETURN (res); | |
472 } else if (((sig_y.w[1] > sig_x.w[1] || (sig_y.w[1] == sig_x.w[1] | |
473 && sig_y.w[0] > sig_x.w[0])) | |
474 && exp_y == exp_x) | |
475 || ((sig_y.w[1] > sig_x.w[1] | |
476 || (sig_y.w[1] == sig_x.w[1] | |
477 && sig_y.w[0] >= sig_x.w[0])) | |
478 && exp_y > exp_x)) { | |
479 res = x; | |
480 BID_RETURN (res); | |
481 } else { | |
482 ; // continue | |
483 } | |
484 diff = exp_x - exp_y; | |
485 // if |exp_x - exp_y| < 33, it comes down to the compensated significand | |
486 if (diff > 0) { // to simplify the loop below, | |
487 // if exp_x is 33 greater than exp_y, no need for compensation | |
488 if (diff > 33) { | |
489 res = y; // difference cannot be greater than 10^33 | |
490 BID_RETURN (res); | |
491 } | |
492 if (diff > 19) { //128 by 128 bit multiply -> 256 bits | |
493 __mul_128x128_to_256 (sig_n_prime256, sig_x, ten2k128[diff - 20]); | |
494 // if positive, return whichever significand is larger | |
495 // (converse if negative) | |
496 if (sig_n_prime256.w[3] == 0 && (sig_n_prime256.w[2] == 0) | |
497 && sig_n_prime256.w[1] == sig_y.w[1] | |
498 && (sig_n_prime256.w[0] == sig_y.w[0])) { | |
499 res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x; // if equal | |
500 BID_RETURN (res); | |
501 } | |
502 res = (((sig_n_prime256.w[3] > 0) || sig_n_prime256.w[2] > 0) | |
503 || (sig_n_prime256.w[1] > sig_y.w[1]) | |
504 || (sig_n_prime256.w[1] == sig_y.w[1] | |
505 && sig_n_prime256.w[0] > sig_y.w[0])) ? y : x; | |
506 BID_RETURN (res); | |
507 } | |
508 __mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_x); | |
509 // if positive, return whichever significand is larger | |
510 // (converse if negative) | |
511 if ((sig_n_prime192.w[2] == 0) && sig_n_prime192.w[1] == sig_y.w[1] | |
512 && (sig_n_prime192.w[0] == sig_y.w[0])) { | |
513 // if = in magnitude, return +, (if possible) | |
514 res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x; | |
515 BID_RETURN (res); | |
516 } | |
517 res = ((sig_n_prime192.w[2] > 0) | |
518 || (sig_n_prime192.w[1] > sig_y.w[1]) | |
519 || (sig_n_prime192.w[1] == sig_y.w[1] | |
520 && sig_n_prime192.w[0] > sig_y.w[0])) ? y : x; | |
521 BID_RETURN (res); | |
522 } | |
523 diff = exp_y - exp_x; | |
524 // if exp_x is 33 less than exp_y, no need for compensation | |
525 if (diff > 33) { | |
526 res = x; | |
527 BID_RETURN (res); | |
528 } | |
529 if (diff > 19) { //128 by 128 bit multiply -> 256 bits | |
530 // adjust the y significand upwards | |
531 __mul_128x128_to_256 (sig_n_prime256, sig_y, ten2k128[diff - 20]); | |
532 // if positive, return whichever significand is larger | |
533 // (converse if negative) | |
534 if (sig_n_prime256.w[3] == 0 && (sig_n_prime256.w[2] == 0) | |
535 && sig_n_prime256.w[1] == sig_x.w[1] | |
536 && (sig_n_prime256.w[0] == sig_x.w[0])) { | |
537 // if = in magnitude, return +, (if possible) | |
538 res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x; | |
539 BID_RETURN (res); | |
540 } | |
541 res = (sig_n_prime256.w[3] == 0 && sig_n_prime256.w[2] == 0 | |
542 && (sig_n_prime256.w[1] < sig_x.w[1] | |
543 || (sig_n_prime256.w[1] == sig_x.w[1] | |
544 && sig_n_prime256.w[0] < sig_x.w[0]))) ? y : x; | |
545 BID_RETURN (res); | |
546 } | |
547 // adjust the y significand upwards | |
548 __mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_y); | |
549 // if positive, return whichever significand is larger (converse if negative) | |
550 if ((sig_n_prime192.w[2] == 0) && sig_n_prime192.w[1] == sig_x.w[1] | |
551 && (sig_n_prime192.w[0] == sig_x.w[0])) { | |
552 // if = in magnitude, return +, if possible) | |
553 res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x; | |
554 BID_RETURN (res); | |
555 } | |
556 res = (sig_n_prime192.w[2] == 0 | |
557 && (sig_n_prime192.w[1] < sig_x.w[1] | |
558 || (sig_n_prime192.w[1] == sig_x.w[1] | |
559 && sig_n_prime192.w[0] < sig_x.w[0]))) ? y : x; | |
560 BID_RETURN (res); | |
561 } | |
562 | |
563 /***************************************************************************** | |
564 * BID128 maximum function - returns greater of two numbers | |
565 *****************************************************************************/ | |
566 | |
567 #if DECIMAL_CALL_BY_REFERENCE | |
568 void | |
569 bid128_maxnum (UINT128 * pres, UINT128 * px, | |
570 UINT128 * py _EXC_FLAGS_PARAM) { | |
571 UINT128 x = *px; | |
572 UINT128 y = *py; | |
573 #else | |
574 UINT128 | |
575 bid128_maxnum (UINT128 x, UINT128 y _EXC_FLAGS_PARAM) { | |
576 #endif | |
577 | |
578 UINT128 res; | |
579 int exp_x, exp_y; | |
580 int diff; | |
581 UINT128 sig_x, sig_y; | |
582 UINT192 sig_n_prime192; | |
583 UINT256 sig_n_prime256; | |
584 char x_is_zero = 0, y_is_zero = 0; | |
585 | |
586 BID_SWAP128 (x); | |
587 BID_SWAP128 (y); | |
588 | |
589 // check for non-canonical x | |
590 if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN | |
591 x.w[1] = x.w[1] & 0xfe003fffffffffffull; // clear out G[6]-G[16] | |
592 // check for non-canonical NaN payload | |
593 if (((x.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) || | |
594 (((x.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull) && | |
595 (x.w[0] > 0x38c15b09ffffffffull))) { | |
596 x.w[1] = x.w[1] & 0xffffc00000000000ull; | |
597 x.w[0] = 0x0ull; | |
598 } | |
599 } else if ((x.w[1] & MASK_ANY_INF) == MASK_INF) { // x = inf | |
600 x.w[1] = x.w[1] & (MASK_SIGN | MASK_INF); | |
601 x.w[0] = 0x0ull; | |
602 } else { // x is not special | |
603 // check for non-canonical values - treated as zero | |
604 if ((x.w[1] & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // G0_G1=11 | |
605 // non-canonical | |
606 x.w[1] = (x.w[1] & MASK_SIGN) | ((x.w[1] << 2) & MASK_EXP); | |
607 x.w[0] = 0x0ull; | |
608 } else { // G0_G1 != 11 | |
609 if ((x.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull || | |
610 ((x.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull | |
611 && x.w[0] > 0x378d8e63ffffffffull)) { | |
612 // x is non-canonical if coefficient is larger than 10^34 -1 | |
613 x.w[1] = (x.w[1] & MASK_SIGN) | (x.w[1] & MASK_EXP); | |
614 x.w[0] = 0x0ull; | |
615 } else { // canonical | |
616 ; | |
617 } | |
618 } | |
619 } | |
620 // check for non-canonical y | |
621 if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NAN | |
622 y.w[1] = y.w[1] & 0xfe003fffffffffffull; // clear out G[6]-G[16] | |
623 // check for non-canonical NaN payload | |
624 if (((y.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) || | |
625 (((y.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull) && | |
626 (y.w[0] > 0x38c15b09ffffffffull))) { | |
627 y.w[1] = y.w[1] & 0xffffc00000000000ull; | |
628 y.w[0] = 0x0ull; | |
629 } | |
630 } else if ((y.w[1] & MASK_ANY_INF) == MASK_INF) { // y = inf | |
631 y.w[1] = y.w[1] & (MASK_SIGN | MASK_INF); | |
632 y.w[0] = 0x0ull; | |
633 } else { // y is not special | |
634 // check for non-canonical values - treated as zero | |
635 if ((y.w[1] & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // G0_G1=11 | |
636 // non-canonical | |
637 y.w[1] = (y.w[1] & MASK_SIGN) | ((y.w[1] << 2) & MASK_EXP); | |
638 y.w[0] = 0x0ull; | |
639 } else { // G0_G1 != 11 | |
640 if ((y.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull || | |
641 ((y.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull | |
642 && y.w[0] > 0x378d8e63ffffffffull)) { | |
643 // y is non-canonical if coefficient is larger than 10^34 -1 | |
644 y.w[1] = (y.w[1] & MASK_SIGN) | (y.w[1] & MASK_EXP); | |
645 y.w[0] = 0x0ull; | |
646 } else { // canonical | |
647 ; | |
648 } | |
649 } | |
650 } | |
651 | |
652 // NaN (CASE1) | |
653 if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN | |
654 if ((x.w[1] & MASK_SNAN) == MASK_SNAN) { // x is SNaN | |
655 // if x is SNAN, then return quiet (x) | |
656 *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN | |
657 x.w[1] = x.w[1] & 0xfdffffffffffffffull; // quietize x | |
658 res = x; | |
659 } else { // x is QNaN | |
660 if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NAN | |
661 if ((y.w[1] & MASK_SNAN) == MASK_SNAN) { // y is SNAN | |
662 *pfpsf |= INVALID_EXCEPTION; // set invalid flag | |
663 } | |
664 res = x; | |
665 } else { | |
666 res = y; | |
667 } | |
668 } | |
669 BID_RETURN (res); | |
670 } else if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NaN, but x is not | |
671 if ((y.w[1] & MASK_SNAN) == MASK_SNAN) { | |
672 *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN | |
673 y.w[1] = y.w[1] & 0xfdffffffffffffffull; // quietize y | |
674 res = y; | |
675 } else { | |
676 // will return x (which is not NaN) | |
677 res = x; | |
678 } | |
679 BID_RETURN (res); | |
680 } | |
681 // SIMPLE (CASE2) | |
682 // if all the bits are the same, these numbers are equal (not Greater). | |
683 if (x.w[0] == y.w[0] && x.w[1] == y.w[1]) { | |
684 res = x; | |
685 BID_RETURN (res); | |
686 } | |
687 // INFINITY (CASE3) | |
688 if ((x.w[1] & MASK_INF) == MASK_INF) { | |
689 res = ((x.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x; | |
690 BID_RETURN (res); | |
691 } else if ((y.w[1] & MASK_INF) == MASK_INF) { | |
692 // x is finite, so if y is positive infinity, then x is less, return 0 | |
693 // if y is negative infinity, then x is greater, return 1 | |
694 res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y; | |
695 BID_RETURN (res); | |
696 } | |
697 // CONVERT X | |
698 sig_x.w[1] = x.w[1] & 0x0001ffffffffffffull; | |
699 sig_x.w[0] = x.w[0]; | |
700 exp_x = (x.w[1] >> 49) & 0x000000000003fffull; | |
701 | |
702 // CONVERT Y | |
703 exp_y = (y.w[1] >> 49) & 0x0000000000003fffull; | |
704 sig_y.w[1] = y.w[1] & 0x0001ffffffffffffull; | |
705 sig_y.w[0] = y.w[0]; | |
706 | |
707 // ZERO (CASE4) | |
708 // some properties: | |
709 // (+ZERO == -ZERO) => therefore ignore the sign | |
710 // (ZERO x 10^A == ZERO x 10^B) for any valid A, B => | |
711 // therefore ignore the exponent field | |
712 // (Any non-canonical # is considered 0) | |
713 if ((sig_x.w[1] == 0) && (sig_x.w[0] == 0)) { | |
714 x_is_zero = 1; | |
715 } | |
716 if ((sig_y.w[1] == 0) && (sig_y.w[0] == 0)) { | |
717 y_is_zero = 1; | |
718 } | |
719 | |
720 if (x_is_zero && y_is_zero) { | |
721 // if both numbers are zero, neither is greater => return either number | |
722 res = x; | |
723 BID_RETURN (res); | |
724 } else if (x_is_zero) { | |
725 // is x is zero, it is greater if Y is negative | |
726 res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y; | |
727 BID_RETURN (res); | |
728 } else if (y_is_zero) { | |
729 // is y is zero, X is greater if it is positive | |
730 res = ((x.w[1] & MASK_SIGN) != MASK_SIGN) ? x : y; | |
731 BID_RETURN (res); | |
732 } | |
733 // OPPOSITE SIGN (CASE5) | |
734 // now, if the sign bits differ, x is greater if y is negative | |
735 if (((x.w[1] ^ y.w[1]) & MASK_SIGN) == MASK_SIGN) { | |
736 res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y; | |
737 BID_RETURN (res); | |
738 } | |
739 // REDUNDANT REPRESENTATIONS (CASE6) | |
740 // if exponents are the same, then we have a simple comparison of | |
741 // the significands | |
742 if (exp_y == exp_x) { | |
743 res = (((sig_x.w[1] > sig_y.w[1]) || (sig_x.w[1] == sig_y.w[1] && | |
744 sig_x.w[0] >= sig_y.w[0])) ^ | |
745 ((x.w[1] & MASK_SIGN) == MASK_SIGN)) ? x : y; | |
746 BID_RETURN (res); | |
747 } | |
748 // if both components are either bigger or smaller, it is clear what | |
749 // needs to be done | |
750 if ((sig_x.w[1] > sig_y.w[1] | |
751 || (sig_x.w[1] == sig_y.w[1] && sig_x.w[0] > sig_y.w[0])) | |
752 && exp_x >= exp_y) { | |
753 res = ((x.w[1] & MASK_SIGN) != MASK_SIGN) ? x : y; | |
754 BID_RETURN (res); | |
755 } | |
756 if ((sig_x.w[1] < sig_y.w[1] | |
757 || (sig_x.w[1] == sig_y.w[1] && sig_x.w[0] < sig_y.w[0])) | |
758 && exp_x <= exp_y) { | |
759 res = ((x.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y; | |
760 BID_RETURN (res); | |
761 } | |
762 diff = exp_x - exp_y; | |
763 // if |exp_x - exp_y| < 33, it comes down to the compensated significand | |
764 if (diff > 0) { // to simplify the loop below, | |
765 // if exp_x is 33 greater than exp_y, no need for compensation | |
766 if (diff > 33) { | |
767 // difference cannot be greater than 10^33 | |
768 res = ((x.w[1] & MASK_SIGN) != MASK_SIGN) ? x : y; | |
769 BID_RETURN (res); | |
770 } | |
771 if (diff > 19) { //128 by 128 bit multiply -> 256 bits | |
772 __mul_128x128_to_256 (sig_n_prime256, sig_x, ten2k128[diff - 20]); | |
773 // if postitive, return whichever significand is larger | |
774 // (converse if negative) | |
775 res = ((((sig_n_prime256.w[3] > 0) || sig_n_prime256.w[2] > 0) | |
776 || (sig_n_prime256.w[1] > sig_y.w[1]) | |
777 || (sig_n_prime256.w[1] == sig_y.w[1] | |
778 && sig_n_prime256.w[0] > | |
779 sig_y.w[0])) ^ ((y.w[1] & MASK_SIGN) == | |
780 MASK_SIGN)) ? x : y; | |
781 BID_RETURN (res); | |
782 } | |
783 __mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_x); | |
784 // if postitive, return whichever significand is larger | |
785 // (converse if negative) | |
786 res = | |
787 (((sig_n_prime192.w[2] > 0) || (sig_n_prime192.w[1] > sig_y.w[1]) | |
788 || (sig_n_prime192.w[1] == sig_y.w[1] | |
789 && sig_n_prime192.w[0] > | |
790 sig_y.w[0])) ^ ((y.w[1] & MASK_SIGN) == MASK_SIGN)) ? x : y; | |
791 BID_RETURN (res); | |
792 } | |
793 diff = exp_y - exp_x; | |
794 // if exp_x is 33 less than exp_y, no need for compensation | |
795 if (diff > 33) { | |
796 res = ((x.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y; | |
797 BID_RETURN (res); | |
798 } | |
799 if (diff > 19) { //128 by 128 bit multiply -> 256 bits | |
800 // adjust the y significand upwards | |
801 __mul_128x128_to_256 (sig_n_prime256, sig_y, ten2k128[diff - 20]); | |
802 // if postitive, return whichever significand is larger | |
803 // (converse if negative) | |
804 res = | |
805 ((sig_n_prime256.w[3] != 0 || sig_n_prime256.w[2] != 0 | |
806 || (sig_n_prime256.w[1] > sig_x.w[1] | |
807 || (sig_n_prime256.w[1] == sig_x.w[1] | |
808 && sig_n_prime256.w[0] > | |
809 sig_x.w[0]))) ^ ((x.w[1] & MASK_SIGN) != | |
810 MASK_SIGN)) ? x : y; | |
811 BID_RETURN (res); | |
812 } | |
813 // adjust the y significand upwards | |
814 __mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_y); | |
815 // if postitive, return whichever significand is larger (converse if negative) | |
816 res = | |
817 ((sig_n_prime192.w[2] != 0 | |
818 || (sig_n_prime192.w[1] > sig_x.w[1] | |
819 || (sig_n_prime192.w[1] == sig_x.w[1] | |
820 && sig_n_prime192.w[0] > | |
821 sig_x.w[0]))) ^ ((y.w[1] & MASK_SIGN) != | |
822 MASK_SIGN)) ? x : y; | |
823 BID_RETURN (res); | |
824 } | |
825 | |
826 /***************************************************************************** | |
827 * BID128 maximum magnitude function - returns greater of two numbers | |
828 *****************************************************************************/ | |
829 | |
830 #if DECIMAL_CALL_BY_REFERENCE | |
831 void | |
832 bid128_maxnum_mag (UINT128 * pres, UINT128 * px, | |
833 UINT128 * py _EXC_FLAGS_PARAM) { | |
834 UINT128 x = *px; | |
835 UINT128 y = *py; | |
836 #else | |
837 UINT128 | |
838 bid128_maxnum_mag (UINT128 x, UINT128 y _EXC_FLAGS_PARAM) { | |
839 #endif | |
840 | |
841 UINT128 res; | |
842 int exp_x, exp_y; | |
843 int diff; | |
844 UINT128 sig_x, sig_y; | |
845 UINT192 sig_n_prime192; | |
846 UINT256 sig_n_prime256; | |
847 | |
848 BID_SWAP128 (x); | |
849 BID_SWAP128 (y); | |
850 | |
851 // check for non-canonical x | |
852 if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN | |
853 x.w[1] = x.w[1] & 0xfe003fffffffffffull; // clear out G[6]-G[16] | |
854 // check for non-canonical NaN payload | |
855 if (((x.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) || | |
856 (((x.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull) && | |
857 (x.w[0] > 0x38c15b09ffffffffull))) { | |
858 x.w[1] = x.w[1] & 0xffffc00000000000ull; | |
859 x.w[0] = 0x0ull; | |
860 } | |
861 } else if ((x.w[1] & MASK_ANY_INF) == MASK_INF) { // x = inf | |
862 x.w[1] = x.w[1] & (MASK_SIGN | MASK_INF); | |
863 x.w[0] = 0x0ull; | |
864 } else { // x is not special | |
865 // check for non-canonical values - treated as zero | |
866 if ((x.w[1] & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // G0_G1=11 | |
867 // non-canonical | |
868 x.w[1] = (x.w[1] & MASK_SIGN) | ((x.w[1] << 2) & MASK_EXP); | |
869 x.w[0] = 0x0ull; | |
870 } else { // G0_G1 != 11 | |
871 if ((x.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull || | |
872 ((x.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull | |
873 && x.w[0] > 0x378d8e63ffffffffull)) { | |
874 // x is non-canonical if coefficient is larger than 10^34 -1 | |
875 x.w[1] = (x.w[1] & MASK_SIGN) | (x.w[1] & MASK_EXP); | |
876 x.w[0] = 0x0ull; | |
877 } else { // canonical | |
878 ; | |
879 } | |
880 } | |
881 } | |
882 // check for non-canonical y | |
883 if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NAN | |
884 y.w[1] = y.w[1] & 0xfe003fffffffffffull; // clear out G[6]-G[16] | |
885 // check for non-canonical NaN payload | |
886 if (((y.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) || | |
887 (((y.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull) && | |
888 (y.w[0] > 0x38c15b09ffffffffull))) { | |
889 y.w[1] = y.w[1] & 0xffffc00000000000ull; | |
890 y.w[0] = 0x0ull; | |
891 } | |
892 } else if ((y.w[1] & MASK_ANY_INF) == MASK_INF) { // y = inf | |
893 y.w[1] = y.w[1] & (MASK_SIGN | MASK_INF); | |
894 y.w[0] = 0x0ull; | |
895 } else { // y is not special | |
896 // check for non-canonical values - treated as zero | |
897 if ((y.w[1] & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // G0_G1=11 | |
898 // non-canonical | |
899 y.w[1] = (y.w[1] & MASK_SIGN) | ((y.w[1] << 2) & MASK_EXP); | |
900 y.w[0] = 0x0ull; | |
901 } else { // G0_G1 != 11 | |
902 if ((y.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull || | |
903 ((y.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull && | |
904 y.w[0] > 0x378d8e63ffffffffull)) { | |
905 // y is non-canonical if coefficient is larger than 10^34 -1 | |
906 y.w[1] = (y.w[1] & MASK_SIGN) | (y.w[1] & MASK_EXP); | |
907 y.w[0] = 0x0ull; | |
908 } else { // canonical | |
909 ; | |
910 } | |
911 } | |
912 } | |
913 | |
914 // NaN (CASE1) | |
915 if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN | |
916 if ((x.w[1] & MASK_SNAN) == MASK_SNAN) { // x is SNaN | |
917 // if x is SNAN, then return quiet (x) | |
918 *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN | |
919 x.w[1] = x.w[1] & 0xfdffffffffffffffull; // quietize x | |
920 res = x; | |
921 } else { // x is QNaN | |
922 if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NAN | |
923 if ((y.w[1] & MASK_SNAN) == MASK_SNAN) { // y is SNAN | |
924 *pfpsf |= INVALID_EXCEPTION; // set invalid flag | |
925 } | |
926 res = x; | |
927 } else { | |
928 res = y; | |
929 } | |
930 } | |
931 BID_RETURN (res); | |
932 } else if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NaN, but x is not | |
933 if ((y.w[1] & MASK_SNAN) == MASK_SNAN) { | |
934 *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN | |
935 y.w[1] = y.w[1] & 0xfdffffffffffffffull; // quietize y | |
936 res = y; | |
937 } else { | |
938 // will return x (which is not NaN) | |
939 res = x; | |
940 } | |
941 BID_RETURN (res); | |
942 } | |
943 // SIMPLE (CASE2) | |
944 // if all the bits are the same, these numbers are equal (not Greater). | |
945 if (x.w[0] == y.w[0] && x.w[1] == y.w[1]) { | |
946 res = y; | |
947 BID_RETURN (res); | |
948 } | |
949 // INFINITY (CASE3) | |
950 if ((x.w[1] & MASK_INF) == MASK_INF) { | |
951 // if x infinity, it has maximum magnitude | |
952 res = ((x.w[1] & MASK_SIGN) == MASK_SIGN | |
953 && (y.w[1] & MASK_INF) == MASK_INF) ? y : x; | |
954 BID_RETURN (res); | |
955 } else if ((y.w[1] & MASK_INF) == MASK_INF) { | |
956 // x is finite, so if y is positive infinity, then x is less, return 0 | |
957 // if y is negative infinity, then x is greater, return 1 | |
958 res = y; | |
959 BID_RETURN (res); | |
960 } | |
961 // CONVERT X | |
962 sig_x.w[1] = x.w[1] & 0x0001ffffffffffffull; | |
963 sig_x.w[0] = x.w[0]; | |
964 exp_x = (x.w[1] >> 49) & 0x000000000003fffull; | |
965 | |
966 // CONVERT Y | |
967 exp_y = (y.w[1] >> 49) & 0x0000000000003fffull; | |
968 sig_y.w[1] = y.w[1] & 0x0001ffffffffffffull; | |
969 sig_y.w[0] = y.w[0]; | |
970 | |
971 // ZERO (CASE4) | |
972 // some properties: | |
973 // (+ZERO == -ZERO) => therefore ignore the sign | |
974 // (ZERO x 10^A == ZERO x 10^B) for any valid A, B => | |
975 // therefore ignore the exponent field | |
976 // (Any non-canonical # is considered 0) | |
977 if ((sig_x.w[1] == 0) && (sig_x.w[0] == 0)) { | |
978 res = y; | |
979 BID_RETURN (res); | |
980 } | |
981 if ((sig_y.w[1] == 0) && (sig_y.w[0] == 0)) { | |
982 res = x; | |
983 BID_RETURN (res); | |
984 } | |
985 // REDUNDANT REPRESENTATIONS (CASE6) | |
986 if (exp_y == exp_x && sig_x.w[1] == sig_y.w[1] | |
987 && sig_x.w[0] == sig_y.w[0]) { | |
988 // check if exponents are the same and significands are the same | |
989 if (x.w[1] & 0x8000000000000000ull) { // x is negative | |
990 res = y; | |
991 BID_RETURN (res); | |
992 } else { | |
993 res = x; | |
994 BID_RETURN (res); | |
995 } | |
996 } else if (((sig_x.w[1] > sig_y.w[1] || (sig_x.w[1] == sig_y.w[1] | |
997 && sig_x.w[0] > sig_y.w[0])) | |
998 && exp_x == exp_y) | |
999 || ((sig_x.w[1] > sig_y.w[1] | |
1000 || (sig_x.w[1] == sig_y.w[1] | |
1001 && sig_x.w[0] >= sig_y.w[0])) | |
1002 && exp_x > exp_y)) { | |
1003 // if both components are either bigger or smaller, it is clear what | |
1004 // needs to be done; also if the magnitudes are equal | |
1005 res = x; | |
1006 BID_RETURN (res); | |
1007 } else if (((sig_y.w[1] > sig_x.w[1] || (sig_y.w[1] == sig_x.w[1] | |
1008 && sig_y.w[0] > sig_x.w[0])) | |
1009 && exp_y == exp_x) | |
1010 || ((sig_y.w[1] > sig_x.w[1] | |
1011 || (sig_y.w[1] == sig_x.w[1] | |
1012 && sig_y.w[0] >= sig_x.w[0])) | |
1013 && exp_y > exp_x)) { | |
1014 res = y; | |
1015 BID_RETURN (res); | |
1016 } else { | |
1017 ; // continue | |
1018 } | |
1019 diff = exp_x - exp_y; | |
1020 // if |exp_x - exp_y| < 33, it comes down to the compensated significand | |
1021 if (diff > 0) { // to simplify the loop below, | |
1022 // if exp_x is 33 greater than exp_y, no need for compensation | |
1023 if (diff > 33) { | |
1024 res = x; // difference cannot be greater than 10^33 | |
1025 BID_RETURN (res); | |
1026 } | |
1027 if (diff > 19) { //128 by 128 bit multiply -> 256 bits | |
1028 __mul_128x128_to_256 (sig_n_prime256, sig_x, ten2k128[diff - 20]); | |
1029 // if postitive, return whichever significand is larger | |
1030 // (converse if negative) | |
1031 if (sig_n_prime256.w[3] == 0 && (sig_n_prime256.w[2] == 0) | |
1032 && sig_n_prime256.w[1] == sig_y.w[1] | |
1033 && (sig_n_prime256.w[0] == sig_y.w[0])) { | |
1034 res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y; // if equal | |
1035 BID_RETURN (res); | |
1036 } | |
1037 res = (((sig_n_prime256.w[3] > 0) || sig_n_prime256.w[2] > 0) | |
1038 || (sig_n_prime256.w[1] > sig_y.w[1]) | |
1039 || (sig_n_prime256.w[1] == sig_y.w[1] | |
1040 && sig_n_prime256.w[0] > sig_y.w[0])) ? x : y; | |
1041 BID_RETURN (res); | |
1042 } | |
1043 __mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_x); | |
1044 // if postitive, return whichever significand is larger (converse if negative) | |
1045 if ((sig_n_prime192.w[2] == 0) && sig_n_prime192.w[1] == sig_y.w[1] | |
1046 && (sig_n_prime192.w[0] == sig_y.w[0])) { | |
1047 // if equal, return positive magnitude | |
1048 res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y; | |
1049 BID_RETURN (res); | |
1050 } | |
1051 res = ((sig_n_prime192.w[2] > 0) | |
1052 || (sig_n_prime192.w[1] > sig_y.w[1]) | |
1053 || (sig_n_prime192.w[1] == sig_y.w[1] | |
1054 && sig_n_prime192.w[0] > sig_y.w[0])) ? x : y; | |
1055 BID_RETURN (res); | |
1056 } | |
1057 diff = exp_y - exp_x; | |
1058 // if exp_x is 33 less than exp_y, no need for compensation | |
1059 if (diff > 33) { | |
1060 res = y; | |
1061 BID_RETURN (res); | |
1062 } | |
1063 if (diff > 19) { //128 by 128 bit multiply -> 256 bits | |
1064 // adjust the y significand upwards | |
1065 __mul_128x128_to_256 (sig_n_prime256, sig_y, ten2k128[diff - 20]); | |
1066 // if postitive, return whichever significand is larger | |
1067 // (converse if negative) | |
1068 if (sig_n_prime256.w[3] == 0 && (sig_n_prime256.w[2] == 0) | |
1069 && sig_n_prime256.w[1] == sig_x.w[1] | |
1070 && (sig_n_prime256.w[0] == sig_x.w[0])) { | |
1071 // if equal, return positive (if possible) | |
1072 res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y; | |
1073 BID_RETURN (res); | |
1074 } | |
1075 res = (sig_n_prime256.w[3] == 0 && sig_n_prime256.w[2] == 0 | |
1076 && (sig_n_prime256.w[1] < sig_x.w[1] | |
1077 || (sig_n_prime256.w[1] == sig_x.w[1] | |
1078 && sig_n_prime256.w[0] < sig_x.w[0]))) ? x : y; | |
1079 BID_RETURN (res); | |
1080 } | |
1081 // adjust the y significand upwards | |
1082 __mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_y); | |
1083 // if postitive, return whichever significand is larger (converse if negative) | |
1084 if ((sig_n_prime192.w[2] == 0) && sig_n_prime192.w[1] == sig_x.w[1] | |
1085 && (sig_n_prime192.w[0] == sig_x.w[0])) { | |
1086 // if equal, return positive (if possible) | |
1087 res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y; | |
1088 BID_RETURN (res); | |
1089 } | |
1090 res = (sig_n_prime192.w[2] == 0 | |
1091 && (sig_n_prime192.w[1] < sig_x.w[1] | |
1092 || (sig_n_prime192.w[1] == sig_x.w[1] | |
1093 && sig_n_prime192.w[0] < sig_x.w[0]))) ? x : y; | |
1094 BID_RETURN (res); | |
1095 } |