]>
Commit | Line | Data |
---|---|---|
f1717362 | 1 | /* Copyright (C) 2007-2016 Free Software Foundation, Inc. |
9b6b0236 | 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 | |
6bc9506f | 7 | Software Foundation; either version 3, or (at your option) any later |
9b6b0236 | 8 | version. |
9 | ||
9b6b0236 | 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 | ||
6bc9506f | 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/>. */ | |
9b6b0236 | 23 | |
24 | #include "bid_internal.h" | |
25 | ||
26 | /***************************************************************************** | |
27 | * BID64 minimum function - returns greater of two numbers | |
28 | *****************************************************************************/ | |
29 | ||
30 | static const UINT64 mult_factor[16] = { | |
31 | 1ull, 10ull, 100ull, 1000ull, | |
32 | 10000ull, 100000ull, 1000000ull, 10000000ull, | |
33 | 100000000ull, 1000000000ull, 10000000000ull, 100000000000ull, | |
34 | 1000000000000ull, 10000000000000ull, | |
35 | 100000000000000ull, 1000000000000000ull | |
36 | }; | |
37 | ||
38 | #if DECIMAL_CALL_BY_REFERENCE | |
39 | void | |
84d1fc49 | 40 | bid64_minnum (UINT64 * pres, UINT64 * px, UINT64 * py _EXC_FLAGS_PARAM) { |
9b6b0236 | 41 | UINT64 x = *px; |
42 | UINT64 y = *py; | |
43 | #else | |
44 | UINT64 | |
84d1fc49 | 45 | bid64_minnum (UINT64 x, UINT64 y _EXC_FLAGS_PARAM) { |
9b6b0236 | 46 | #endif |
47 | ||
48 | UINT64 res; | |
49 | int exp_x, exp_y; | |
50 | UINT64 sig_x, sig_y; | |
51 | UINT128 sig_n_prime; | |
84d1fc49 | 52 | char x_is_zero = 0, y_is_zero = 0; |
9b6b0236 | 53 | |
84d1fc49 | 54 | // check for non-canonical x |
55 | if ((x & MASK_NAN) == MASK_NAN) { // x is NaN | |
56 | x = x & 0xfe03ffffffffffffull; // clear G6-G12 | |
57 | if ((x & 0x0003ffffffffffffull) > 999999999999999ull) { | |
58 | x = x & 0xfe00000000000000ull; // clear G6-G12 and the payload bits | |
9b6b0236 | 59 | } |
84d1fc49 | 60 | } else if ((x & MASK_INF) == MASK_INF) { // check for Infinity |
61 | x = x & (MASK_SIGN | MASK_INF); | |
62 | } else { // x is not special | |
63 | // check for non-canonical values - treated as zero | |
64 | if ((x & MASK_STEERING_BITS) == MASK_STEERING_BITS) { | |
65 | // if the steering bits are 11, then the exponent is G[0:w+1] | |
66 | if (((x & MASK_BINARY_SIG2) | MASK_BINARY_OR2) > | |
67 | 9999999999999999ull) { | |
68 | // non-canonical | |
69 | x = (x & MASK_SIGN) | ((x & MASK_BINARY_EXPONENT2) << 2); | |
70 | } // else canonical | |
71 | } // else canonical | |
72 | } | |
73 | ||
74 | // check for non-canonical y | |
75 | if ((y & MASK_NAN) == MASK_NAN) { // y is NaN | |
76 | y = y & 0xfe03ffffffffffffull; // clear G6-G12 | |
77 | if ((y & 0x0003ffffffffffffull) > 999999999999999ull) { | |
78 | y = y & 0xfe00000000000000ull; // clear G6-G12 and the payload bits | |
9b6b0236 | 79 | } |
84d1fc49 | 80 | } else if ((y & MASK_INF) == MASK_INF) { // check for Infinity |
81 | y = y & (MASK_SIGN | MASK_INF); | |
82 | } else { // y is not special | |
83 | // check for non-canonical values - treated as zero | |
84 | if ((y & MASK_STEERING_BITS) == MASK_STEERING_BITS) { | |
85 | // if the steering bits are 11, then the exponent is G[0:w+1] | |
86 | if (((y & MASK_BINARY_SIG2) | MASK_BINARY_OR2) > | |
87 | 9999999999999999ull) { | |
88 | // non-canonical | |
89 | y = (y & MASK_SIGN) | ((y & MASK_BINARY_EXPONENT2) << 2); | |
90 | } // else canonical | |
91 | } // else canonical | |
9b6b0236 | 92 | } |
84d1fc49 | 93 | |
94 | // NaN (CASE1) | |
95 | if ((x & MASK_NAN) == MASK_NAN) { // x is NAN | |
96 | if ((x & MASK_SNAN) == MASK_SNAN) { // x is SNaN | |
97 | // if x is SNAN, then return quiet (x) | |
98 | *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN | |
99 | x = x & 0xfdffffffffffffffull; // quietize x | |
100 | res = x; | |
101 | } else { // x is QNaN | |
102 | if ((y & MASK_NAN) == MASK_NAN) { // y is NAN | |
103 | if ((y & MASK_SNAN) == MASK_SNAN) { // y is SNAN | |
104 | *pfpsf |= INVALID_EXCEPTION; // set invalid flag | |
105 | } | |
106 | res = x; | |
107 | } else { | |
108 | res = y; | |
109 | } | |
110 | } | |
111 | BID_RETURN (res); | |
112 | } else if ((y & MASK_NAN) == MASK_NAN) { // y is NaN, but x is not | |
113 | if ((y & MASK_SNAN) == MASK_SNAN) { | |
114 | *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN | |
115 | y = y & 0xfdffffffffffffffull; // quietize y | |
116 | res = y; | |
117 | } else { | |
118 | // will return x (which is not NaN) | |
119 | res = x; | |
9b6b0236 | 120 | } |
9b6b0236 | 121 | BID_RETURN (res); |
122 | } | |
123 | // SIMPLE (CASE2) | |
124 | // if all the bits are the same, these numbers are equal, return either number | |
125 | if (x == y) { | |
126 | res = x; | |
127 | BID_RETURN (res); | |
128 | } | |
129 | // INFINITY (CASE3) | |
130 | if ((x & MASK_INF) == MASK_INF) { | |
131 | // if x is neg infinity, there is no way it is greater than y, return x | |
132 | if (((x & MASK_SIGN) == MASK_SIGN)) { | |
133 | res = x; | |
134 | BID_RETURN (res); | |
135 | } | |
136 | // x is pos infinity, return y | |
137 | else { | |
138 | res = y; | |
139 | BID_RETURN (res); | |
140 | } | |
141 | } else if ((y & MASK_INF) == MASK_INF) { | |
142 | // x is finite, so if y is positive infinity, then x is less, return y | |
143 | // if y is negative infinity, then x is greater, return x | |
144 | res = ((y & MASK_SIGN) == MASK_SIGN) ? y : x; | |
145 | BID_RETURN (res); | |
146 | } | |
147 | // if steering bits are 11 (condition will be 0), then exponent is G[0:w+1] => | |
148 | if ((x & MASK_STEERING_BITS) == MASK_STEERING_BITS) { | |
149 | exp_x = (x & MASK_BINARY_EXPONENT2) >> 51; | |
150 | sig_x = (x & MASK_BINARY_SIG2) | MASK_BINARY_OR2; | |
9b6b0236 | 151 | } else { |
152 | exp_x = (x & MASK_BINARY_EXPONENT1) >> 53; | |
153 | sig_x = (x & MASK_BINARY_SIG1); | |
9b6b0236 | 154 | } |
155 | ||
156 | // if steering bits are 11 (condition will be 0), then exponent is G[0:w+1] => | |
157 | if ((y & MASK_STEERING_BITS) == MASK_STEERING_BITS) { | |
158 | exp_y = (y & MASK_BINARY_EXPONENT2) >> 51; | |
159 | sig_y = (y & MASK_BINARY_SIG2) | MASK_BINARY_OR2; | |
9b6b0236 | 160 | } else { |
161 | exp_y = (y & MASK_BINARY_EXPONENT1) >> 53; | |
162 | sig_y = (y & MASK_BINARY_SIG1); | |
9b6b0236 | 163 | } |
164 | ||
165 | // ZERO (CASE4) | |
166 | // some properties: | |
167 | // (+ZERO == -ZERO) => therefore | |
168 | // ignore the sign, and neither number is greater | |
169 | // (ZERO x 10^A == ZERO x 10^B) for any valid A, B => | |
170 | // ignore the exponent field | |
171 | // (Any non-canonical # is considered 0) | |
84d1fc49 | 172 | if (sig_x == 0) { |
9b6b0236 | 173 | x_is_zero = 1; |
174 | } | |
84d1fc49 | 175 | if (sig_y == 0) { |
9b6b0236 | 176 | y_is_zero = 1; |
177 | } | |
178 | ||
179 | if (x_is_zero && y_is_zero) { | |
180 | // if both numbers are zero, neither is greater => return either | |
181 | res = y; | |
182 | BID_RETURN (res); | |
183 | } else if (x_is_zero) { | |
184 | // is x is zero, it is greater if Y is negative | |
185 | res = ((y & MASK_SIGN) == MASK_SIGN) ? y : x; | |
186 | BID_RETURN (res); | |
187 | } else if (y_is_zero) { | |
188 | // is y is zero, X is greater if it is positive | |
189 | res = ((x & MASK_SIGN) != MASK_SIGN) ? y : x;; | |
190 | BID_RETURN (res); | |
191 | } | |
192 | // OPPOSITE SIGN (CASE5) | |
193 | // now, if the sign bits differ, x is greater if y is negative | |
194 | if (((x ^ y) & MASK_SIGN) == MASK_SIGN) { | |
195 | res = ((y & MASK_SIGN) == MASK_SIGN) ? y : x; | |
196 | BID_RETURN (res); | |
197 | } | |
198 | // REDUNDANT REPRESENTATIONS (CASE6) | |
199 | ||
200 | // if both components are either bigger or smaller, | |
201 | // it is clear what needs to be done | |
202 | if (sig_x > sig_y && exp_x >= exp_y) { | |
203 | res = ((x & MASK_SIGN) != MASK_SIGN) ? y : x; | |
204 | BID_RETURN (res); | |
205 | } | |
206 | if (sig_x < sig_y && exp_x <= exp_y) { | |
207 | res = ((x & MASK_SIGN) == MASK_SIGN) ? y : x; | |
208 | BID_RETURN (res); | |
209 | } | |
210 | // if exp_x is 15 greater than exp_y, no need for compensation | |
211 | if (exp_x - exp_y > 15) { | |
84d1fc49 | 212 | res = ((x & MASK_SIGN) != MASK_SIGN) ? y : x; // difference cannot be >10^15 |
9b6b0236 | 213 | BID_RETURN (res); |
214 | } | |
215 | // if exp_x is 15 less than exp_y, no need for compensation | |
216 | if (exp_y - exp_x > 15) { | |
217 | res = ((x & MASK_SIGN) == MASK_SIGN) ? y : x; | |
218 | BID_RETURN (res); | |
219 | } | |
220 | // if |exp_x - exp_y| < 15, it comes down to the compensated significand | |
84d1fc49 | 221 | if (exp_x > exp_y) { // to simplify the loop below, |
9b6b0236 | 222 | |
223 | // otherwise adjust the x significand upwards | |
224 | __mul_64x64_to_128MACH (sig_n_prime, sig_x, | |
225 | mult_factor[exp_x - exp_y]); | |
226 | // if postitive, return whichever significand is larger | |
227 | // (converse if negative) | |
228 | if (sig_n_prime.w[1] == 0 && (sig_n_prime.w[0] == sig_y)) { | |
229 | res = y; | |
230 | BID_RETURN (res); | |
231 | } | |
232 | ||
233 | res = (((sig_n_prime.w[1] > 0) | |
234 | || sig_n_prime.w[0] > sig_y) ^ ((x & MASK_SIGN) == | |
235 | MASK_SIGN)) ? y : x; | |
236 | BID_RETURN (res); | |
237 | } | |
238 | // adjust the y significand upwards | |
239 | __mul_64x64_to_128MACH (sig_n_prime, sig_y, | |
240 | mult_factor[exp_y - exp_x]); | |
241 | ||
242 | // if postitive, return whichever significand is larger (converse if negative) | |
243 | if (sig_n_prime.w[1] == 0 && (sig_n_prime.w[0] == sig_x)) { | |
244 | res = y; | |
245 | BID_RETURN (res); | |
246 | } | |
247 | res = (((sig_n_prime.w[1] == 0) | |
248 | && (sig_x > sig_n_prime.w[0])) ^ ((x & MASK_SIGN) == | |
249 | MASK_SIGN)) ? y : x; | |
250 | BID_RETURN (res); | |
251 | } | |
252 | ||
253 | /***************************************************************************** | |
254 | * BID64 minimum magnitude function - returns greater of two numbers | |
255 | *****************************************************************************/ | |
256 | ||
257 | #if DECIMAL_CALL_BY_REFERENCE | |
258 | void | |
84d1fc49 | 259 | bid64_minnum_mag (UINT64 * pres, UINT64 * px, |
260 | UINT64 * py _EXC_FLAGS_PARAM) { | |
9b6b0236 | 261 | UINT64 x = *px; |
262 | UINT64 y = *py; | |
263 | #else | |
264 | UINT64 | |
84d1fc49 | 265 | bid64_minnum_mag (UINT64 x, UINT64 y _EXC_FLAGS_PARAM) { |
9b6b0236 | 266 | #endif |
267 | ||
268 | UINT64 res; | |
269 | int exp_x, exp_y; | |
270 | UINT64 sig_x, sig_y; | |
271 | UINT128 sig_n_prime; | |
9b6b0236 | 272 | |
84d1fc49 | 273 | // check for non-canonical x |
274 | if ((x & MASK_NAN) == MASK_NAN) { // x is NaN | |
275 | x = x & 0xfe03ffffffffffffull; // clear G6-G12 | |
276 | if ((x & 0x0003ffffffffffffull) > 999999999999999ull) { | |
277 | x = x & 0xfe00000000000000ull; // clear G6-G12 and the payload bits | |
9b6b0236 | 278 | } |
84d1fc49 | 279 | } else if ((x & MASK_INF) == MASK_INF) { // check for Infinity |
280 | x = x & (MASK_SIGN | MASK_INF); | |
281 | } else { // x is not special | |
282 | // check for non-canonical values - treated as zero | |
283 | if ((x & MASK_STEERING_BITS) == MASK_STEERING_BITS) { | |
284 | // if the steering bits are 11, then the exponent is G[0:w+1] | |
285 | if (((x & MASK_BINARY_SIG2) | MASK_BINARY_OR2) > | |
286 | 9999999999999999ull) { | |
287 | // non-canonical | |
288 | x = (x & MASK_SIGN) | ((x & MASK_BINARY_EXPONENT2) << 2); | |
289 | } // else canonical | |
290 | } // else canonical | |
291 | } | |
292 | ||
293 | // check for non-canonical y | |
294 | if ((y & MASK_NAN) == MASK_NAN) { // y is NaN | |
295 | y = y & 0xfe03ffffffffffffull; // clear G6-G12 | |
296 | if ((y & 0x0003ffffffffffffull) > 999999999999999ull) { | |
297 | y = y & 0xfe00000000000000ull; // clear G6-G12 and the payload bits | |
298 | } | |
299 | } else if ((y & MASK_INF) == MASK_INF) { // check for Infinity | |
300 | y = y & (MASK_SIGN | MASK_INF); | |
301 | } else { // y is not special | |
302 | // check for non-canonical values - treated as zero | |
303 | if ((y & MASK_STEERING_BITS) == MASK_STEERING_BITS) { | |
304 | // if the steering bits are 11, then the exponent is G[0:w+1] | |
305 | if (((y & MASK_BINARY_SIG2) | MASK_BINARY_OR2) > | |
306 | 9999999999999999ull) { | |
307 | // non-canonical | |
308 | y = (y & MASK_SIGN) | ((y & MASK_BINARY_EXPONENT2) << 2); | |
309 | } // else canonical | |
310 | } // else canonical | |
311 | } | |
312 | ||
313 | // NaN (CASE1) | |
314 | if ((x & MASK_NAN) == MASK_NAN) { // x is NAN | |
315 | if ((x & MASK_SNAN) == MASK_SNAN) { // x is SNaN | |
316 | // if x is SNAN, then return quiet (x) | |
317 | *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN | |
318 | x = x & 0xfdffffffffffffffull; // quietize x | |
319 | res = x; | |
320 | } else { // x is QNaN | |
321 | if ((y & MASK_NAN) == MASK_NAN) { // y is NAN | |
322 | if ((y & MASK_SNAN) == MASK_SNAN) { // y is SNAN | |
323 | *pfpsf |= INVALID_EXCEPTION; // set invalid flag | |
324 | } | |
325 | res = x; | |
326 | } else { | |
327 | res = y; | |
328 | } | |
9b6b0236 | 329 | } |
9b6b0236 | 330 | BID_RETURN (res); |
84d1fc49 | 331 | } else if ((y & MASK_NAN) == MASK_NAN) { // y is NaN, but x is not |
332 | if ((y & MASK_SNAN) == MASK_SNAN) { | |
333 | *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN | |
334 | y = y & 0xfdffffffffffffffull; // quietize y | |
335 | res = y; | |
336 | } else { | |
337 | // will return x (which is not NaN) | |
338 | res = x; | |
9b6b0236 | 339 | } |
9b6b0236 | 340 | BID_RETURN (res); |
341 | } | |
342 | // SIMPLE (CASE2) | |
343 | // if all the bits are the same, these numbers are equal, return either number | |
344 | if (x == y) { | |
345 | res = x; | |
346 | BID_RETURN (res); | |
347 | } | |
348 | // INFINITY (CASE3) | |
349 | if ((x & MASK_INF) == MASK_INF) { | |
350 | // x is infinity, its magnitude is greater than or equal to y | |
351 | // return x only if y is infinity and x is negative | |
352 | res = ((x & MASK_SIGN) == MASK_SIGN | |
353 | && (y & MASK_INF) == MASK_INF) ? x : y; | |
354 | BID_RETURN (res); | |
355 | } else if ((y & MASK_INF) == MASK_INF) { | |
356 | // y is infinity, then it must be greater in magnitude, return x | |
357 | res = x; | |
358 | BID_RETURN (res); | |
359 | } | |
360 | // if steering bits are 11 (condition will be 0), then exponent is G[0:w+1] => | |
361 | if ((x & MASK_STEERING_BITS) == MASK_STEERING_BITS) { | |
362 | exp_x = (x & MASK_BINARY_EXPONENT2) >> 51; | |
363 | sig_x = (x & MASK_BINARY_SIG2) | MASK_BINARY_OR2; | |
9b6b0236 | 364 | } else { |
365 | exp_x = (x & MASK_BINARY_EXPONENT1) >> 53; | |
366 | sig_x = (x & MASK_BINARY_SIG1); | |
9b6b0236 | 367 | } |
368 | ||
369 | // if steering bits are 11 (condition will be 0), then exponent is G[0:w+1] => | |
370 | if ((y & MASK_STEERING_BITS) == MASK_STEERING_BITS) { | |
371 | exp_y = (y & MASK_BINARY_EXPONENT2) >> 51; | |
372 | sig_y = (y & MASK_BINARY_SIG2) | MASK_BINARY_OR2; | |
9b6b0236 | 373 | } else { |
374 | exp_y = (y & MASK_BINARY_EXPONENT1) >> 53; | |
375 | sig_y = (y & MASK_BINARY_SIG1); | |
9b6b0236 | 376 | } |
377 | ||
378 | // ZERO (CASE4) | |
379 | // some properties: | |
380 | // (+ZERO == -ZERO) => therefore | |
381 | // ignore the sign, and neither number is greater | |
382 | // (ZERO x 10^A == ZERO x 10^B) for any valid A, B => | |
383 | // ignore the exponent field | |
384 | // (Any non-canonical # is considered 0) | |
84d1fc49 | 385 | if (sig_x == 0) { |
386 | res = x; // x_is_zero, its magnitude must be smaller than y | |
9b6b0236 | 387 | BID_RETURN (res); |
388 | } | |
84d1fc49 | 389 | if (sig_y == 0) { |
390 | res = y; // y_is_zero, its magnitude must be smaller than x | |
9b6b0236 | 391 | BID_RETURN (res); |
392 | } | |
393 | // REDUNDANT REPRESENTATIONS (CASE6) | |
394 | // if both components are either bigger or smaller, | |
395 | // it is clear what needs to be done | |
396 | if (sig_x > sig_y && exp_x >= exp_y) { | |
397 | res = y; | |
398 | BID_RETURN (res); | |
399 | } | |
400 | if (sig_x < sig_y && exp_x <= exp_y) { | |
401 | res = x; | |
402 | BID_RETURN (res); | |
403 | } | |
404 | // if exp_x is 15 greater than exp_y, no need for compensation | |
405 | if (exp_x - exp_y > 15) { | |
84d1fc49 | 406 | res = y; // difference cannot be greater than 10^15 |
9b6b0236 | 407 | BID_RETURN (res); |
408 | } | |
409 | // if exp_x is 15 less than exp_y, no need for compensation | |
410 | if (exp_y - exp_x > 15) { | |
411 | res = x; | |
412 | BID_RETURN (res); | |
413 | } | |
414 | // if |exp_x - exp_y| < 15, it comes down to the compensated significand | |
84d1fc49 | 415 | if (exp_x > exp_y) { // to simplify the loop below, |
9b6b0236 | 416 | // otherwise adjust the x significand upwards |
417 | __mul_64x64_to_128MACH (sig_n_prime, sig_x, | |
418 | mult_factor[exp_x - exp_y]); | |
419 | // now, sig_n_prime has: sig_x * 10^(exp_x-exp_y), this is | |
420 | // the compensated signif. | |
421 | if (sig_n_prime.w[1] == 0 && (sig_n_prime.w[0] == sig_y)) { | |
422 | // two numbers are equal, return minNum(x,y) | |
423 | res = ((y & MASK_SIGN) == MASK_SIGN) ? y : x; | |
424 | BID_RETURN (res); | |
425 | } | |
426 | // now, if compensated_x (sig_n_prime) is greater than y, return y, | |
427 | // otherwise return x | |
428 | res = ((sig_n_prime.w[1] != 0) || sig_n_prime.w[0] > sig_y) ? y : x; | |
429 | BID_RETURN (res); | |
430 | } | |
431 | // exp_y must be greater than exp_x, thus adjust the y significand upwards | |
432 | __mul_64x64_to_128MACH (sig_n_prime, sig_y, | |
433 | mult_factor[exp_y - exp_x]); | |
434 | ||
435 | if (sig_n_prime.w[1] == 0 && (sig_n_prime.w[0] == sig_x)) { | |
84d1fc49 | 436 | res = ((y & MASK_SIGN) == MASK_SIGN) ? y : x; |
437 | // two numbers are equal, return either | |
9b6b0236 | 438 | BID_RETURN (res); |
439 | } | |
440 | ||
441 | res = ((sig_n_prime.w[1] == 0) && (sig_x > sig_n_prime.w[0])) ? y : x; | |
442 | BID_RETURN (res); | |
443 | } | |
444 | ||
445 | /***************************************************************************** | |
446 | * BID64 maximum function - returns greater of two numbers | |
447 | *****************************************************************************/ | |
448 | ||
449 | #if DECIMAL_CALL_BY_REFERENCE | |
450 | void | |
84d1fc49 | 451 | bid64_maxnum (UINT64 * pres, UINT64 * px, UINT64 * py _EXC_FLAGS_PARAM) { |
9b6b0236 | 452 | UINT64 x = *px; |
453 | UINT64 y = *py; | |
454 | #else | |
455 | UINT64 | |
84d1fc49 | 456 | bid64_maxnum (UINT64 x, UINT64 y _EXC_FLAGS_PARAM) { |
9b6b0236 | 457 | #endif |
458 | ||
459 | UINT64 res; | |
460 | int exp_x, exp_y; | |
461 | UINT64 sig_x, sig_y; | |
462 | UINT128 sig_n_prime; | |
84d1fc49 | 463 | char x_is_zero = 0, y_is_zero = 0; |
9b6b0236 | 464 | |
84d1fc49 | 465 | // check for non-canonical x |
466 | if ((x & MASK_NAN) == MASK_NAN) { // x is NaN | |
467 | x = x & 0xfe03ffffffffffffull; // clear G6-G12 | |
468 | if ((x & 0x0003ffffffffffffull) > 999999999999999ull) { | |
469 | x = x & 0xfe00000000000000ull; // clear G6-G12 and the payload bits | |
9b6b0236 | 470 | } |
84d1fc49 | 471 | } else if ((x & MASK_INF) == MASK_INF) { // check for Infinity |
472 | x = x & (MASK_SIGN | MASK_INF); | |
473 | } else { // x is not special | |
474 | // check for non-canonical values - treated as zero | |
475 | if ((x & MASK_STEERING_BITS) == MASK_STEERING_BITS) { | |
476 | // if the steering bits are 11, then the exponent is G[0:w+1] | |
477 | if (((x & MASK_BINARY_SIG2) | MASK_BINARY_OR2) > | |
478 | 9999999999999999ull) { | |
479 | // non-canonical | |
480 | x = (x & MASK_SIGN) | ((x & MASK_BINARY_EXPONENT2) << 2); | |
481 | } // else canonical | |
482 | } // else canonical | |
483 | } | |
484 | ||
485 | // check for non-canonical y | |
486 | if ((y & MASK_NAN) == MASK_NAN) { // y is NaN | |
487 | y = y & 0xfe03ffffffffffffull; // clear G6-G12 | |
488 | if ((y & 0x0003ffffffffffffull) > 999999999999999ull) { | |
489 | y = y & 0xfe00000000000000ull; // clear G6-G12 and the payload bits | |
490 | } | |
491 | } else if ((y & MASK_INF) == MASK_INF) { // check for Infinity | |
492 | y = y & (MASK_SIGN | MASK_INF); | |
493 | } else { // y is not special | |
494 | // check for non-canonical values - treated as zero | |
495 | if ((y & MASK_STEERING_BITS) == MASK_STEERING_BITS) { | |
496 | // if the steering bits are 11, then the exponent is G[0:w+1] | |
497 | if (((y & MASK_BINARY_SIG2) | MASK_BINARY_OR2) > | |
498 | 9999999999999999ull) { | |
499 | // non-canonical | |
500 | y = (y & MASK_SIGN) | ((y & MASK_BINARY_EXPONENT2) << 2); | |
501 | } // else canonical | |
502 | } // else canonical | |
503 | } | |
504 | ||
505 | // NaN (CASE1) | |
506 | if ((x & MASK_NAN) == MASK_NAN) { // x is NAN | |
507 | if ((x & MASK_SNAN) == MASK_SNAN) { // x is SNaN | |
508 | // if x is SNAN, then return quiet (x) | |
509 | *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN | |
510 | x = x & 0xfdffffffffffffffull; // quietize x | |
511 | res = x; | |
512 | } else { // x is QNaN | |
513 | if ((y & MASK_NAN) == MASK_NAN) { // y is NAN | |
514 | if ((y & MASK_SNAN) == MASK_SNAN) { // y is SNAN | |
515 | *pfpsf |= INVALID_EXCEPTION; // set invalid flag | |
516 | } | |
517 | res = x; | |
518 | } else { | |
519 | res = y; | |
520 | } | |
9b6b0236 | 521 | } |
9b6b0236 | 522 | BID_RETURN (res); |
84d1fc49 | 523 | } else if ((y & MASK_NAN) == MASK_NAN) { // y is NaN, but x is not |
524 | if ((y & MASK_SNAN) == MASK_SNAN) { | |
525 | *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN | |
526 | y = y & 0xfdffffffffffffffull; // quietize y | |
527 | res = y; | |
528 | } else { | |
529 | // will return x (which is not NaN) | |
530 | res = x; | |
9b6b0236 | 531 | } |
9b6b0236 | 532 | BID_RETURN (res); |
533 | } | |
534 | // SIMPLE (CASE2) | |
535 | // if all the bits are the same, these numbers are equal (not Greater). | |
536 | if (x == y) { | |
537 | res = x; | |
538 | BID_RETURN (res); | |
539 | } | |
540 | // INFINITY (CASE3) | |
541 | if ((x & MASK_INF) == MASK_INF) { | |
542 | // if x is neg infinity, there is no way it is greater than y, return y | |
543 | // x is pos infinity, it is greater, unless y is positive infinity => | |
544 | // return y!=pos_infinity | |
545 | if (((x & MASK_SIGN) == MASK_SIGN)) { | |
546 | res = y; | |
547 | BID_RETURN (res); | |
548 | } else { | |
549 | res = (((y & MASK_INF) != MASK_INF) | |
550 | || ((y & MASK_SIGN) == MASK_SIGN)) ? x : y; | |
551 | BID_RETURN (res); | |
552 | } | |
553 | } else if ((y & MASK_INF) == MASK_INF) { | |
554 | // x is finite, so if y is positive infinity, then x is less, return y | |
555 | // if y is negative infinity, then x is greater, return x | |
556 | res = ((y & MASK_SIGN) == MASK_SIGN) ? x : y; | |
557 | BID_RETURN (res); | |
558 | } | |
559 | // if steering bits are 11 (condition will be 0), then exponent is G[0:w+1] => | |
560 | if ((x & MASK_STEERING_BITS) == MASK_STEERING_BITS) { | |
561 | exp_x = (x & MASK_BINARY_EXPONENT2) >> 51; | |
562 | sig_x = (x & MASK_BINARY_SIG2) | MASK_BINARY_OR2; | |
9b6b0236 | 563 | } else { |
564 | exp_x = (x & MASK_BINARY_EXPONENT1) >> 53; | |
565 | sig_x = (x & MASK_BINARY_SIG1); | |
9b6b0236 | 566 | } |
567 | ||
568 | // if steering bits are 11 (condition will be 0), then exponent is G[0:w+1] => | |
569 | if ((y & MASK_STEERING_BITS) == MASK_STEERING_BITS) { | |
570 | exp_y = (y & MASK_BINARY_EXPONENT2) >> 51; | |
571 | sig_y = (y & MASK_BINARY_SIG2) | MASK_BINARY_OR2; | |
9b6b0236 | 572 | } else { |
573 | exp_y = (y & MASK_BINARY_EXPONENT1) >> 53; | |
574 | sig_y = (y & MASK_BINARY_SIG1); | |
9b6b0236 | 575 | } |
576 | ||
577 | // ZERO (CASE4) | |
578 | // some properties: | |
579 | // (+ZERO == -ZERO) => therefore | |
580 | // ignore the sign, and neither number is greater | |
581 | // (ZERO x 10^A == ZERO x 10^B) for any valid A, B => | |
582 | // ignore the exponent field | |
583 | // (Any non-canonical # is considered 0) | |
84d1fc49 | 584 | if (sig_x == 0) { |
9b6b0236 | 585 | x_is_zero = 1; |
586 | } | |
84d1fc49 | 587 | if (sig_y == 0) { |
9b6b0236 | 588 | y_is_zero = 1; |
589 | } | |
590 | ||
591 | if (x_is_zero && y_is_zero) { | |
592 | // if both numbers are zero, neither is greater => return NOTGREATERTHAN | |
593 | res = y; | |
594 | BID_RETURN (res); | |
595 | } else if (x_is_zero) { | |
596 | // is x is zero, it is greater if Y is negative | |
597 | res = ((y & MASK_SIGN) == MASK_SIGN) ? x : y; | |
598 | BID_RETURN (res); | |
599 | } else if (y_is_zero) { | |
600 | // is y is zero, X is greater if it is positive | |
601 | res = ((x & MASK_SIGN) != MASK_SIGN) ? x : y;; | |
602 | BID_RETURN (res); | |
603 | } | |
604 | // OPPOSITE SIGN (CASE5) | |
605 | // now, if the sign bits differ, x is greater if y is negative | |
606 | if (((x ^ y) & MASK_SIGN) == MASK_SIGN) { | |
607 | res = ((y & MASK_SIGN) == MASK_SIGN) ? x : y; | |
608 | BID_RETURN (res); | |
609 | } | |
610 | // REDUNDANT REPRESENTATIONS (CASE6) | |
611 | ||
612 | // if both components are either bigger or smaller, | |
613 | // it is clear what needs to be done | |
614 | if (sig_x > sig_y && exp_x >= exp_y) { | |
615 | res = ((x & MASK_SIGN) != MASK_SIGN) ? x : y; | |
616 | BID_RETURN (res); | |
617 | } | |
618 | if (sig_x < sig_y && exp_x <= exp_y) { | |
619 | res = ((x & MASK_SIGN) == MASK_SIGN) ? x : y; | |
620 | BID_RETURN (res); | |
621 | } | |
622 | // if exp_x is 15 greater than exp_y, no need for compensation | |
623 | if (exp_x - exp_y > 15) { | |
84d1fc49 | 624 | res = ((x & MASK_SIGN) != MASK_SIGN) ? x : y; |
625 | // difference cannot be > 10^15 | |
9b6b0236 | 626 | BID_RETURN (res); |
627 | } | |
628 | // if exp_x is 15 less than exp_y, no need for compensation | |
629 | if (exp_y - exp_x > 15) { | |
630 | res = ((x & MASK_SIGN) == MASK_SIGN) ? x : y; | |
631 | BID_RETURN (res); | |
632 | } | |
633 | // if |exp_x - exp_y| < 15, it comes down to the compensated significand | |
84d1fc49 | 634 | if (exp_x > exp_y) { // to simplify the loop below, |
9b6b0236 | 635 | // otherwise adjust the x significand upwards |
636 | __mul_64x64_to_128MACH (sig_n_prime, sig_x, | |
637 | mult_factor[exp_x - exp_y]); | |
638 | // if postitive, return whichever significand is larger | |
639 | // (converse if negative) | |
640 | if (sig_n_prime.w[1] == 0 && (sig_n_prime.w[0] == sig_y)) { | |
641 | res = y; | |
642 | BID_RETURN (res); | |
643 | } | |
644 | res = (((sig_n_prime.w[1] > 0) | |
645 | || sig_n_prime.w[0] > sig_y) ^ ((x & MASK_SIGN) == | |
646 | MASK_SIGN)) ? x : y; | |
647 | BID_RETURN (res); | |
648 | } | |
649 | // adjust the y significand upwards | |
650 | __mul_64x64_to_128MACH (sig_n_prime, sig_y, | |
651 | mult_factor[exp_y - exp_x]); | |
652 | ||
653 | // if postitive, return whichever significand is larger (converse if negative) | |
654 | if (sig_n_prime.w[1] == 0 && (sig_n_prime.w[0] == sig_x)) { | |
655 | res = y; | |
656 | BID_RETURN (res); | |
657 | } | |
658 | res = (((sig_n_prime.w[1] == 0) | |
659 | && (sig_x > sig_n_prime.w[0])) ^ ((x & MASK_SIGN) == | |
660 | MASK_SIGN)) ? x : y; | |
661 | BID_RETURN (res); | |
662 | } | |
663 | ||
664 | /***************************************************************************** | |
665 | * BID64 maximum magnitude function - returns greater of two numbers | |
666 | *****************************************************************************/ | |
667 | ||
668 | #if DECIMAL_CALL_BY_REFERENCE | |
669 | void | |
84d1fc49 | 670 | bid64_maxnum_mag (UINT64 * pres, UINT64 * px, |
671 | UINT64 * py _EXC_FLAGS_PARAM) { | |
9b6b0236 | 672 | UINT64 x = *px; |
673 | UINT64 y = *py; | |
674 | #else | |
675 | UINT64 | |
84d1fc49 | 676 | bid64_maxnum_mag (UINT64 x, UINT64 y _EXC_FLAGS_PARAM) { |
9b6b0236 | 677 | #endif |
678 | ||
679 | UINT64 res; | |
680 | int exp_x, exp_y; | |
681 | UINT64 sig_x, sig_y; | |
682 | UINT128 sig_n_prime; | |
9b6b0236 | 683 | |
84d1fc49 | 684 | // check for non-canonical x |
685 | if ((x & MASK_NAN) == MASK_NAN) { // x is NaN | |
686 | x = x & 0xfe03ffffffffffffull; // clear G6-G12 | |
687 | if ((x & 0x0003ffffffffffffull) > 999999999999999ull) { | |
688 | x = x & 0xfe00000000000000ull; // clear G6-G12 and the payload bits | |
9b6b0236 | 689 | } |
84d1fc49 | 690 | } else if ((x & MASK_INF) == MASK_INF) { // check for Infinity |
691 | x = x & (MASK_SIGN | MASK_INF); | |
692 | } else { // x is not special | |
693 | // check for non-canonical values - treated as zero | |
694 | if ((x & MASK_STEERING_BITS) == MASK_STEERING_BITS) { | |
695 | // if the steering bits are 11, then the exponent is G[0:w+1] | |
696 | if (((x & MASK_BINARY_SIG2) | MASK_BINARY_OR2) > | |
697 | 9999999999999999ull) { | |
698 | // non-canonical | |
699 | x = (x & MASK_SIGN) | ((x & MASK_BINARY_EXPONENT2) << 2); | |
700 | } // else canonical | |
701 | } // else canonical | |
702 | } | |
703 | ||
704 | // check for non-canonical y | |
705 | if ((y & MASK_NAN) == MASK_NAN) { // y is NaN | |
706 | y = y & 0xfe03ffffffffffffull; // clear G6-G12 | |
707 | if ((y & 0x0003ffffffffffffull) > 999999999999999ull) { | |
708 | y = y & 0xfe00000000000000ull; // clear G6-G12 and the payload bits | |
709 | } | |
710 | } else if ((y & MASK_INF) == MASK_INF) { // check for Infinity | |
711 | y = y & (MASK_SIGN | MASK_INF); | |
712 | } else { // y is not special | |
713 | // check for non-canonical values - treated as zero | |
714 | if ((y & MASK_STEERING_BITS) == MASK_STEERING_BITS) { | |
715 | // if the steering bits are 11, then the exponent is G[0:w+1] | |
716 | if (((y & MASK_BINARY_SIG2) | MASK_BINARY_OR2) > | |
717 | 9999999999999999ull) { | |
718 | // non-canonical | |
719 | y = (y & MASK_SIGN) | ((y & MASK_BINARY_EXPONENT2) << 2); | |
720 | } // else canonical | |
721 | } // else canonical | |
722 | } | |
723 | ||
724 | // NaN (CASE1) | |
725 | if ((x & MASK_NAN) == MASK_NAN) { // x is NAN | |
726 | if ((x & MASK_SNAN) == MASK_SNAN) { // x is SNaN | |
727 | // if x is SNAN, then return quiet (x) | |
728 | *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN | |
729 | x = x & 0xfdffffffffffffffull; // quietize x | |
730 | res = x; | |
731 | } else { // x is QNaN | |
732 | if ((y & MASK_NAN) == MASK_NAN) { // y is NAN | |
733 | if ((y & MASK_SNAN) == MASK_SNAN) { // y is SNAN | |
734 | *pfpsf |= INVALID_EXCEPTION; // set invalid flag | |
735 | } | |
736 | res = x; | |
737 | } else { | |
738 | res = y; | |
739 | } | |
9b6b0236 | 740 | } |
9b6b0236 | 741 | BID_RETURN (res); |
84d1fc49 | 742 | } else if ((y & MASK_NAN) == MASK_NAN) { // y is NaN, but x is not |
743 | if ((y & MASK_SNAN) == MASK_SNAN) { | |
744 | *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN | |
745 | y = y & 0xfdffffffffffffffull; // quietize y | |
746 | res = y; | |
747 | } else { | |
748 | // will return x (which is not NaN) | |
749 | res = x; | |
9b6b0236 | 750 | } |
9b6b0236 | 751 | BID_RETURN (res); |
752 | } | |
753 | // SIMPLE (CASE2) | |
754 | // if all the bits are the same, these numbers are equal, return either number | |
755 | if (x == y) { | |
756 | res = x; | |
757 | BID_RETURN (res); | |
758 | } | |
759 | // INFINITY (CASE3) | |
760 | if ((x & MASK_INF) == MASK_INF) { | |
761 | // x is infinity, its magnitude is greater than or equal to y | |
762 | // return y as long as x isn't negative infinity | |
763 | res = ((x & MASK_SIGN) == MASK_SIGN | |
764 | && (y & MASK_INF) == MASK_INF) ? y : x; | |
765 | BID_RETURN (res); | |
766 | } else if ((y & MASK_INF) == MASK_INF) { | |
767 | // y is infinity, then it must be greater in magnitude | |
768 | res = y; | |
769 | BID_RETURN (res); | |
770 | } | |
771 | // if steering bits are 11 (condition will be 0), then exponent is G[0:w+1] => | |
772 | if ((x & MASK_STEERING_BITS) == MASK_STEERING_BITS) { | |
773 | exp_x = (x & MASK_BINARY_EXPONENT2) >> 51; | |
774 | sig_x = (x & MASK_BINARY_SIG2) | MASK_BINARY_OR2; | |
9b6b0236 | 775 | } else { |
776 | exp_x = (x & MASK_BINARY_EXPONENT1) >> 53; | |
777 | sig_x = (x & MASK_BINARY_SIG1); | |
9b6b0236 | 778 | } |
779 | ||
780 | // if steering bits are 11 (condition will be 0), then exponent is G[0:w+1] => | |
781 | if ((y & MASK_STEERING_BITS) == MASK_STEERING_BITS) { | |
782 | exp_y = (y & MASK_BINARY_EXPONENT2) >> 51; | |
783 | sig_y = (y & MASK_BINARY_SIG2) | MASK_BINARY_OR2; | |
9b6b0236 | 784 | } else { |
785 | exp_y = (y & MASK_BINARY_EXPONENT1) >> 53; | |
786 | sig_y = (y & MASK_BINARY_SIG1); | |
9b6b0236 | 787 | } |
788 | ||
789 | // ZERO (CASE4) | |
790 | // some properties: | |
791 | // (+ZERO == -ZERO) => therefore | |
792 | // ignore the sign, and neither number is greater | |
793 | // (ZERO x 10^A == ZERO x 10^B) for any valid A, B => | |
794 | // ignore the exponent field | |
795 | // (Any non-canonical # is considered 0) | |
84d1fc49 | 796 | if (sig_x == 0) { |
797 | res = y; // x_is_zero, its magnitude must be smaller than y | |
9b6b0236 | 798 | BID_RETURN (res); |
799 | } | |
84d1fc49 | 800 | if (sig_y == 0) { |
801 | res = x; // y_is_zero, its magnitude must be smaller than x | |
9b6b0236 | 802 | BID_RETURN (res); |
803 | } | |
804 | // REDUNDANT REPRESENTATIONS (CASE6) | |
805 | // if both components are either bigger or smaller, | |
806 | // it is clear what needs to be done | |
807 | if (sig_x > sig_y && exp_x >= exp_y) { | |
808 | res = x; | |
809 | BID_RETURN (res); | |
810 | } | |
811 | if (sig_x < sig_y && exp_x <= exp_y) { | |
812 | res = y; | |
813 | BID_RETURN (res); | |
814 | } | |
815 | // if exp_x is 15 greater than exp_y, no need for compensation | |
816 | if (exp_x - exp_y > 15) { | |
84d1fc49 | 817 | res = x; // difference cannot be greater than 10^15 |
9b6b0236 | 818 | BID_RETURN (res); |
819 | } | |
820 | // if exp_x is 15 less than exp_y, no need for compensation | |
821 | if (exp_y - exp_x > 15) { | |
822 | res = y; | |
823 | BID_RETURN (res); | |
824 | } | |
825 | // if |exp_x - exp_y| < 15, it comes down to the compensated significand | |
84d1fc49 | 826 | if (exp_x > exp_y) { // to simplify the loop below, |
9b6b0236 | 827 | // otherwise adjust the x significand upwards |
828 | __mul_64x64_to_128MACH (sig_n_prime, sig_x, | |
829 | mult_factor[exp_x - exp_y]); | |
830 | // now, sig_n_prime has: sig_x * 10^(exp_x-exp_y), | |
831 | // this is the compensated signif. | |
832 | if (sig_n_prime.w[1] == 0 && (sig_n_prime.w[0] == sig_y)) { | |
833 | // two numbers are equal, return maxNum(x,y) | |
834 | res = ((y & MASK_SIGN) == MASK_SIGN) ? x : y; | |
835 | BID_RETURN (res); | |
836 | } | |
837 | // now, if compensated_x (sig_n_prime) is greater than y return y, | |
838 | // otherwise return x | |
839 | res = ((sig_n_prime.w[1] != 0) || sig_n_prime.w[0] > sig_y) ? x : y; | |
840 | BID_RETURN (res); | |
841 | } | |
842 | // exp_y must be greater than exp_x, thus adjust the y significand upwards | |
843 | __mul_64x64_to_128MACH (sig_n_prime, sig_y, | |
844 | mult_factor[exp_y - exp_x]); | |
845 | ||
846 | if (sig_n_prime.w[1] == 0 && (sig_n_prime.w[0] == sig_x)) { | |
84d1fc49 | 847 | res = ((y & MASK_SIGN) == MASK_SIGN) ? x : y; |
848 | // two numbers are equal, return either | |
9b6b0236 | 849 | BID_RETURN (res); |
850 | } | |
851 | ||
852 | res = ((sig_n_prime.w[1] == 0) && (sig_x > sig_n_prime.w[0])) ? x : y; | |
853 | BID_RETURN (res); | |
854 | } |