UINT64 bid64_round_integral_exact (UINT64 x _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) { #endif UINT64 res = 0xbaddbaddbaddbaddull; UINT64 x_sign; int exp; // unbiased exponent // Note: C1 represents the significand (UINT64) BID_UI64DOUBLE tmp1; int x_nr_bits; int q, ind, shift; UINT64 C1; // UINT64 res is C* at first - represents up to 16 decimal digits <= 54 bits UINT128 fstar = { {0x0ull, 0x0ull} }; UINT128 P128; x_sign = x & MASK_SIGN; // 0 for positive, MASK_SIGN for negative // check for NaNs and infinities if ((x & MASK_NAN) == MASK_NAN) { // check for NaN if ((x & 0x0003ffffffffffffull) > 999999999999999ull) x = x & 0xfe00000000000000ull; // clear G6-G12 and the payload bits else x = x & 0xfe03ffffffffffffull; // clear G6-G12 if ((x & MASK_SNAN) == MASK_SNAN) { // SNaN // set invalid flag *pfpsf |= INVALID_EXCEPTION; // return quiet (SNaN) res = x & 0xfdffffffffffffffull; } else { // QNaN res = x; } BID_RETURN (res); } else if ((x & MASK_INF) == MASK_INF) { // check for Infinity res = x_sign | 0x7800000000000000ull; BID_RETURN (res); } // unpack x if ((x & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // if the steering bits are 11 (condition will be 0), then // the exponent is G[0:w+1] exp = ((x & MASK_BINARY_EXPONENT2) >> 51) - 398; C1 = (x & MASK_BINARY_SIG2) | MASK_BINARY_OR2; if (C1 > 9999999999999999ull) { // non-canonical C1 = 0; } } else { // if ((x & MASK_STEERING_BITS) != MASK_STEERING_BITS)
BID_UINT64 bid64_nextup (BID_UINT64 x _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) { #endif BID_UINT64 res; BID_UINT64 x_sign; BID_UINT64 x_exp; BID_UI64DOUBLE tmp1; int x_nr_bits; int q1, ind; BID_UINT64 C1; // C1 represents x_signif (BID_UINT64) // check for NaNs and infinities if ((x & MASK_NAN) == MASK_NAN) { // check for NaN if ((x & 0x0003ffffffffffffull) > 999999999999999ull) x = x & 0xfe00000000000000ull; // clear G6-G12 and the payload bits else x = x & 0xfe03ffffffffffffull; // clear G6-G12 if ((x & MASK_SNAN) == MASK_SNAN) { // SNaN // set invalid flag *pfpsf |= BID_INVALID_EXCEPTION; // return quiet (SNaN) res = x & 0xfdffffffffffffffull; } else { // QNaN res = x; } BID_RETURN (res); } else if ((x & MASK_INF) == MASK_INF) { // check for Infinity if (!(x & 0x8000000000000000ull)) { // x is +inf res = 0x7800000000000000ull; } else { // x is -inf res = 0xf7fb86f26fc0ffffull; // -MAXFP = -999...99 * 10^emax } BID_RETURN (res); } // unpack the argument x_sign = x & MASK_SIGN; // 0 for positive, MASK_SIGN for negative // if steering bits are 11 (condition will be 0), then exponent is G[0:w+1] => if ((x & MASK_STEERING_BITS) == MASK_STEERING_BITS) { x_exp = (x & MASK_BINARY_EXPONENT2) >> 51; // biased C1 = (x & MASK_BINARY_SIG2) | MASK_BINARY_OR2; if (C1 > 9999999999999999ull) { // non-canonical x_exp = 0; C1 = 0; } } else {
UINT64 bid64_from_uint32 (unsigned int x _EXC_MASKS_PARAM _EXC_INFO_PARAM) { #endif UINT64 res; res = x | 0x31c0000000000000ull; // (exp << 53)) = biased exp. is 0 BID_RETURN (res); }
BID_UINT32 bid32_nextup (BID_UINT32 x _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) { #endif BID_UINT32 res; BID_UINT32 x_sign; BID_UINT32 x_exp; BID_UI32FLOAT tmp1; int x_nr_bits; int q1, ind; BID_UINT32 C1; // C1 represents x_signif (BID_UINT32) // check for NaNs and infinities if ((x & MASK_NAN32) == MASK_NAN32) { // check for NaN if ((x & 0x000fffff) > 999999) x = x & 0xfe000000; // clear G6-G10 and the payload bits else x = x & 0xfe0fffff; // clear G6-G10 if ((x & MASK_SNAN32) == MASK_SNAN32) { // SNaN // set invalid flag *pfpsf |= BID_INVALID_EXCEPTION; // return quiet (SNaN) res = x & 0xfdffffff; } else { // QNaN res = x; } BID_RETURN (res); } else if ((x & MASK_INF32) == MASK_INF32) { // check for Infinity if (!(x & 0x80000000)) { // x is +inf res = 0x78000000; } else { // x is -inf res = 0xf7f8967f; // -MAXFP = -9999999 * 10^emax } BID_RETURN (res); } // unpack the argument x_sign = x & MASK_SIGN32; // 0 for positive, MASK_SIGN32 for negative // if steering bits are 11 (condition will be 0), then exponent is G[0:7] if ((x & MASK_STEERING_BITS32) == MASK_STEERING_BITS32) { x_exp = (x & MASK_BINARY_EXPONENT2_32) >> 21; // biased C1 = (x & MASK_BINARY_SIG2_32) | MASK_BINARY_OR2_32; if (C1 > 9999999) { // non-canonical x_exp = 0; C1 = 0; } } else {
UINT128 bid128_from_uint32 (unsigned int x _EXC_MASKS_PARAM _EXC_INFO_PARAM) { #endif UINT128 res; res.w[HIGH_128W] = 0x3040000000000000ull; res.w[LOW_128W] = x; BID_RETURN (res); }
UINT128 bid128_from_int32 (int x _EXC_MASKS_PARAM _EXC_INFO_PARAM) { #endif UINT128 res; // if integer is negative, use the absolute value if ((x & SIGNMASK32) == SIGNMASK32) { res.w[HIGH_128W] = 0xb040000000000000ull; res.w[LOW_128W] = ~((unsigned int) x) + 1; // 2's complement of x } else { res.w[HIGH_128W] = 0x3040000000000000ull; res.w[LOW_128W] = (unsigned int) x; } BID_RETURN (res); }
BID_UINT64 bid64_logb (BID_UINT64 x _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) { #endif int ires, exponent_x; BID_UINT64 sign_x, coefficient_x; BID_UINT64 valid_x, res; valid_x = unpack_BID64 (&sign_x, &exponent_x, &coefficient_x, x); if (!valid_x) { // test if x is NaN/Inf if ((x & 0x7800000000000000ull) == 0x7800000000000000ull) { #ifdef BID_SET_STATUS_FLAGS if ((x & 0x7e00000000000000ull) == 0x7e00000000000000ull) // sNaN __set_status_flags (pfpsf, BID_INVALID_EXCEPTION); #endif res = (coefficient_x) & QUIET_MASK64; if ((x & 0x7c00000000000000ull) == 0x7800000000000000ull) res &= 0x7fffffffffffffffull; BID_RETURN (res); } // x is 0 #ifdef BID_SET_STATUS_FLAGS __set_status_flags (pfpsf, BID_ZERO_DIVIDE_EXCEPTION); #endif res = 0xf800000000000000ull; BID_RETURN (res); } BIDECIMAL_CALL1_NORND (bid64_ilogb, ires, x); if (ires & 0x80000000) res = 0xb1c0000000000000ull | (BID_UINT64)(-ires); else res = 0x31c0000000000000ull | (BID_UINT64)ires; BID_RETURN (res); }
UINT128 bid128_from_int64 (SINT64 x _EXC_MASKS_PARAM _EXC_INFO_PARAM) { #endif UINT128 res; // if integer is negative, use the absolute value if ((x & SIGNMASK64) == SIGNMASK64) { res.w[HIGH_128W] = 0xb040000000000000ull; res.w[LOW_128W] = ~x + 1; // 2's complement of x } else { res.w[HIGH_128W] = 0x3040000000000000ull; res.w[LOW_128W] = x; } BID_RETURN (res); }
UINT64 bid64_from_int32 (int x _EXC_MASKS_PARAM _EXC_INFO_PARAM) { #endif UINT64 res; // if integer is negative, put the absolute value // in the lowest 32bits of the result if ((x & SIGNMASK32) == SIGNMASK32) { // negative int32 x = ~x + 1; // 2's complement of x res = (unsigned int) x | 0xb1c0000000000000ull; // (exp << 53)) = biased exp. is 0 } else { // positive int32 res = x | 0x31c0000000000000ull; // (exp << 53)) = biased exp. is 0 } BID_RETURN (res); }
long long int bid128_llrint (BID_UINT128 x _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) { #endif long long int res; // assume sizeof (long long) = 8 if (rnd_mode == BID_ROUNDING_TO_NEAREST) BIDECIMAL_CALL1_NORND (bid128_to_int64_xrnint, res, x); else if (rnd_mode == BID_ROUNDING_TIES_AWAY) BIDECIMAL_CALL1_NORND (bid128_to_int64_xrninta, res, x); else if (rnd_mode == BID_ROUNDING_DOWN) BIDECIMAL_CALL1_NORND (bid128_to_int64_xfloor, res, x); else if (rnd_mode == BID_ROUNDING_UP) BIDECIMAL_CALL1_NORND (bid128_to_int64_xceil, res, x); else // if (rnd_mode == BID_ROUNDING_TO_ZERO) BIDECIMAL_CALL1_NORND (bid128_to_int64_xint, res, x); BID_RETURN (res); }
BID_UINT32 bid32_sub (BID_UINT32 x, BID_UINT32 y _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) { #endif BID_UINT32 r32; #if DECIMAL_CALL_BY_REFERENCE #if !DECIMAL_GLOBAL_ROUNDING _IDEC_round rnd_mode = *prnd_mode; #endif x = *px; y = *py; #endif if (((y & NAN_MASK32) != NAN_MASK32)) y ^= 0x80000000; BIDECIMAL_CALL2 (bid32_add, r32, x, y); BID_RETURN(r32); }
UINT64 bid64_from_int64 (SINT64 x _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) { #endif UINT64 res; UINT64 x_sign, C; unsigned int q, ind; int incr_exp = 0; int is_midpoint_lt_even = 0, is_midpoint_gt_even = 0; int is_inexact_lt_midpoint = 0, is_inexact_gt_midpoint = 0; x_sign = x & 0x8000000000000000ull; // if the integer is negative, use the absolute value if (x_sign) C = ~((UINT64) x) + 1; else C = x; if (C <= BID64_SIG_MAX) { // |C| <= 10^16-1 and the result is exact if (C < 0x0020000000000000ull) { // C < 2^53 res = x_sign | 0x31c0000000000000ull | C; } else { // C >= 2^53 res = x_sign | 0x6c70000000000000ull | (C & 0x0007ffffffffffffull); } } else { // |C| >= 10^16 and the result may be inexact // the smallest |C| is 10^16 which has 17 decimal digits // the largest |C| is 0x8000000000000000 = 9223372036854775808 w/ 19 digits if (C < 0x16345785d8a0000ull) { // x < 10^17 q = 17; ind = 1; // number of digits to remove for q = 17 } else if (C < 0xde0b6b3a7640000ull) { // C < 10^18 q = 18; ind = 2; // number of digits to remove for q = 18 } else { // C < 10^19 q = 19; ind = 3; // number of digits to remove for q = 19 } // overflow and underflow are not possible // Note: performace can be improved by inlining this call round64_2_18 ( // will work for 19 digits too if C fits in 64 bits q, ind, C, &res, &incr_exp, &is_midpoint_lt_even, &is_midpoint_gt_even, &is_inexact_lt_midpoint, &is_inexact_gt_midpoint); if (incr_exp) ind++; // set the inexact flag if (is_inexact_lt_midpoint || is_inexact_gt_midpoint || is_midpoint_lt_even || is_midpoint_gt_even) *pfpsf |= INEXACT_EXCEPTION; // general correction from RN to RA, RM, RP, RZ; result uses ind for exp if (rnd_mode != ROUNDING_TO_NEAREST) { if ((!x_sign && ((rnd_mode == ROUNDING_UP && is_inexact_lt_midpoint) || ((rnd_mode == ROUNDING_TIES_AWAY || rnd_mode == ROUNDING_UP) && is_midpoint_gt_even))) || (x_sign && ((rnd_mode == ROUNDING_DOWN && is_inexact_lt_midpoint) || ((rnd_mode == ROUNDING_TIES_AWAY || rnd_mode == ROUNDING_DOWN) && is_midpoint_gt_even)))) { res = res + 1; if (res == 0x002386f26fc10000ull) { // res = 10^16 => rounding overflow res = 0x00038d7ea4c68000ull; // 10^15 ind = ind + 1; } } else if ((is_midpoint_lt_even || is_inexact_gt_midpoint) && ((x_sign && (rnd_mode == ROUNDING_UP || rnd_mode == ROUNDING_TO_ZERO)) || (!x_sign && (rnd_mode == ROUNDING_DOWN || rnd_mode == ROUNDING_TO_ZERO)))) { res = res - 1; // check if we crossed into the lower decade if (res == 0x00038d7ea4c67fffull) { // 10^15 - 1 res = 0x002386f26fc0ffffull; // 10^16 - 1 ind = ind - 1; } } else { ; // exact, the result is already correct } } if (res < 0x0020000000000000ull) { // res < 2^53 res = x_sign | (((UINT64) ind + 398) << 53) | res; } else { // res >= 2^53 res = x_sign | 0x6000000000000000ull | (((UINT64) ind + 398) << 51) | (res & 0x0007ffffffffffffull); } } BID_RETURN (res); }
UINT64 bid64_from_uint64 (UINT64 x _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) { #endif UINT64 res; UINT128 x128, res128; unsigned int q, ind; int incr_exp = 0; int is_midpoint_lt_even = 0, is_midpoint_gt_even = 0; int is_inexact_lt_midpoint = 0, is_inexact_gt_midpoint = 0; if (x <= BID64_SIG_MAX) { // x <= 10^16-1 and the result is exact if (x < 0x0020000000000000ull) { // x < 2^53 res = 0x31c0000000000000ull | x; } else { // x >= 2^53 res = 0x6c70000000000000ull | (x & 0x0007ffffffffffffull); } } else { // x >= 10^16 and the result may be inexact // the smallest x is 10^16 which has 17 decimal digits // the largest x is 0xffffffffffffffff = 18446744073709551615 w/ 20 digits if (x < 0x16345785d8a0000ull) { // x < 10^17 q = 17; ind = 1; // number of digits to remove for q = 17 } else if (x < 0xde0b6b3a7640000ull) { // x < 10^18 q = 18; ind = 2; // number of digits to remove for q = 18 } else if (x < 0x8ac7230489e80000ull) { // x < 10^19 q = 19; ind = 3; // number of digits to remove for q = 19 } else { // x < 10^20 q = 20; ind = 4; // number of digits to remove for q = 20 } // overflow and underflow are not possible // Note: performace can be improved by inlining this call if (q <= 19) { round64_2_18 ( // will work for 20 digits too if x fits in 64 bits q, ind, x, &res, &incr_exp, &is_midpoint_lt_even, &is_midpoint_gt_even, &is_inexact_lt_midpoint, &is_inexact_gt_midpoint); } else { // q = 20 x128.w[1] = 0x0; x128.w[0] = x; round128_19_38 (q, ind, x128, &res128, &incr_exp, &is_midpoint_lt_even, &is_midpoint_gt_even, &is_inexact_lt_midpoint, &is_inexact_gt_midpoint); res = res128.w[0]; // res.w[1] is 0 } if (incr_exp) ind++; // set the inexact flag if (is_inexact_lt_midpoint || is_inexact_gt_midpoint || is_midpoint_lt_even || is_midpoint_gt_even) *pfpsf |= INEXACT_EXCEPTION; // general correction from RN to RA, RM, RP, RZ; result uses ind for exp if (rnd_mode != ROUNDING_TO_NEAREST) { if ((rnd_mode == ROUNDING_UP && is_inexact_lt_midpoint) || ((rnd_mode == ROUNDING_TIES_AWAY || rnd_mode == ROUNDING_UP) && is_midpoint_gt_even)) { res = res + 1; if (res == 0x002386f26fc10000ull) { // res = 10^16 => rounding overflow res = 0x00038d7ea4c68000ull; // 10^15 ind = ind + 1; } } else if ((is_midpoint_lt_even || is_inexact_gt_midpoint) && (rnd_mode == ROUNDING_DOWN || rnd_mode == ROUNDING_TO_ZERO)) { res = res - 1; // check if we crossed into the lower decade if (res == 0x00038d7ea4c67fffull) { // 10^15 - 1 res = 0x002386f26fc0ffffull; // 10^16 - 1 ind = ind - 1; } } else { ; // exact, the result is already correct } } if (res < 0x0020000000000000ull) { // res < 2^53 res = (((UINT64) ind + 398) << 53) | res; } else { // res >= 2^53 res = 0x6000000000000000ull | (((UINT64) ind + 398) << 51) | (res & 0x0007ffffffffffffull); } } BID_RETURN (res); }
UINT64 bid64_scalb (UINT64 x, int n _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) { #endif UINT64 sign_x, coefficient_x, res; SINT64 exp64; int exponent_x, rmode; #if DECIMAL_CALL_BY_REFERENCE #if !DECIMAL_GLOBAL_ROUNDING _IDEC_round rnd_mode = *prnd_mode; #endif x = *px; n = *pn; #endif // unpack arguments, check for NaN or Infinity if (!unpack_BID64 (&sign_x, &exponent_x, &coefficient_x, x)) { // x is Inf. or NaN or 0 #ifdef SET_STATUS_FLAGS if ((x & SNAN_MASK64) == SNAN_MASK64) // y is sNaN __set_status_flags (pfpsf, INVALID_EXCEPTION); #endif if (coefficient_x) res = coefficient_x & QUIET_MASK64; else { exp64 = (SINT64) exponent_x + (SINT64) n; if(exp64<0) exp64=0; if(exp64>MAX_DECIMAL_EXPONENT) exp64=MAX_DECIMAL_EXPONENT; exponent_x = exp64; res = very_fast_get_BID64 (sign_x, exponent_x, coefficient_x); // 0 } BID_RETURN (res); } exp64 = (SINT64) exponent_x + (SINT64) n; exponent_x = exp64; if ((UINT32) exponent_x <= MAX_DECIMAL_EXPONENT) { res = very_fast_get_BID64 (sign_x, exponent_x, coefficient_x); BID_RETURN (res); } // check for overflow if (exp64 > MAX_DECIMAL_EXPONENT) { // try to normalize coefficient while ((coefficient_x < 1000000000000000ull) && (exp64 > MAX_DECIMAL_EXPONENT)) { // coefficient_x < 10^15, scale by 10 coefficient_x = (coefficient_x << 1) + (coefficient_x << 3); exponent_x--; exp64--; } if (exp64 <= MAX_DECIMAL_EXPONENT) { res = very_fast_get_BID64 (sign_x, exponent_x, coefficient_x); BID_RETURN (res); } else exponent_x = 0x7fffffff; // overflow } // exponent < 0 // the BID pack routine will round the coefficient rmode = rnd_mode; res = get_BID64 (sign_x, exponent_x, coefficient_x, rmode, pfpsf); BID_RETURN (res); }
UINT64 bid64_minnum (UINT64 x, UINT64 y _EXC_FLAGS_PARAM) { #endif UINT64 res; int exp_x, exp_y; UINT64 sig_x, sig_y; UINT128 sig_n_prime; char x_is_zero = 0, y_is_zero = 0; // check for non-canonical x if ((x & MASK_NAN) == MASK_NAN) { // x is NaN x = x & 0xfe03ffffffffffffull; // clear G6-G12 if ((x & 0x0003ffffffffffffull) > 999999999999999ull) { x = x & 0xfe00000000000000ull; // clear G6-G12 and the payload bits } } else if ((x & MASK_INF) == MASK_INF) { // check for Infinity x = x & (MASK_SIGN | MASK_INF); } else { // x is not special // check for non-canonical values - treated as zero if ((x & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // if the steering bits are 11, then the exponent is G[0:w+1] if (((x & MASK_BINARY_SIG2) | MASK_BINARY_OR2) > 9999999999999999ull) { // non-canonical x = (x & MASK_SIGN) | ((x & MASK_BINARY_EXPONENT2) << 2); } // else canonical } // else canonical } // check for non-canonical y if ((y & MASK_NAN) == MASK_NAN) { // y is NaN y = y & 0xfe03ffffffffffffull; // clear G6-G12 if ((y & 0x0003ffffffffffffull) > 999999999999999ull) { y = y & 0xfe00000000000000ull; // clear G6-G12 and the payload bits } } else if ((y & MASK_INF) == MASK_INF) { // check for Infinity y = y & (MASK_SIGN | MASK_INF); } else { // y is not special // check for non-canonical values - treated as zero if ((y & MASK_STEERING_BITS) == MASK_STEERING_BITS) { // if the steering bits are 11, then the exponent is G[0:w+1] if (((y & MASK_BINARY_SIG2) | MASK_BINARY_OR2) > 9999999999999999ull) { // non-canonical y = (y & MASK_SIGN) | ((y & MASK_BINARY_EXPONENT2) << 2); } // else canonical } // else canonical } // NaN (CASE1) if ((x & MASK_NAN) == MASK_NAN) { // x is NAN if ((x & MASK_SNAN) == MASK_SNAN) { // x is SNaN // if x is SNAN, then return quiet (x) *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN x = x & 0xfdffffffffffffffull; // quietize x res = x; } else { // x is QNaN if ((y & MASK_NAN) == MASK_NAN) { // y is NAN if ((y & MASK_SNAN) == MASK_SNAN) { // y is SNAN *pfpsf |= INVALID_EXCEPTION; // set invalid flag } res = x; } else { res = y; } } BID_RETURN (res); } else if ((y & MASK_NAN) == MASK_NAN) { // y is NaN, but x is not if ((y & MASK_SNAN) == MASK_SNAN) { *pfpsf |= INVALID_EXCEPTION; // set exception if SNaN y = y & 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, return either number if (x == y) { res = x; BID_RETURN (res); } // INFINITY (CASE3) if ((x & MASK_INF) == MASK_INF) { // if x is neg infinity, there is no way it is greater than y, return x if (((x & MASK_SIGN) == MASK_SIGN)) { res = x; BID_RETURN (res); } // x is pos infinity, return y else { res = y; BID_RETURN (res); } } else if ((y & MASK_INF) == MASK_INF) { // x is finite, so if y is positive infinity, then x is less, return y // if y is negative infinity, then x is greater, return x res = ((y & MASK_SIGN) == MASK_SIGN) ? y : x; BID_RETURN (res); } // if steering bits are 11 (condition will be 0), then exponent is G[0:w+1] => if ((x & MASK_STEERING_BITS) == MASK_STEERING_BITS) { exp_x = (x & MASK_BINARY_EXPONENT2) >> 51; sig_x = (x & MASK_BINARY_SIG2) | MASK_BINARY_OR2; } else {