gcc/libgcc/config/libbid/bid128_minmax.c
H.J. Lu b2a00c8984 Makefile.in (dfp-filenames): Replace decimal_globals...
libgcc/

2007-09-27  H.J. Lu  <hongjiu.lu@intel.com>

	* Makefile.in (dfp-filenames): Replace decimal_globals,
	decimal_data, binarydecimal and convert_data with
	bid_decimal_globals, bid_decimal_data, bid_binarydecimal
	and bid_convert_data, respectively.

libgcc/config/libbid/

2007-09-27  H.J. Lu  <hongjiu.lu@intel.com>

	* bid128_fromstring.c: Removed.

	* bid_dpd.c: New from libbid 2007-09-26.
	* bid128_to_int16.c: Likewise.
	* bid128_to_int8.c: Likewise.
	* bid128_to_uint8.c: Likewise.
	* bid128_to_uint16.c: Likewise.
	* bid64_to_int16.c: Likewise.
	* bid64_to_int8.c: Likewise.
	* bid64_to_uint16.c: Likewise.
	* bid64_to_uint8.c: Likewise.

	* bid128_2_str.h: Updated from libbid 2007-09-26.
	* bid128_2_str_macros.h: Likewise.
	* bid128_2_str_tables.c: Likewise.
	* bid128_add.c: Likewise.
	* bid128.c: Likewise.
	* bid128_compare.c: Likewise.
	* bid128_div.c: Likewise.
	* bid128_fma.c: Likewise.
	* bid128_logb.c: Likewise.
	* bid128_minmax.c: Likewise.
	* bid128_mul.c: Likewise.
	* bid128_next.c: Likewise.
	* bid128_noncomp.c: Likewise.
	* bid128_quantize.c: Likewise.
	* bid128_rem.c: Likewise.
	* bid128_round_integral.c: Likewise.
	* bid128_scalb.c: Likewise.
	* bid128_sqrt.c: Likewise.
	* bid128_string.c: Likewise.
	* bid128_to_int32.c: Likewise.
	* bid128_to_int64.c: Likewise.
	* bid128_to_uint32.c: Likewise.
	* bid128_to_uint64.c: Likewise.
	* bid32_to_bid128.c: Likewise.
	* bid32_to_bid64.c: Likewise.
	* bid64_add.c: Likewise.
	* bid64_compare.c: Likewise.
	* bid64_div.c: Likewise.
	* bid64_fma.c: Likewise.
	* bid64_logb.c: Likewise.
	* bid64_minmax.c: Likewise.
	* bid64_mul.c: Likewise.
	* bid64_next.c: Likewise.
	* bid64_noncomp.c: Likewise.
	* bid64_quantize.c: Likewise.
	* bid64_rem.c: Likewise.
	* bid64_round_integral.c: Likewise.
	* bid64_scalb.c: Likewise.
	* bid64_sqrt.c: Likewise.
	* bid64_string.c: Likewise.
	* bid64_to_bid128.c: Likewise.
	* bid64_to_int32.c: Likewise.
	* bid64_to_int64.c: Likewise.
	* bid64_to_uint32.c: Likewise.
	* bid64_to_uint64.c: Likewise.
	* bid_b2d.h: Likewise.
	* bid_binarydecimal.c: Likewise.
	* bid_conf.h: Likewise.
	* bid_convert_data.c: Likewise.
	* bid_decimal_data.c: Likewise.
	* bid_decimal_globals.c: Likewise.
	* bid_div_macros.h: Likewise.
	* bid_flag_operations.c: Likewise.
	* bid_from_int.c: Likewise.
	* bid_functions.h: Likewise.
	* bid_gcc_intrinsics.h: Likewise.
	* bid_inline_add.h: Likewise.
	* bid_internal.h: Likewise.
	* bid_round.c: Likewise.
	* bid_sqrt_macros.h: Likewise.
	* _addsub_dd.c: Likewise.
	* _addsub_sd.c: Likewise.
	* _addsub_td.c: Likewise.
	* _dd_to_df.c: Likewise.
	* _dd_to_di.c: Likewise.
	* _dd_to_sd.c: Likewise.
	* _dd_to_sf.c: Likewise.
	* _dd_to_si.c: Likewise.
	* _dd_to_td.c: Likewise.
	* _dd_to_tf.c: Likewise.
	* _dd_to_udi.c: Likewise.
	* _dd_to_usi.c: Likewise.
	* _dd_to_xf.c: Likewise.
	* _df_to_dd.c: Likewise.
	* _df_to_sd.c: Likewise.
	* _df_to_td.c: Likewise.
	* _di_to_dd.c: Likewise.
	* _di_to_sd.c: Likewise.
	* _di_to_td.c: Likewise.
	* _div_dd.c: Likewise.
	* _div_sd.c: Likewise.
	* _div_td.c: Likewise.
	* _eq_dd.c: Likewise.
	* _eq_sd.c: Likewise.
	* _eq_td.c: Likewise.
	* _ge_dd.c: Likewise.
	* _ge_sd.c: Likewise.
	* _ge_td.c: Likewise.
	* _gt_dd.c: Likewise.
	* _gt_sd.c: Likewise.
	* _gt_td.c: Likewise.
	* _isinfd128.c: Likewise.
	* _isinfd32.c: Likewise.
	* _isinfd64.c: Likewise.
	* _le_dd.c: Likewise.
	* _le_sd.c: Likewise.
	* _le_td.c: Likewise.
	* _lt_dd.c: Likewise.
	* _lt_sd.c: Likewise.
	* _lt_td.c: Likewise.
	* _mul_dd.c: Likewise.
	* _mul_sd.c: Likewise.
	* _mul_td.c: Likewise.
	* _ne_dd.c: Likewise.
	* _ne_sd.c: Likewise.
	* _ne_td.c: Likewise.
	* _sd_to_dd.c: Likewise.
	* _sd_to_df.c: Likewise.
	* _sd_to_di.c: Likewise.
	* _sd_to_sf.c: Likewise.
	* _sd_to_si.c: Likewise.
	* _sd_to_td.c: Likewise.
	* _sd_to_tf.c: Likewise.
	* _sd_to_udi.c: Likewise.
	* _sd_to_usi.c: Likewise.
	* _sd_to_xf.c: Likewise.
	* _sf_to_dd.c: Likewise.
	* _sf_to_sd.c: Likewise.
	* _sf_to_td.c: Likewise.
	* _si_to_dd.c: Likewise.
	* _si_to_sd.c: Likewise.
	* _si_to_td.c: Likewise.
	* _td_to_dd.c: Likewise.
	* _td_to_df.c: Likewise.
	* _td_to_di.c: Likewise.
	* _td_to_sd.c: Likewise.
	* _td_to_sf.c: Likewise.
	* _td_to_si.c: Likewise.
	* _td_to_tf.c: Likewise.
	* _td_to_udi.c: Likewise.
	* _td_to_usi.c: Likewise.
	* _td_to_xf.c: Likewise.
	* _tf_to_dd.c: Likewise.
	* _tf_to_sd.c: Likewise.
	* _tf_to_td.c: Likewise.
	* _udi_to_dd.c: Likewise.
	* _udi_to_sd.c: Likewise.
	* _udi_to_td.c: Likewise.
	* _unord_dd.c: Likewise.
	* _unord_sd.c: Likewise.
	* _unord_td.c: Likewise.
	* _usi_to_dd.c: Likewise.
	* _usi_to_sd.c: Likewise.
	* _usi_to_td.c: Likewise.
	* _xf_to_dd.c: Likewise.
	* _xf_to_sd.c: Likewise.
	* _xf_to_td.c: Likewise.

2007-09-27  H.J. Lu  <hongjiu.lu@intel.com>

	* b2d.h: Renamed to ...
	* bid_b2d.h: This.

	* bid128_to_string.c: Renamed to ...
	* bid128_string.c: This.

	* bid_intrinsics.h: Renamed to ...
	* bid_gcc_intrinsics.h: This.

	* bid_string.c: Renamed to ...
	* bid64_string.c: This.

	* binarydecimal.c: Renamed to ...
	* bid_decimal_globals.c: This.

	* convert_data.c: Renamed to ...
	* bid_convert_data.c: This.

	* decimal_data.c: Renamed to ...
	* bid_decimal_data.c: This.

	* decimal_globals.c: Renamed to ...
	* bid_decimal_globals.c: This.

	* div_macros.h: Renamed to ...
	* bid_div_macros.h: This.

	* inline_bid_add.h: Renamed to ...
	* bid_inline_add.h: This.

	* sqrt_macros.h: Renamed to ...
	* bid_sqrt_macros.h: This.

From-SVN: r128841
2007-09-27 10:47:23 -07:00

1101 lines
38 KiB
C

/* Copyright (C) 2007 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
In addition to the permissions in the GNU General Public License, the
Free Software Foundation gives you unlimited permission to link the
compiled version of this file into combinations with other programs,
and to distribute those combinations without any restriction coming
from the use of this file. (The General Public License restrictions
do apply in other respects; for example, they cover modification of
the file, and distribution when not linked into a combine
executable.)
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA. */
#define BID_128RES
#include "bid_internal.h"
/*****************************************************************************
* BID128 minimum number
*****************************************************************************/
#if DECIMAL_CALL_BY_REFERENCE
void
bid128_minnum (UINT128 * pres, UINT128 * px,
UINT128 * py _EXC_FLAGS_PARAM) {
UINT128 x = *px;
UINT128 y = *py;
#else
UINT128
bid128_minnum (UINT128 x, UINT128 y _EXC_FLAGS_PARAM) {
#endif
UINT128 res;
int exp_x, exp_y;
int diff;
UINT128 sig_x, sig_y;
UINT192 sig_n_prime192;
UINT256 sig_n_prime256;
char x_is_zero = 0, y_is_zero = 0;
BID_SWAP128 (x);
BID_SWAP128 (y);
// check for non-canonical x
if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN
x.w[1] = x.w[1] & 0xfe003fffffffffffull; // clear out G[6]-G[16]
// check for non-canonical NaN payload
if (((x.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) ||
(((x.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull) &&
(x.w[0] > 0x38c15b09ffffffffull))) {
x.w[1] = x.w[1] & 0xffffc00000000000ull;
x.w[0] = 0x0ull;
}
} else if ((x.w[1] & MASK_ANY_INF) == MASK_INF) { // x = inf
x.w[1] = x.w[1] & (MASK_SIGN | MASK_INF);
x.w[0] = 0x0ull;
} else { // x is not special
// check for non-canonical values - treated as zero
if ((x.w[1] & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // G0_G1=11
// non-canonical
x.w[1] = (x.w[1] & MASK_SIGN) | ((x.w[1] << 2) & MASK_EXP);
x.w[0] = 0x0ull;
} else { // G0_G1 != 11
if ((x.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull ||
((x.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull
&& x.w[0] > 0x378d8e63ffffffffull)) {
// x is non-canonical if coefficient is larger than 10^34 -1
x.w[1] = (x.w[1] & MASK_SIGN) | (x.w[1] & MASK_EXP);
x.w[0] = 0x0ull;
} else { // canonical
;
}
}
}
// check for non-canonical y
if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NAN
y.w[1] = y.w[1] & 0xfe003fffffffffffull; // clear out G[6]-G[16]
// check for non-canonical NaN payload
if (((y.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) ||
(((y.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull) &&
(y.w[0] > 0x38c15b09ffffffffull))) {
y.w[1] = y.w[1] & 0xffffc00000000000ull;
y.w[0] = 0x0ull;
}
} else if ((y.w[1] & MASK_ANY_INF) == MASK_INF) { // y = inf
y.w[1] = y.w[1] & (MASK_SIGN | MASK_INF);
y.w[0] = 0x0ull;
} else { // y is not special
// check for non-canonical values - treated as zero
if ((y.w[1] & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // G0_G1=11
// non-canonical
y.w[1] = (y.w[1] & MASK_SIGN) | ((y.w[1] << 2) & MASK_EXP);
y.w[0] = 0x0ull;
} else { // G0_G1 != 11
if ((y.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull ||
((y.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull
&& y.w[0] > 0x378d8e63ffffffffull)) {
// y is non-canonical if coefficient is larger than 10^34 -1
y.w[1] = (y.w[1] & MASK_SIGN) | (y.w[1] & MASK_EXP);
y.w[0] = 0x0ull;
} else { // canonical
;
}
}
}
// NaN (CASE1)
if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN
if ((x.w[1] & MASK_SNAN) == MASK_SNAN) { // x is SNaN
// if x is SNAN, then return quiet (x)
*pfpsf |= INVALID_EXCEPTION; // set exception if SNaN
x.w[1] = x.w[1] & 0xfdffffffffffffffull; // quietize x
res = x;
} else { // x is QNaN
if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NAN
if ((y.w[1] & MASK_SNAN) == MASK_SNAN) { // y is SNAN
*pfpsf |= INVALID_EXCEPTION; // set invalid flag
}
res = x;
} else {
res = y;
}
}
BID_RETURN (res);
} else if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NaN, but x is not
if ((y.w[1] & MASK_SNAN) == MASK_SNAN) {
*pfpsf |= INVALID_EXCEPTION; // set exception if SNaN
y.w[1] = y.w[1] & 0xfdffffffffffffffull; // quietize y
res = y;
} else {
// will return x (which is not NaN)
res = x;
}
BID_RETURN (res);
}
// SIMPLE (CASE2)
// if all the bits are the same, these numbers are equal (not Greater).
if (x.w[0] == y.w[0] && x.w[1] == y.w[1]) {
res = x;
BID_RETURN (res);
}
// INFINITY (CASE3)
if ((x.w[1] & MASK_INF) == MASK_INF) {
// if x is neg infinity, there is no way it is greater than y, return 0
res = (((x.w[1] & MASK_SIGN) == MASK_SIGN)) ? x : y;
BID_RETURN (res);
} else if ((y.w[1] & MASK_INF) == MASK_INF) {
// x is finite, so if y is positive infinity, then x is less, return 0
// if y is negative infinity, then x is greater, return 1
res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x;
BID_RETURN (res);
}
// CONVERT X
sig_x.w[1] = x.w[1] & 0x0001ffffffffffffull;
sig_x.w[0] = x.w[0];
exp_x = (x.w[1] >> 49) & 0x000000000003fffull;
// CONVERT Y
exp_y = (y.w[1] >> 49) & 0x0000000000003fffull;
sig_y.w[1] = y.w[1] & 0x0001ffffffffffffull;
sig_y.w[0] = y.w[0];
// ZERO (CASE4)
// some properties:
// (+ZERO == -ZERO) => therefore ignore the sign
// (ZERO x 10^A == ZERO x 10^B) for any valid A, B => ignore the exponent
// field
// (Any non-canonical # is considered 0)
if ((sig_x.w[1] == 0) && (sig_x.w[0] == 0)) {
x_is_zero = 1;
}
if ((sig_y.w[1] == 0) && (sig_y.w[0] == 0)) {
y_is_zero = 1;
}
if (x_is_zero && y_is_zero) {
// if both numbers are zero, neither is greater => return either number
res = x;
BID_RETURN (res);
} else if (x_is_zero) {
// is x is zero, it is greater if Y is negative
res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x;
BID_RETURN (res);
} else if (y_is_zero) {
// is y is zero, X is greater if it is positive
res = ((x.w[1] & MASK_SIGN) != MASK_SIGN) ? y : x;
BID_RETURN (res);
}
// OPPOSITE SIGN (CASE5)
// now, if the sign bits differ, x is greater if y is negative
if (((x.w[1] ^ y.w[1]) & MASK_SIGN) == MASK_SIGN) {
res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x;
BID_RETURN (res);
}
// REDUNDANT REPRESENTATIONS (CASE6)
// if exponents are the same, then we have a simple comparison of
// the significands
if (exp_y == exp_x) {
res = (((sig_x.w[1] > sig_y.w[1])
|| (sig_x.w[1] == sig_y.w[1]
&& sig_x.w[0] >= sig_y.w[0])) ^ ((x.w[1] & MASK_SIGN) ==
MASK_SIGN)) ? y : x;
BID_RETURN (res);
}
// if both components are either bigger or smaller, it is clear what
// needs to be done
if (sig_x.w[1] >= sig_y.w[1] && sig_x.w[0] >= sig_y.w[0]
&& exp_x > exp_y) {
res = ((x.w[1] & MASK_SIGN) != MASK_SIGN) ? y : x;
BID_RETURN (res);
}
if (sig_x.w[1] <= sig_y.w[1] && sig_x.w[0] <= sig_y.w[0]
&& exp_x < exp_y) {
res = ((x.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x;
BID_RETURN (res);
}
diff = exp_x - exp_y;
// if |exp_x - exp_y| < 33, it comes down to the compensated significand
if (diff > 0) { // to simplify the loop below,
// if exp_x is 33 greater than exp_y, no need for compensation
if (diff > 33) {
// difference cannot be greater than 10^33
res = ((x.w[1] & MASK_SIGN) != MASK_SIGN) ? y : x;
BID_RETURN (res);
}
if (diff > 19) { //128 by 128 bit multiply -> 256 bits
__mul_128x128_to_256 (sig_n_prime256, sig_x, ten2k128[diff - 20]);
// if postitive, return whichever significand is larger
// (converse if negative)
res = ((((sig_n_prime256.w[3] > 0) || sig_n_prime256.w[2] > 0)
|| (sig_n_prime256.w[1] > sig_y.w[1])
|| (sig_n_prime256.w[1] == sig_y.w[1]
&& sig_n_prime256.w[0] >
sig_y.w[0])) ^ ((y.w[1] & MASK_SIGN) ==
MASK_SIGN)) ? y : x;
BID_RETURN (res);
}
__mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_x);
// if postitive, return whichever significand is larger
// (converse if negative)
res =
(((sig_n_prime192.w[2] > 0) || (sig_n_prime192.w[1] > sig_y.w[1])
|| (sig_n_prime192.w[1] == sig_y.w[1]
&& sig_n_prime192.w[0] >
sig_y.w[0])) ^ ((y.w[1] & MASK_SIGN) == MASK_SIGN)) ? y : x;
BID_RETURN (res);
}
diff = exp_y - exp_x;
// if exp_x is 33 less than exp_y, no need for compensation
if (diff > 33) {
res = ((x.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x;
BID_RETURN (res);
}
if (diff > 19) { //128 by 128 bit multiply -> 256 bits
// adjust the y significand upwards
__mul_128x128_to_256 (sig_n_prime256, sig_y, ten2k128[diff - 20]);
// if postitive, return whichever significand is larger
// (converse if negative)
res =
((sig_n_prime256.w[3] != 0 || sig_n_prime256.w[2] != 0
|| (sig_n_prime256.w[1] > sig_x.w[1]
|| (sig_n_prime256.w[1] == sig_x.w[1]
&& sig_n_prime256.w[0] >
sig_x.w[0]))) ^ ((x.w[1] & MASK_SIGN) ==
MASK_SIGN)) ? x : y;
BID_RETURN (res);
}
// adjust the y significand upwards
__mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_y);
// if postitive, return whichever significand is larger (converse if negative)
res =
((sig_n_prime192.w[2] != 0
|| (sig_n_prime192.w[1] > sig_x.w[1]
|| (sig_n_prime192.w[1] == sig_x.w[1]
&& sig_n_prime192.w[0] > sig_x.w[0])))
^ ((y.w[1] & MASK_SIGN) == MASK_SIGN)) ? x : y;
BID_RETURN (res);
}
/*****************************************************************************
* BID128 minimum magnitude function - returns greater of two numbers
*****************************************************************************/
#if DECIMAL_CALL_BY_REFERENCE
void
bid128_minnum_mag (UINT128 * pres, UINT128 * px,
UINT128 * py _EXC_FLAGS_PARAM) {
UINT128 x = *px;
UINT128 y = *py;
#else
UINT128
bid128_minnum_mag (UINT128 x, UINT128 y _EXC_FLAGS_PARAM) {
#endif
UINT128 res;
int exp_x, exp_y;
int diff;
UINT128 sig_x, sig_y;
UINT192 sig_n_prime192;
UINT256 sig_n_prime256;
BID_SWAP128 (x);
BID_SWAP128 (y);
// check for non-canonical x
if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN
x.w[1] = x.w[1] & 0xfe003fffffffffffull; // clear out G[6]-G[16]
// check for non-canonical NaN payload
if (((x.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) ||
(((x.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull) &&
(x.w[0] > 0x38c15b09ffffffffull))) {
x.w[1] = x.w[1] & 0xffffc00000000000ull;
x.w[0] = 0x0ull;
}
} else if ((x.w[1] & MASK_ANY_INF) == MASK_INF) { // x = inf
x.w[1] = x.w[1] & (MASK_SIGN | MASK_INF);
x.w[0] = 0x0ull;
} else { // x is not special
// check for non-canonical values - treated as zero
if ((x.w[1] & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // G0_G1=11
// non-canonical
x.w[1] = (x.w[1] & MASK_SIGN) | ((x.w[1] << 2) & MASK_EXP);
x.w[0] = 0x0ull;
} else { // G0_G1 != 11
if ((x.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull ||
((x.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull
&& x.w[0] > 0x378d8e63ffffffffull)) {
// x is non-canonical if coefficient is larger than 10^34 -1
x.w[1] = (x.w[1] & MASK_SIGN) | (x.w[1] & MASK_EXP);
x.w[0] = 0x0ull;
} else { // canonical
;
}
}
}
// check for non-canonical y
if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NAN
y.w[1] = y.w[1] & 0xfe003fffffffffffull; // clear out G[6]-G[16]
// check for non-canonical NaN payload
if (((y.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) ||
(((y.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull) &&
(y.w[0] > 0x38c15b09ffffffffull))) {
y.w[1] = y.w[1] & 0xffffc00000000000ull;
y.w[0] = 0x0ull;
}
} else if ((y.w[1] & MASK_ANY_INF) == MASK_INF) { // y = inf
y.w[1] = y.w[1] & (MASK_SIGN | MASK_INF);
y.w[0] = 0x0ull;
} else { // y is not special
// check for non-canonical values - treated as zero
if ((y.w[1] & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // G0_G1=11
// non-canonical
y.w[1] = (y.w[1] & MASK_SIGN) | ((y.w[1] << 2) & MASK_EXP);
y.w[0] = 0x0ull;
} else { // G0_G1 != 11
if ((y.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull ||
((y.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull
&& y.w[0] > 0x378d8e63ffffffffull)) {
// y is non-canonical if coefficient is larger than 10^34 -1
y.w[1] = (y.w[1] & MASK_SIGN) | (y.w[1] & MASK_EXP);
y.w[0] = 0x0ull;
} else { // canonical
;
}
}
}
// NaN (CASE1)
if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN
if ((x.w[1] & MASK_SNAN) == MASK_SNAN) { // x is SNaN
// if x is SNAN, then return quiet (x)
*pfpsf |= INVALID_EXCEPTION; // set exception if SNaN
x.w[1] = x.w[1] & 0xfdffffffffffffffull; // quietize x
res = x;
} else { // x is QNaN
if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NAN
if ((y.w[1] & MASK_SNAN) == MASK_SNAN) { // y is SNAN
*pfpsf |= INVALID_EXCEPTION; // set invalid flag
}
res = x;
} else {
res = y;
}
}
BID_RETURN (res);
} else if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NaN, but x is not
if ((y.w[1] & MASK_SNAN) == MASK_SNAN) {
*pfpsf |= INVALID_EXCEPTION; // set exception if SNaN
y.w[1] = y.w[1] & 0xfdffffffffffffffull; // quietize y
res = y;
} else {
// will return x (which is not NaN)
res = x;
}
BID_RETURN (res);
}
// SIMPLE (CASE2)
// if all the bits are the same, these numbers are equal (not Greater).
if (x.w[0] == y.w[0] && x.w[1] == y.w[1]) {
res = y;
BID_RETURN (res);
}
// INFINITY (CASE3)
if ((x.w[1] & MASK_INF) == MASK_INF) {
// if x infinity, it has maximum magnitude.
// Check if magnitudes are equal. If x is negative, return it.
res = ((x.w[1] & MASK_SIGN) == MASK_SIGN
&& (y.w[1] & MASK_INF) == MASK_INF) ? x : y;
BID_RETURN (res);
} else if ((y.w[1] & MASK_INF) == MASK_INF) {
// x is finite, so if y is infinity, then x is less in magnitude
res = x;
BID_RETURN (res);
}
// CONVERT X
sig_x.w[1] = x.w[1] & 0x0001ffffffffffffull;
sig_x.w[0] = x.w[0];
exp_x = (x.w[1] >> 49) & 0x000000000003fffull;
// CONVERT Y
exp_y = (y.w[1] >> 49) & 0x0000000000003fffull;
sig_y.w[1] = y.w[1] & 0x0001ffffffffffffull;
sig_y.w[0] = y.w[0];
// ZERO (CASE4)
// some properties:
// (+ZERO == -ZERO) => therefore ignore the sign
// (ZERO x 10^A == ZERO x 10^B) for any valid A, B =>
// therefore ignore the exponent field
// (Any non-canonical # is considered 0)
if ((sig_x.w[1] == 0) && (sig_x.w[0] == 0)) {
res = x;
BID_RETURN (res);
}
if ((sig_y.w[1] == 0) && (sig_y.w[0] == 0)) {
res = y;
BID_RETURN (res);
}
// REDUNDANT REPRESENTATIONS (CASE6)
// check if exponents are the same and significands are the same
if (exp_y == exp_x && sig_x.w[1] == sig_y.w[1]
&& sig_x.w[0] == sig_y.w[0]) {
if (x.w[1] & 0x8000000000000000ull) { // x is negative
res = x;
BID_RETURN (res);
} else {
res = y;
BID_RETURN (res);
}
} else if (((sig_x.w[1] > sig_y.w[1] || (sig_x.w[1] == sig_y.w[1]
&& sig_x.w[0] > sig_y.w[0]))
&& exp_x == exp_y)
|| ((sig_x.w[1] > sig_y.w[1]
|| (sig_x.w[1] == sig_y.w[1]
&& sig_x.w[0] >= sig_y.w[0]))
&& exp_x > exp_y)) {
// if both components are either bigger or smaller, it is clear what
// needs to be done; also if the magnitudes are equal
res = y;
BID_RETURN (res);
} else if (((sig_y.w[1] > sig_x.w[1] || (sig_y.w[1] == sig_x.w[1]
&& sig_y.w[0] > sig_x.w[0]))
&& exp_y == exp_x)
|| ((sig_y.w[1] > sig_x.w[1]
|| (sig_y.w[1] == sig_x.w[1]
&& sig_y.w[0] >= sig_x.w[0]))
&& exp_y > exp_x)) {
res = x;
BID_RETURN (res);
} else {
; // continue
}
diff = exp_x - exp_y;
// if |exp_x - exp_y| < 33, it comes down to the compensated significand
if (diff > 0) { // to simplify the loop below,
// if exp_x is 33 greater than exp_y, no need for compensation
if (diff > 33) {
res = y; // difference cannot be greater than 10^33
BID_RETURN (res);
}
if (diff > 19) { //128 by 128 bit multiply -> 256 bits
__mul_128x128_to_256 (sig_n_prime256, sig_x, ten2k128[diff - 20]);
// if positive, return whichever significand is larger
// (converse if negative)
if (sig_n_prime256.w[3] == 0 && (sig_n_prime256.w[2] == 0)
&& sig_n_prime256.w[1] == sig_y.w[1]
&& (sig_n_prime256.w[0] == sig_y.w[0])) {
res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x; // if equal
BID_RETURN (res);
}
res = (((sig_n_prime256.w[3] > 0) || sig_n_prime256.w[2] > 0)
|| (sig_n_prime256.w[1] > sig_y.w[1])
|| (sig_n_prime256.w[1] == sig_y.w[1]
&& sig_n_prime256.w[0] > sig_y.w[0])) ? y : x;
BID_RETURN (res);
}
__mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_x);
// if positive, return whichever significand is larger
// (converse if negative)
if ((sig_n_prime192.w[2] == 0) && sig_n_prime192.w[1] == sig_y.w[1]
&& (sig_n_prime192.w[0] == sig_y.w[0])) {
// if = in magnitude, return +, (if possible)
res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x;
BID_RETURN (res);
}
res = ((sig_n_prime192.w[2] > 0)
|| (sig_n_prime192.w[1] > sig_y.w[1])
|| (sig_n_prime192.w[1] == sig_y.w[1]
&& sig_n_prime192.w[0] > sig_y.w[0])) ? y : x;
BID_RETURN (res);
}
diff = exp_y - exp_x;
// if exp_x is 33 less than exp_y, no need for compensation
if (diff > 33) {
res = x;
BID_RETURN (res);
}
if (diff > 19) { //128 by 128 bit multiply -> 256 bits
// adjust the y significand upwards
__mul_128x128_to_256 (sig_n_prime256, sig_y, ten2k128[diff - 20]);
// if positive, return whichever significand is larger
// (converse if negative)
if (sig_n_prime256.w[3] == 0 && (sig_n_prime256.w[2] == 0)
&& sig_n_prime256.w[1] == sig_x.w[1]
&& (sig_n_prime256.w[0] == sig_x.w[0])) {
// if = in magnitude, return +, (if possible)
res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x;
BID_RETURN (res);
}
res = (sig_n_prime256.w[3] == 0 && sig_n_prime256.w[2] == 0
&& (sig_n_prime256.w[1] < sig_x.w[1]
|| (sig_n_prime256.w[1] == sig_x.w[1]
&& sig_n_prime256.w[0] < sig_x.w[0]))) ? y : x;
BID_RETURN (res);
}
// adjust the y significand upwards
__mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_y);
// if positive, return whichever significand is larger (converse if negative)
if ((sig_n_prime192.w[2] == 0) && sig_n_prime192.w[1] == sig_x.w[1]
&& (sig_n_prime192.w[0] == sig_x.w[0])) {
// if = in magnitude, return +, if possible)
res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x;
BID_RETURN (res);
}
res = (sig_n_prime192.w[2] == 0
&& (sig_n_prime192.w[1] < sig_x.w[1]
|| (sig_n_prime192.w[1] == sig_x.w[1]
&& sig_n_prime192.w[0] < sig_x.w[0]))) ? y : x;
BID_RETURN (res);
}
/*****************************************************************************
* BID128 maximum function - returns greater of two numbers
*****************************************************************************/
#if DECIMAL_CALL_BY_REFERENCE
void
bid128_maxnum (UINT128 * pres, UINT128 * px,
UINT128 * py _EXC_FLAGS_PARAM) {
UINT128 x = *px;
UINT128 y = *py;
#else
UINT128
bid128_maxnum (UINT128 x, UINT128 y _EXC_FLAGS_PARAM) {
#endif
UINT128 res;
int exp_x, exp_y;
int diff;
UINT128 sig_x, sig_y;
UINT192 sig_n_prime192;
UINT256 sig_n_prime256;
char x_is_zero = 0, y_is_zero = 0;
BID_SWAP128 (x);
BID_SWAP128 (y);
// check for non-canonical x
if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN
x.w[1] = x.w[1] & 0xfe003fffffffffffull; // clear out G[6]-G[16]
// check for non-canonical NaN payload
if (((x.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) ||
(((x.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull) &&
(x.w[0] > 0x38c15b09ffffffffull))) {
x.w[1] = x.w[1] & 0xffffc00000000000ull;
x.w[0] = 0x0ull;
}
} else if ((x.w[1] & MASK_ANY_INF) == MASK_INF) { // x = inf
x.w[1] = x.w[1] & (MASK_SIGN | MASK_INF);
x.w[0] = 0x0ull;
} else { // x is not special
// check for non-canonical values - treated as zero
if ((x.w[1] & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // G0_G1=11
// non-canonical
x.w[1] = (x.w[1] & MASK_SIGN) | ((x.w[1] << 2) & MASK_EXP);
x.w[0] = 0x0ull;
} else { // G0_G1 != 11
if ((x.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull ||
((x.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull
&& x.w[0] > 0x378d8e63ffffffffull)) {
// x is non-canonical if coefficient is larger than 10^34 -1
x.w[1] = (x.w[1] & MASK_SIGN) | (x.w[1] & MASK_EXP);
x.w[0] = 0x0ull;
} else { // canonical
;
}
}
}
// check for non-canonical y
if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NAN
y.w[1] = y.w[1] & 0xfe003fffffffffffull; // clear out G[6]-G[16]
// check for non-canonical NaN payload
if (((y.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) ||
(((y.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull) &&
(y.w[0] > 0x38c15b09ffffffffull))) {
y.w[1] = y.w[1] & 0xffffc00000000000ull;
y.w[0] = 0x0ull;
}
} else if ((y.w[1] & MASK_ANY_INF) == MASK_INF) { // y = inf
y.w[1] = y.w[1] & (MASK_SIGN | MASK_INF);
y.w[0] = 0x0ull;
} else { // y is not special
// check for non-canonical values - treated as zero
if ((y.w[1] & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // G0_G1=11
// non-canonical
y.w[1] = (y.w[1] & MASK_SIGN) | ((y.w[1] << 2) & MASK_EXP);
y.w[0] = 0x0ull;
} else { // G0_G1 != 11
if ((y.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull ||
((y.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull
&& y.w[0] > 0x378d8e63ffffffffull)) {
// y is non-canonical if coefficient is larger than 10^34 -1
y.w[1] = (y.w[1] & MASK_SIGN) | (y.w[1] & MASK_EXP);
y.w[0] = 0x0ull;
} else { // canonical
;
}
}
}
// NaN (CASE1)
if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN
if ((x.w[1] & MASK_SNAN) == MASK_SNAN) { // x is SNaN
// if x is SNAN, then return quiet (x)
*pfpsf |= INVALID_EXCEPTION; // set exception if SNaN
x.w[1] = x.w[1] & 0xfdffffffffffffffull; // quietize x
res = x;
} else { // x is QNaN
if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NAN
if ((y.w[1] & MASK_SNAN) == MASK_SNAN) { // y is SNAN
*pfpsf |= INVALID_EXCEPTION; // set invalid flag
}
res = x;
} else {
res = y;
}
}
BID_RETURN (res);
} else if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NaN, but x is not
if ((y.w[1] & MASK_SNAN) == MASK_SNAN) {
*pfpsf |= INVALID_EXCEPTION; // set exception if SNaN
y.w[1] = y.w[1] & 0xfdffffffffffffffull; // quietize y
res = y;
} else {
// will return x (which is not NaN)
res = x;
}
BID_RETURN (res);
}
// SIMPLE (CASE2)
// if all the bits are the same, these numbers are equal (not Greater).
if (x.w[0] == y.w[0] && x.w[1] == y.w[1]) {
res = x;
BID_RETURN (res);
}
// INFINITY (CASE3)
if ((x.w[1] & MASK_INF) == MASK_INF) {
res = ((x.w[1] & MASK_SIGN) == MASK_SIGN) ? y : x;
BID_RETURN (res);
} else if ((y.w[1] & MASK_INF) == MASK_INF) {
// x is finite, so if y is positive infinity, then x is less, return 0
// if y is negative infinity, then x is greater, return 1
res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y;
BID_RETURN (res);
}
// CONVERT X
sig_x.w[1] = x.w[1] & 0x0001ffffffffffffull;
sig_x.w[0] = x.w[0];
exp_x = (x.w[1] >> 49) & 0x000000000003fffull;
// CONVERT Y
exp_y = (y.w[1] >> 49) & 0x0000000000003fffull;
sig_y.w[1] = y.w[1] & 0x0001ffffffffffffull;
sig_y.w[0] = y.w[0];
// ZERO (CASE4)
// some properties:
// (+ZERO == -ZERO) => therefore ignore the sign
// (ZERO x 10^A == ZERO x 10^B) for any valid A, B =>
// therefore ignore the exponent field
// (Any non-canonical # is considered 0)
if ((sig_x.w[1] == 0) && (sig_x.w[0] == 0)) {
x_is_zero = 1;
}
if ((sig_y.w[1] == 0) && (sig_y.w[0] == 0)) {
y_is_zero = 1;
}
if (x_is_zero && y_is_zero) {
// if both numbers are zero, neither is greater => return either number
res = x;
BID_RETURN (res);
} else if (x_is_zero) {
// is x is zero, it is greater if Y is negative
res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y;
BID_RETURN (res);
} else if (y_is_zero) {
// is y is zero, X is greater if it is positive
res = ((x.w[1] & MASK_SIGN) != MASK_SIGN) ? x : y;
BID_RETURN (res);
}
// OPPOSITE SIGN (CASE5)
// now, if the sign bits differ, x is greater if y is negative
if (((x.w[1] ^ y.w[1]) & MASK_SIGN) == MASK_SIGN) {
res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y;
BID_RETURN (res);
}
// REDUNDANT REPRESENTATIONS (CASE6)
// if exponents are the same, then we have a simple comparison of
// the significands
if (exp_y == exp_x) {
res = (((sig_x.w[1] > sig_y.w[1]) || (sig_x.w[1] == sig_y.w[1] &&
sig_x.w[0] >= sig_y.w[0])) ^
((x.w[1] & MASK_SIGN) == MASK_SIGN)) ? x : y;
BID_RETURN (res);
}
// if both components are either bigger or smaller, it is clear what
// needs to be done
if ((sig_x.w[1] > sig_y.w[1]
|| (sig_x.w[1] == sig_y.w[1] && sig_x.w[0] > sig_y.w[0]))
&& exp_x >= exp_y) {
res = ((x.w[1] & MASK_SIGN) != MASK_SIGN) ? x : y;
BID_RETURN (res);
}
if ((sig_x.w[1] < sig_y.w[1]
|| (sig_x.w[1] == sig_y.w[1] && sig_x.w[0] < sig_y.w[0]))
&& exp_x <= exp_y) {
res = ((x.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y;
BID_RETURN (res);
}
diff = exp_x - exp_y;
// if |exp_x - exp_y| < 33, it comes down to the compensated significand
if (diff > 0) { // to simplify the loop below,
// if exp_x is 33 greater than exp_y, no need for compensation
if (diff > 33) {
// difference cannot be greater than 10^33
res = ((x.w[1] & MASK_SIGN) != MASK_SIGN) ? x : y;
BID_RETURN (res);
}
if (diff > 19) { //128 by 128 bit multiply -> 256 bits
__mul_128x128_to_256 (sig_n_prime256, sig_x, ten2k128[diff - 20]);
// if postitive, return whichever significand is larger
// (converse if negative)
res = ((((sig_n_prime256.w[3] > 0) || sig_n_prime256.w[2] > 0)
|| (sig_n_prime256.w[1] > sig_y.w[1])
|| (sig_n_prime256.w[1] == sig_y.w[1]
&& sig_n_prime256.w[0] >
sig_y.w[0])) ^ ((y.w[1] & MASK_SIGN) ==
MASK_SIGN)) ? x : y;
BID_RETURN (res);
}
__mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_x);
// if postitive, return whichever significand is larger
// (converse if negative)
res =
(((sig_n_prime192.w[2] > 0) || (sig_n_prime192.w[1] > sig_y.w[1])
|| (sig_n_prime192.w[1] == sig_y.w[1]
&& sig_n_prime192.w[0] >
sig_y.w[0])) ^ ((y.w[1] & MASK_SIGN) == MASK_SIGN)) ? x : y;
BID_RETURN (res);
}
diff = exp_y - exp_x;
// if exp_x is 33 less than exp_y, no need for compensation
if (diff > 33) {
res = ((x.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y;
BID_RETURN (res);
}
if (diff > 19) { //128 by 128 bit multiply -> 256 bits
// adjust the y significand upwards
__mul_128x128_to_256 (sig_n_prime256, sig_y, ten2k128[diff - 20]);
// if postitive, return whichever significand is larger
// (converse if negative)
res =
((sig_n_prime256.w[3] != 0 || sig_n_prime256.w[2] != 0
|| (sig_n_prime256.w[1] > sig_x.w[1]
|| (sig_n_prime256.w[1] == sig_x.w[1]
&& sig_n_prime256.w[0] >
sig_x.w[0]))) ^ ((x.w[1] & MASK_SIGN) !=
MASK_SIGN)) ? x : y;
BID_RETURN (res);
}
// adjust the y significand upwards
__mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_y);
// if postitive, return whichever significand is larger (converse if negative)
res =
((sig_n_prime192.w[2] != 0
|| (sig_n_prime192.w[1] > sig_x.w[1]
|| (sig_n_prime192.w[1] == sig_x.w[1]
&& sig_n_prime192.w[0] >
sig_x.w[0]))) ^ ((y.w[1] & MASK_SIGN) !=
MASK_SIGN)) ? x : y;
BID_RETURN (res);
}
/*****************************************************************************
* BID128 maximum magnitude function - returns greater of two numbers
*****************************************************************************/
#if DECIMAL_CALL_BY_REFERENCE
void
bid128_maxnum_mag (UINT128 * pres, UINT128 * px,
UINT128 * py _EXC_FLAGS_PARAM) {
UINT128 x = *px;
UINT128 y = *py;
#else
UINT128
bid128_maxnum_mag (UINT128 x, UINT128 y _EXC_FLAGS_PARAM) {
#endif
UINT128 res;
int exp_x, exp_y;
int diff;
UINT128 sig_x, sig_y;
UINT192 sig_n_prime192;
UINT256 sig_n_prime256;
BID_SWAP128 (x);
BID_SWAP128 (y);
// check for non-canonical x
if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN
x.w[1] = x.w[1] & 0xfe003fffffffffffull; // clear out G[6]-G[16]
// check for non-canonical NaN payload
if (((x.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) ||
(((x.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull) &&
(x.w[0] > 0x38c15b09ffffffffull))) {
x.w[1] = x.w[1] & 0xffffc00000000000ull;
x.w[0] = 0x0ull;
}
} else if ((x.w[1] & MASK_ANY_INF) == MASK_INF) { // x = inf
x.w[1] = x.w[1] & (MASK_SIGN | MASK_INF);
x.w[0] = 0x0ull;
} else { // x is not special
// check for non-canonical values - treated as zero
if ((x.w[1] & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // G0_G1=11
// non-canonical
x.w[1] = (x.w[1] & MASK_SIGN) | ((x.w[1] << 2) & MASK_EXP);
x.w[0] = 0x0ull;
} else { // G0_G1 != 11
if ((x.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull ||
((x.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull
&& x.w[0] > 0x378d8e63ffffffffull)) {
// x is non-canonical if coefficient is larger than 10^34 -1
x.w[1] = (x.w[1] & MASK_SIGN) | (x.w[1] & MASK_EXP);
x.w[0] = 0x0ull;
} else { // canonical
;
}
}
}
// check for non-canonical y
if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NAN
y.w[1] = y.w[1] & 0xfe003fffffffffffull; // clear out G[6]-G[16]
// check for non-canonical NaN payload
if (((y.w[1] & 0x00003fffffffffffull) > 0x0000314dc6448d93ull) ||
(((y.w[1] & 0x00003fffffffffffull) == 0x0000314dc6448d93ull) &&
(y.w[0] > 0x38c15b09ffffffffull))) {
y.w[1] = y.w[1] & 0xffffc00000000000ull;
y.w[0] = 0x0ull;
}
} else if ((y.w[1] & MASK_ANY_INF) == MASK_INF) { // y = inf
y.w[1] = y.w[1] & (MASK_SIGN | MASK_INF);
y.w[0] = 0x0ull;
} else { // y is not special
// check for non-canonical values - treated as zero
if ((y.w[1] & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // G0_G1=11
// non-canonical
y.w[1] = (y.w[1] & MASK_SIGN) | ((y.w[1] << 2) & MASK_EXP);
y.w[0] = 0x0ull;
} else { // G0_G1 != 11
if ((y.w[1] & MASK_COEFF) > 0x0001ed09bead87c0ull ||
((y.w[1] & MASK_COEFF) == 0x0001ed09bead87c0ull &&
y.w[0] > 0x378d8e63ffffffffull)) {
// y is non-canonical if coefficient is larger than 10^34 -1
y.w[1] = (y.w[1] & MASK_SIGN) | (y.w[1] & MASK_EXP);
y.w[0] = 0x0ull;
} else { // canonical
;
}
}
}
// NaN (CASE1)
if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN
if ((x.w[1] & MASK_SNAN) == MASK_SNAN) { // x is SNaN
// if x is SNAN, then return quiet (x)
*pfpsf |= INVALID_EXCEPTION; // set exception if SNaN
x.w[1] = x.w[1] & 0xfdffffffffffffffull; // quietize x
res = x;
} else { // x is QNaN
if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NAN
if ((y.w[1] & MASK_SNAN) == MASK_SNAN) { // y is SNAN
*pfpsf |= INVALID_EXCEPTION; // set invalid flag
}
res = x;
} else {
res = y;
}
}
BID_RETURN (res);
} else if ((y.w[1] & MASK_NAN) == MASK_NAN) { // y is NaN, but x is not
if ((y.w[1] & MASK_SNAN) == MASK_SNAN) {
*pfpsf |= INVALID_EXCEPTION; // set exception if SNaN
y.w[1] = y.w[1] & 0xfdffffffffffffffull; // quietize y
res = y;
} else {
// will return x (which is not NaN)
res = x;
}
BID_RETURN (res);
}
// SIMPLE (CASE2)
// if all the bits are the same, these numbers are equal (not Greater).
if (x.w[0] == y.w[0] && x.w[1] == y.w[1]) {
res = y;
BID_RETURN (res);
}
// INFINITY (CASE3)
if ((x.w[1] & MASK_INF) == MASK_INF) {
// if x infinity, it has maximum magnitude
res = ((x.w[1] & MASK_SIGN) == MASK_SIGN
&& (y.w[1] & MASK_INF) == MASK_INF) ? y : x;
BID_RETURN (res);
} else if ((y.w[1] & MASK_INF) == MASK_INF) {
// x is finite, so if y is positive infinity, then x is less, return 0
// if y is negative infinity, then x is greater, return 1
res = y;
BID_RETURN (res);
}
// CONVERT X
sig_x.w[1] = x.w[1] & 0x0001ffffffffffffull;
sig_x.w[0] = x.w[0];
exp_x = (x.w[1] >> 49) & 0x000000000003fffull;
// CONVERT Y
exp_y = (y.w[1] >> 49) & 0x0000000000003fffull;
sig_y.w[1] = y.w[1] & 0x0001ffffffffffffull;
sig_y.w[0] = y.w[0];
// ZERO (CASE4)
// some properties:
// (+ZERO == -ZERO) => therefore ignore the sign
// (ZERO x 10^A == ZERO x 10^B) for any valid A, B =>
// therefore ignore the exponent field
// (Any non-canonical # is considered 0)
if ((sig_x.w[1] == 0) && (sig_x.w[0] == 0)) {
res = y;
BID_RETURN (res);
}
if ((sig_y.w[1] == 0) && (sig_y.w[0] == 0)) {
res = x;
BID_RETURN (res);
}
// REDUNDANT REPRESENTATIONS (CASE6)
if (exp_y == exp_x && sig_x.w[1] == sig_y.w[1]
&& sig_x.w[0] == sig_y.w[0]) {
// check if exponents are the same and significands are the same
if (x.w[1] & 0x8000000000000000ull) { // x is negative
res = y;
BID_RETURN (res);
} else {
res = x;
BID_RETURN (res);
}
} else if (((sig_x.w[1] > sig_y.w[1] || (sig_x.w[1] == sig_y.w[1]
&& sig_x.w[0] > sig_y.w[0]))
&& exp_x == exp_y)
|| ((sig_x.w[1] > sig_y.w[1]
|| (sig_x.w[1] == sig_y.w[1]
&& sig_x.w[0] >= sig_y.w[0]))
&& exp_x > exp_y)) {
// if both components are either bigger or smaller, it is clear what
// needs to be done; also if the magnitudes are equal
res = x;
BID_RETURN (res);
} else if (((sig_y.w[1] > sig_x.w[1] || (sig_y.w[1] == sig_x.w[1]
&& sig_y.w[0] > sig_x.w[0]))
&& exp_y == exp_x)
|| ((sig_y.w[1] > sig_x.w[1]
|| (sig_y.w[1] == sig_x.w[1]
&& sig_y.w[0] >= sig_x.w[0]))
&& exp_y > exp_x)) {
res = y;
BID_RETURN (res);
} else {
; // continue
}
diff = exp_x - exp_y;
// if |exp_x - exp_y| < 33, it comes down to the compensated significand
if (diff > 0) { // to simplify the loop below,
// if exp_x is 33 greater than exp_y, no need for compensation
if (diff > 33) {
res = x; // difference cannot be greater than 10^33
BID_RETURN (res);
}
if (diff > 19) { //128 by 128 bit multiply -> 256 bits
__mul_128x128_to_256 (sig_n_prime256, sig_x, ten2k128[diff - 20]);
// if postitive, return whichever significand is larger
// (converse if negative)
if (sig_n_prime256.w[3] == 0 && (sig_n_prime256.w[2] == 0)
&& sig_n_prime256.w[1] == sig_y.w[1]
&& (sig_n_prime256.w[0] == sig_y.w[0])) {
res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y; // if equal
BID_RETURN (res);
}
res = (((sig_n_prime256.w[3] > 0) || sig_n_prime256.w[2] > 0)
|| (sig_n_prime256.w[1] > sig_y.w[1])
|| (sig_n_prime256.w[1] == sig_y.w[1]
&& sig_n_prime256.w[0] > sig_y.w[0])) ? x : y;
BID_RETURN (res);
}
__mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_x);
// if postitive, return whichever significand is larger (converse if negative)
if ((sig_n_prime192.w[2] == 0) && sig_n_prime192.w[1] == sig_y.w[1]
&& (sig_n_prime192.w[0] == sig_y.w[0])) {
// if equal, return positive magnitude
res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y;
BID_RETURN (res);
}
res = ((sig_n_prime192.w[2] > 0)
|| (sig_n_prime192.w[1] > sig_y.w[1])
|| (sig_n_prime192.w[1] == sig_y.w[1]
&& sig_n_prime192.w[0] > sig_y.w[0])) ? x : y;
BID_RETURN (res);
}
diff = exp_y - exp_x;
// if exp_x is 33 less than exp_y, no need for compensation
if (diff > 33) {
res = y;
BID_RETURN (res);
}
if (diff > 19) { //128 by 128 bit multiply -> 256 bits
// adjust the y significand upwards
__mul_128x128_to_256 (sig_n_prime256, sig_y, ten2k128[diff - 20]);
// if postitive, return whichever significand is larger
// (converse if negative)
if (sig_n_prime256.w[3] == 0 && (sig_n_prime256.w[2] == 0)
&& sig_n_prime256.w[1] == sig_x.w[1]
&& (sig_n_prime256.w[0] == sig_x.w[0])) {
// if equal, return positive (if possible)
res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y;
BID_RETURN (res);
}
res = (sig_n_prime256.w[3] == 0 && sig_n_prime256.w[2] == 0
&& (sig_n_prime256.w[1] < sig_x.w[1]
|| (sig_n_prime256.w[1] == sig_x.w[1]
&& sig_n_prime256.w[0] < sig_x.w[0]))) ? x : y;
BID_RETURN (res);
}
// adjust the y significand upwards
__mul_64x128_to_192 (sig_n_prime192, ten2k64[diff], sig_y);
// if postitive, return whichever significand is larger (converse if negative)
if ((sig_n_prime192.w[2] == 0) && sig_n_prime192.w[1] == sig_x.w[1]
&& (sig_n_prime192.w[0] == sig_x.w[0])) {
// if equal, return positive (if possible)
res = ((y.w[1] & MASK_SIGN) == MASK_SIGN) ? x : y;
BID_RETURN (res);
}
res = (sig_n_prime192.w[2] == 0
&& (sig_n_prime192.w[1] < sig_x.w[1]
|| (sig_n_prime192.w[1] == sig_x.w[1]
&& sig_n_prime192.w[0] < sig_x.w[0]))) ? x : y;
BID_RETURN (res);
}