]>
Commit | Line | Data |
---|---|---|
83ffe9cd | 1 | /* Copyright (C) 2007-2023 Free Software Foundation, Inc. |
200359e8 L |
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 | |
748086b7 | 7 | Software Foundation; either version 3, or (at your option) any later |
200359e8 L |
8 | version. |
9 | ||
200359e8 L |
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 | ||
748086b7 JJ |
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/>. */ | |
200359e8 L |
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 | |
b2a00c89 L |
33 | bid128_minnum (UINT128 * pres, UINT128 * px, |
34 | UINT128 * py _EXC_FLAGS_PARAM) { | |
200359e8 L |
35 | UINT128 x = *px; |
36 | UINT128 y = *py; | |
37 | #else | |
38 | UINT128 | |
b2a00c89 | 39 | bid128_minnum (UINT128 x, UINT128 y _EXC_FLAGS_PARAM) { |
200359e8 L |
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; | |
b2a00c89 | 48 | char x_is_zero = 0, y_is_zero = 0; |
200359e8 | 49 | |
b2a00c89 L |
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; | |
200359e8 | 62 | } |
b2a00c89 L |
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 | } | |
200359e8 | 82 | } |
200359e8 | 83 | } |
b2a00c89 L |
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; | |
200359e8 | 142 | } |
200359e8 L |
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 | ||
200359e8 L |
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 | ||
200359e8 L |
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) | |
b2a00c89 | 178 | if ((sig_x.w[1] == 0) && (sig_x.w[0] == 0)) { |
200359e8 L |
179 | x_is_zero = 1; |
180 | } | |
b2a00c89 | 181 | if ((sig_y.w[1] == 0) && (sig_y.w[0] == 0)) { |
200359e8 L |
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]) | |
b2a00c89 L |
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; | |
200359e8 L |
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 | |
b2a00c89 | 230 | if (diff > 0) { // to simplify the loop below, |
200359e8 L |
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 | } | |
b2a00c89 L |
237 | if (diff > 19) { //128 by 128 bit multiply -> 256 bits |
238 | __mul_128x128_to_256 (sig_n_prime256, sig_x, ten2k128[diff - 20]); | |
200359e8 L |
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) | |
b2a00c89 L |
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; | |
200359e8 L |
247 | BID_RETURN (res); |
248 | } | |
b2a00c89 | 249 | __mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_x); |
200359e8 L |
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]) | |
b2a00c89 L |
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; | |
200359e8 L |
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 | } | |
b2a00c89 | 265 | if (diff > 19) { //128 by 128 bit multiply -> 256 bits |
200359e8 | 266 | // adjust the y significand upwards |
b2a00c89 | 267 | __mul_128x128_to_256 (sig_n_prime256, sig_y, ten2k128[diff - 20]); |
200359e8 L |
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 | |
b2a00c89 L |
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; | |
200359e8 L |
277 | BID_RETURN (res); |
278 | } | |
279 | // adjust the y significand upwards | |
b2a00c89 | 280 | __mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_y); |
200359e8 | 281 | // if postitive, return whichever significand is larger (converse if negative) |
b2a00c89 L |
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; | |
200359e8 L |
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 | |
b2a00c89 L |
297 | bid128_minnum_mag (UINT128 * pres, UINT128 * px, |
298 | UINT128 * py _EXC_FLAGS_PARAM) { | |
200359e8 L |
299 | UINT128 x = *px; |
300 | UINT128 y = *py; | |
301 | #else | |
302 | UINT128 | |
b2a00c89 | 303 | bid128_minnum_mag (UINT128 x, UINT128 y _EXC_FLAGS_PARAM) { |
200359e8 L |
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; | |
200359e8 | 312 | |
b2a00c89 L |
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; | |
200359e8 | 325 | } |
b2a00c89 L |
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 | } | |
200359e8 | 395 | } |
200359e8 | 396 | BID_RETURN (res); |
b2a00c89 L |
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; | |
200359e8 | 405 | } |
200359e8 L |
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 | |
b2a00c89 | 419 | && (y.w[1] & MASK_INF) == MASK_INF) ? x : y; |
200359e8 L |
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 | ||
200359e8 L |
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 | ||
200359e8 L |
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) | |
b2a00c89 | 442 | if ((sig_x.w[1] == 0) && (sig_x.w[0] == 0)) { |
200359e8 L |
443 | res = x; |
444 | BID_RETURN (res); | |
445 | } | |
b2a00c89 | 446 | if ((sig_y.w[1] == 0) && (sig_y.w[0] == 0)) { |
200359e8 L |
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]) { | |
b2a00c89 | 454 | if (x.w[1] & 0x8000000000000000ull) { // x is negative |
200359e8 L |
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] | |
b2a00c89 L |
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)) { | |
200359e8 L |
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] | |
b2a00c89 L |
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)) { | |
200359e8 L |
479 | res = x; |
480 | BID_RETURN (res); | |
481 | } else { | |
b2a00c89 | 482 | ; // continue |
200359e8 L |
483 | } |
484 | diff = exp_x - exp_y; | |
485 | // if |exp_x - exp_y| < 33, it comes down to the compensated significand | |
b2a00c89 | 486 | if (diff > 0) { // to simplify the loop below, |
200359e8 L |
487 | // if exp_x is 33 greater than exp_y, no need for compensation |
488 | if (diff > 33) { | |
b2a00c89 | 489 | res = y; // difference cannot be greater than 10^33 |
200359e8 L |
490 | BID_RETURN (res); |
491 | } | |
b2a00c89 L |
492 | if (diff > 19) { //128 by 128 bit multiply -> 256 bits |
493 | __mul_128x128_to_256 (sig_n_prime256, sig_x, ten2k128[diff - 20]); | |
200359e8 L |
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) | |
b2a00c89 L |
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); | |
200359e8 L |
501 | } |
502 | res = (((sig_n_prime256.w[3] > 0) || sig_n_prime256.w[2] > 0) | |
b2a00c89 L |
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; | |
200359e8 L |
506 | BID_RETURN (res); |
507 | } | |
b2a00c89 | 508 | __mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_x); |
200359e8 L |
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] | |
b2a00c89 | 512 | && (sig_n_prime192.w[0] == sig_y.w[0])) { |
200359e8 L |
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) | |
b2a00c89 L |
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; | |
200359e8 L |
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 | } | |
b2a00c89 | 529 | if (diff > 19) { //128 by 128 bit multiply -> 256 bits |
200359e8 | 530 | // adjust the y significand upwards |
b2a00c89 | 531 | __mul_128x128_to_256 (sig_n_prime256, sig_y, ten2k128[diff - 20]); |
200359e8 L |
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) | |
b2a00c89 L |
535 | && sig_n_prime256.w[1] == sig_x.w[1] |
536 | && (sig_n_prime256.w[0] == sig_x.w[0])) { | |
200359e8 L |
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 | |
b2a00c89 L |
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; | |
200359e8 L |
545 | BID_RETURN (res); |
546 | } | |
547 | // adjust the y significand upwards | |
b2a00c89 | 548 | __mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_y); |
200359e8 L |
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 | } | |
b2a00c89 L |
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; | |
200359e8 L |
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 | |
b2a00c89 L |
569 | bid128_maxnum (UINT128 * pres, UINT128 * px, |
570 | UINT128 * py _EXC_FLAGS_PARAM) { | |
200359e8 L |
571 | UINT128 x = *px; |
572 | UINT128 y = *py; | |
573 | #else | |
574 | UINT128 | |
b2a00c89 | 575 | bid128_maxnum (UINT128 x, UINT128 y _EXC_FLAGS_PARAM) { |
200359e8 L |
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; | |
b2a00c89 | 584 | char x_is_zero = 0, y_is_zero = 0; |
200359e8 | 585 | |
b2a00c89 L |
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; | |
200359e8 | 598 | } |
b2a00c89 L |
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 | } | |
200359e8 | 668 | } |
200359e8 | 669 | BID_RETURN (res); |
b2a00c89 L |
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; | |
200359e8 | 678 | } |
200359e8 L |
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 | ||
200359e8 L |
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 | ||
200359e8 L |
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) | |
b2a00c89 | 713 | if ((sig_x.w[1] == 0) && (sig_x.w[0] == 0)) { |
200359e8 L |
714 | x_is_zero = 1; |
715 | } | |
b2a00c89 | 716 | if ((sig_y.w[1] == 0) && (sig_y.w[0] == 0)) { |
200359e8 L |
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) { | |
b2a00c89 L |
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; | |
200359e8 L |
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 | |
b2a00c89 | 764 | if (diff > 0) { // to simplify the loop below, |
200359e8 L |
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 | } | |
b2a00c89 L |
771 | if (diff > 19) { //128 by 128 bit multiply -> 256 bits |
772 | __mul_128x128_to_256 (sig_n_prime256, sig_x, ten2k128[diff - 20]); | |
200359e8 L |
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) | |
b2a00c89 L |
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; | |
200359e8 L |
781 | BID_RETURN (res); |
782 | } | |
b2a00c89 | 783 | __mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_x); |
200359e8 L |
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]) | |
b2a00c89 L |
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; | |
200359e8 L |
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 | } | |
b2a00c89 | 799 | if (diff > 19) { //128 by 128 bit multiply -> 256 bits |
200359e8 | 800 | // adjust the y significand upwards |
b2a00c89 | 801 | __mul_128x128_to_256 (sig_n_prime256, sig_y, ten2k128[diff - 20]); |
200359e8 L |
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 | |
b2a00c89 L |
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; | |
200359e8 L |
811 | BID_RETURN (res); |
812 | } | |
813 | // adjust the y significand upwards | |
b2a00c89 | 814 | __mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_y); |
200359e8 | 815 | // if postitive, return whichever significand is larger (converse if negative) |
b2a00c89 L |
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; | |
200359e8 L |
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 | |
b2a00c89 L |
832 | bid128_maxnum_mag (UINT128 * pres, UINT128 * px, |
833 | UINT128 * py _EXC_FLAGS_PARAM) { | |
200359e8 L |
834 | UINT128 x = *px; |
835 | UINT128 y = *py; | |
836 | #else | |
837 | UINT128 | |
b2a00c89 | 838 | bid128_maxnum_mag (UINT128 x, UINT128 y _EXC_FLAGS_PARAM) { |
200359e8 L |
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; | |
200359e8 | 847 | |
b2a00c89 L |
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; | |
200359e8 | 860 | } |
b2a00c89 L |
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 | } | |
200359e8 | 930 | } |
200359e8 | 931 | BID_RETURN (res); |
b2a00c89 L |
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; | |
200359e8 | 940 | } |
200359e8 L |
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 | |
b2a00c89 | 953 | && (y.w[1] & MASK_INF) == MASK_INF) ? y : x; |
200359e8 L |
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 | ||
200359e8 L |
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 | ||
200359e8 L |
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) | |
b2a00c89 | 977 | if ((sig_x.w[1] == 0) && (sig_x.w[0] == 0)) { |
200359e8 L |
978 | res = y; |
979 | BID_RETURN (res); | |
980 | } | |
b2a00c89 | 981 | if ((sig_y.w[1] == 0) && (sig_y.w[0] == 0)) { |
200359e8 L |
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 | |
b2a00c89 | 989 | if (x.w[1] & 0x8000000000000000ull) { // x is negative |
200359e8 L |
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] | |
b2a00c89 L |
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)) { | |
200359e8 L |
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] | |
b2a00c89 L |
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)) { | |
200359e8 L |
1014 | res = y; |
1015 | BID_RETURN (res); | |
1016 | } else { | |
b2a00c89 | 1017 | ; // continue |
200359e8 L |
1018 | } |
1019 | diff = exp_x - exp_y; | |
1020 | // if |exp_x - exp_y| < 33, it comes down to the compensated significand | |
b2a00c89 | 1021 | if (diff > 0) { // to simplify the loop below, |
200359e8 L |
1022 | // if exp_x is 33 greater than exp_y, no need for compensation |
1023 | if (diff > 33) { | |
b2a00c89 | 1024 | res = x; // difference cannot be greater than 10^33 |
200359e8 L |
1025 | BID_RETURN (res); |
1026 | } | |
b2a00c89 L |
1027 | if (diff > 19) { //128 by 128 bit multiply -> 256 bits |
1028 | __mul_128x128_to_256 (sig_n_prime256, sig_x, ten2k128[diff - 20]); | |
200359e8 L |
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) | |
b2a00c89 L |
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); | |
200359e8 L |
1036 | } |
1037 | res = (((sig_n_prime256.w[3] > 0) || sig_n_prime256.w[2] > 0) | |
b2a00c89 L |
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; | |
200359e8 L |
1041 | BID_RETURN (res); |
1042 | } | |
b2a00c89 | 1043 | __mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_x); |
200359e8 L |
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] | |
b2a00c89 | 1046 | && (sig_n_prime192.w[0] == sig_y.w[0])) { |
200359e8 L |
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) | |
b2a00c89 L |
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; | |
200359e8 L |
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 | } | |
b2a00c89 | 1063 | if (diff > 19) { //128 by 128 bit multiply -> 256 bits |
200359e8 | 1064 | // adjust the y significand upwards |
b2a00c89 | 1065 | __mul_128x128_to_256 (sig_n_prime256, sig_y, ten2k128[diff - 20]); |
200359e8 L |
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) | |
b2a00c89 L |
1069 | && sig_n_prime256.w[1] == sig_x.w[1] |
1070 | && (sig_n_prime256.w[0] == sig_x.w[0])) { | |
200359e8 L |
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 | |
b2a00c89 L |
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; | |
200359e8 L |
1079 | BID_RETURN (res); |
1080 | } | |
1081 | // adjust the y significand upwards | |
b2a00c89 | 1082 | __mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_y); |
200359e8 L |
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 | } | |
b2a00c89 L |
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; | |
200359e8 L |
1094 | BID_RETURN (res); |
1095 | } |