blob: d82b2a65a7f8e3a1b46da493a7921b74acd7e92d [file] [log] [blame]
/* 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 DECNUMDIGITS 34 // work with up to 34 digits
#include "bid_internal.h"
#include "bid_b2d.h"
UINT32
bid_to_bid32 (UINT32 ba) {
UINT32 res;
UINT32 sign, comb, exp;
UINT32 trailing;
UINT32 bcoeff;
sign = (ba & 0x80000000ul);
comb = (ba & 0x7ff00000ul) >> 20;
trailing = (ba & 0x000ffffful);
if ((comb & 0x780) == 0x780) {
ba &= 0xfff0000ul;
return ba;
} else {
if ((comb & 0x600) == 0x600) { // G0..G1 = 11 -> exp is G2..G11
exp = (comb >> 1) & 0xff;
bcoeff = ((8 + (comb & 1)) << 20) | trailing;
} else {
exp = (comb >> 3) & 0xff;
bcoeff = ((comb & 7) << 20) | trailing;
}
if (bcoeff >= 10000000)
bcoeff = 0;
res = very_fast_get_BID32 (sign, exp, bcoeff);
}
return res;
}
UINT64
bid_to_bid64 (UINT64 ba) {
UINT64 res;
UINT64 sign, comb, exp;
UINT64 trailing;
UINT64 bcoeff;
sign = (ba & 0x8000000000000000ull);
comb = (ba & 0x7ffc000000000000ull) >> 50;
trailing = (ba & 0x0003ffffffffffffull);
if ((comb & 0x1e00) == 0x1e00) {
ba &= 0xfff000000000000ULL;
return ba;
} else {
if ((comb & 0x1800) == 0x1800) { // G0..G1 = 11 -> exp is G2..G11
exp = (comb >> 1) & 0x3ff;
bcoeff = ((8 + (comb & 1)) << 50) | trailing;
} else {
exp = (comb >> 3) & 0x3ff;
bcoeff = ((comb & 7) << 50) | trailing;
}
if (bcoeff >= 10000000000000000ull)
bcoeff = 0ull;
res = very_fast_get_BID64 (sign, exp, bcoeff);
}
return res;
}
#if DECIMAL_CALL_BY_REFERENCE
void
bid_to_dpd32 (UINT32 * pres, UINT32 * pba) {
UINT32 ba = *pba;
#else
UINT32
bid_to_dpd32 (UINT32 ba) {
#endif
UINT32 res;
UINT32 sign, comb, exp, trailing;
UINT32 b0, b1, b2;
UINT32 bcoeff, dcoeff;
UINT32 nanb = 0;
sign = (ba & 0x80000000);
comb = (ba & 0x7ff00000) >> 20;
trailing = (ba & 0xfffff);
// Detect infinity, and return canonical infinity
if ((comb & 0x7c0) == 0x780) {
res = sign | 0x78000000;
BID_RETURN (res);
// Detect NaN, and canonicalize trailing
} else if ((comb & 0x7c0) == 0x7c0) {
if (trailing > 999999)
trailing = 0;
nanb = ba & 0xfe000000;
exp = 0;
bcoeff = trailing;
} else { // Normal number
if ((comb & 0x600) == 0x600) { // G0..G1 = 11 -> exp is G2..G11
exp = (comb >> 1) & 0xff;
bcoeff = ((8 + (comb & 1)) << 20) | trailing;
} else {
exp = (comb >> 3) & 0xff;
bcoeff = ((comb & 7) << 20) | trailing;
}
// Zero the coefficient if non-canonical (>= 10^7)
if (bcoeff >= 10000000)
bcoeff = 0;
}
b0 = bcoeff / 1000000;
b1 = (bcoeff / 1000) % 1000;
b2 = bcoeff % 1000;
dcoeff = (b2d[b1] << 10) | b2d[b2];
if (b0 >= 8) // is b0 8 or 9?
res =
sign |
((0x600 | ((exp >> 6) << 7) | ((b0 & 1) << 6) | (exp & 0x3f)) <<
20) | dcoeff;
else // else b0 is 0..7
res =
sign | ((((exp >> 6) << 9) | (b0 << 6) | (exp & 0x3f)) << 20) |
dcoeff;
res |= nanb;
BID_RETURN (res);
}
#if DECIMAL_CALL_BY_REFERENCE
void
bid_to_dpd64 (UINT64 * pres, UINT64 * pba) {
UINT64 ba = *pba;
#else
UINT64
bid_to_dpd64 (UINT64 ba) {
#endif
UINT64 res;
UINT64 sign, comb, exp;
UINT64 trailing;
UINT32 b0, b1, b2, b3, b4, b5;
UINT64 bcoeff;
UINT64 dcoeff;
UINT32 yhi, ylo;
UINT64 nanb = 0;
//printf("arg bid "FMT_LLX16" \n", ba);
sign = (ba & 0x8000000000000000ull);
comb = (ba & 0x7ffc000000000000ull) >> 50;
trailing = (ba & 0x0003ffffffffffffull);
// Detect infinity, and return canonical infinity
if ((comb & 0x1f00) == 0x1e00) {
res = sign | 0x7800000000000000ull;
BID_RETURN (res);
// Detect NaN, and canonicalize trailing
} else if ((comb & 0x1e00) == 0x1e00) {
if (trailing > 999999999999999ull)
trailing = 0;
nanb = ba & 0xfe00000000000000ull;
exp = 0;
bcoeff = trailing;
} else { // Normal number
if ((comb & 0x1800) == 0x1800) { // G0..G1 = 11 -> exp is G2..G11
exp = (comb >> 1) & 0x3ff;
bcoeff = ((8 + (comb & 1)) << 50) | trailing;
} else {
exp = (comb >> 3) & 0x3ff;
bcoeff = ((comb & 7) << 50) | trailing;
}
// Zero the coefficient if it is non-canonical (>= 10^16)
if (bcoeff >= 10000000000000000ull)
bcoeff = 0;
}
// Floor(2^61 / 10^9)
#define D61 (2305843009ull)
// Multipy the binary coefficient by ceil(2^64 / 1000), and take the upper
// 64-bits in order to compute a division by 1000.
#if 1
yhi =
((UINT64) D61 *
(UINT64) (UINT32) (bcoeff >> (UINT64) 27)) >> (UINT64) 34;
ylo = bcoeff - 1000000000ull * yhi;
if (ylo >= 1000000000) {
ylo = ylo - 1000000000;
yhi = yhi + 1;
}
#else
yhi = bcoeff / 1000000000ull;
ylo = bcoeff % 1000000000ull;
#endif
// yhi = ABBBCCC ylo = DDDEEEFFF
b5 = ylo % 1000; // b5 = FFF
b3 = ylo / 1000000; // b3 = DDD
b4 = (ylo / 1000) - (1000 * b3); // b4 = EEE
b2 = yhi % 1000; // b2 = CCC
b0 = yhi / 1000000; // b0 = A
b1 = (yhi / 1000) - (1000 * b0); // b1 = BBB
dcoeff = b2d[b5] | b2d2[b4] | b2d3[b3] | b2d4[b2] | b2d5[b1];
if (b0 >= 8) // is b0 8 or 9?
res =
sign |
((0x1800 | ((exp >> 8) << 9) | ((b0 & 1) << 8) | (exp & 0xff)) <<
50) | dcoeff;
else // else b0 is 0..7
res =
sign | ((((exp >> 8) << 11) | (b0 << 8) | (exp & 0xff)) << 50) |
dcoeff;
res |= nanb;
BID_RETURN (res);
}
#if DECIMAL_CALL_BY_REFERENCE
void
dpd_to_bid32 (UINT32 * pres, UINT32 * pda) {
UINT32 da = *pda;
#else
UINT32
dpd_to_bid32 (UINT32 da) {
#endif
UINT32 in = *(UINT32 *) & da;
UINT32 res;
UINT32 sign, comb, exp;
UINT32 trailing;
UINT32 d0 = 0, d1, d2;
UINT64 bcoeff;
UINT32 nanb = 0;
sign = (in & 0x80000000);
comb = (in & 0x7ff00000) >> 20;
trailing = (in & 0x000fffff);
if ((comb & 0x7e0) == 0x780) { // G0..G4 = 1111 -> Inf
res = in & 0xf8000000;
BID_RETURN (res);
} else if ((comb & 0x7c0) == 0x7c0) { // G0..G5 = 11111 -> NaN
nanb = in & 0xfe000000;
exp = 0;
} else { // Normal number
if ((comb & 0x600) == 0x600) { // G0..G1 = 11 -> d0 = 8 + G4
d0 = ((comb >> 6) & 1) | 8;
exp = ((comb & 0x180) >> 1) | (comb & 0x3f);
} else {
d0 = (comb >> 6) & 0x7;
exp = ((comb & 0x600) >> 3) | (comb & 0x3f);
}
}
d1 = d2b2[(trailing >> 10) & 0x3ff];
d2 = d2b[(trailing) & 0x3ff];
bcoeff = d2 + d1 + (1000000 * d0);
if (bcoeff < 0x800000) {
res = (exp << 23) | bcoeff | sign;
} else {
res = (exp << 21) | sign | 0x60000000 | (bcoeff & 0x1fffff);
}
res |= nanb;
BID_RETURN (res);
}
#if DECIMAL_CALL_BY_REFERENCE
void
dpd_to_bid64 (UINT64 * pres, UINT64 * pda) {
UINT64 da = *pda;
#else
UINT64
dpd_to_bid64 (UINT64 da) {
#endif
UINT64 in = *(UINT64 *) & da;
UINT64 res;
UINT64 sign, comb, exp;
UINT64 trailing;
// UINT64 d0, d1, d2, d3, d4, d5;
UINT64 d1, d2;
UINT32 d0, d3, d4, d5;
UINT64 bcoeff;
UINT64 nanb = 0;
//printf("arg dpd "FMT_LLX16" \n", in);
sign = (in & 0x8000000000000000ull);
comb = (in & 0x7ffc000000000000ull) >> 50;
trailing = (in & 0x0003ffffffffffffull);
if ((comb & 0x1f00) == 0x1e00) { // G0..G4 = 1111 -> Inf
res = in & 0xf800000000000000ull;
BID_RETURN (res);
} else if ((comb & 0x1f00) == 0x1f00) { // G0..G5 = 11111 -> NaN
nanb = in & 0xfe00000000000000ull;
exp = 0;
d0 = 0;
} else { // Normal number
if ((comb & 0x1800) == 0x1800) { // G0..G1 = 11 -> d0 = 8 + G4
d0 = ((comb >> 8) & 1) | 8;
// d0 = (comb & 0x0100 ? 9 : 8);
exp = (comb & 0x600) >> 1;
// exp = (comb & 0x0400 ? 1 : 0) * 0x200 + (comb & 0x0200 ? 1 : 0) * 0x100; // exp leading bits are G2..G3
} else {
d0 = (comb >> 8) & 0x7;
exp = (comb & 0x1800) >> 3;
// exp = (comb & 0x1000 ? 1 : 0) * 0x200 + (comb & 0x0800 ? 1 : 0) * 0x100; // exp loading bits are G0..G1
}
}
d1 = d2b5[(trailing >> 40) & 0x3ff];
d2 = d2b4[(trailing >> 30) & 0x3ff];
d3 = d2b3[(trailing >> 20) & 0x3ff];
d4 = d2b2[(trailing >> 10) & 0x3ff];
d5 = d2b[(trailing) & 0x3ff];
bcoeff = (d5 + d4 + d3) + d2 + d1 + (1000000000000000ull * d0);
exp += (comb & 0xff);
res = very_fast_get_BID64 (sign, exp, bcoeff);
res |= nanb;
BID_RETURN (res);
}
#if DECIMAL_CALL_BY_REFERENCE
void
bid_to_dpd128 (UINT128 * pres, UINT128 * pba) {
UINT128 ba = *pba;
#else
UINT128
bid_to_dpd128 (UINT128 ba) {
#endif
UINT128 res;
UINT128 sign;
UINT32 comb, exp;
UINT128 trailing;
UINT128 d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11;
UINT128 bcoeff;
UINT128 dcoeff;
UINT64 nanb = 0;
sign.w[1] = (ba.w[HIGH_128W] & 0x8000000000000000ull);
sign.w[0] = 0;
comb = (ba.w[HIGH_128W] & 0x7fffc00000000000ull) >> 46;
trailing.w[1] = (ba.w[HIGH_128W] & 0x00003fffffffffffull);
trailing.w[0] = ba.w[LOW_128W];
exp = 0;
if ((comb & 0x1f000) == 0x1e000) { // G0..G4 = 1111 -> Inf
res.w[HIGH_128W] = ba.w[HIGH_128W] & 0xf800000000000000ull;
res.w[LOW_128W] = 0;
BID_RETURN (res);
// Detect NaN, and canonicalize trailing
} else if ((comb & 0x1f000) == 0x1f000) {
if ((trailing.w[1] > 0x0000314dc6448d93ULL) || // significand is non-canonical
((trailing.w[1] == 0x0000314dc6448d93ULL)
&& (trailing.w[0] >= 0x38c15b0a00000000ULL))
// significand is non-canonical
) {
trailing.w[1] = trailing.w[0] = 0ull;
}
bcoeff.w[1] = trailing.w[1];
bcoeff.w[0] = trailing.w[0];
nanb = ba.w[HIGH_128W] & 0xfe00000000000000ull;
exp = 0;
} else { // Normal number
if ((comb & 0x18000) == 0x18000) { // G0..G1 = 11 -> exp is G2..G11
exp = (comb >> 1) & 0x3fff;
bcoeff.w[1] =
((UINT64) (8 + (comb & 1)) << (UINT64) 46) | trailing.w[1];
bcoeff.w[0] = trailing.w[0];
} else {
exp = (comb >> 3) & 0x3fff;
bcoeff.w[1] =
((UINT64) (comb & 7) << (UINT64) 46) | trailing.w[1];
bcoeff.w[0] = trailing.w[0];
}
// Zero the coefficient if non-canonical (>= 10^34)
if (bcoeff.w[1] > 0x1ed09bead87c0ull ||
(bcoeff.w[1] == 0x1ed09bead87c0ull
&& bcoeff.w[0] >= 0x378D8E6400000000ull)) {
bcoeff.w[0] = bcoeff.w[1] = 0;
}
}
// Constant 2^128 / 1000 + 1
{
UINT128 t;
UINT64 t2;
UINT128 d1000;
UINT128 b11, b10, b9, b8, b7, b6, b5, b4, b3, b2, b1;
d1000.w[1] = 0x4189374BC6A7EFull;
d1000.w[0] = 0x9DB22D0E56041894ull;
__mul_128x128_high (b11, bcoeff, d1000);
__mul_128x128_high (b10, b11, d1000);
__mul_128x128_high (b9, b10, d1000);
__mul_128x128_high (b8, b9, d1000);
__mul_128x128_high (b7, b8, d1000);
__mul_128x128_high (b6, b7, d1000);
__mul_128x128_high (b5, b6, d1000);
__mul_128x128_high (b4, b5, d1000);
__mul_128x128_high (b3, b4, d1000);
__mul_128x128_high (b2, b3, d1000);
__mul_128x128_high (b1, b2, d1000);
__mul_64x128_full (t2, t, 1000ull, b11);
__sub_128_128 (d11, bcoeff, t);
__mul_64x128_full (t2, t, 1000ull, b10);
__sub_128_128 (d10, b11, t);
__mul_64x128_full (t2, t, 1000ull, b9);
__sub_128_128 (d9, b10, t);
__mul_64x128_full (t2, t, 1000ull, b8);
__sub_128_128 (d8, b9, t);
__mul_64x128_full (t2, t, 1000ull, b7);
__sub_128_128 (d7, b8, t);
__mul_64x128_full (t2, t, 1000ull, b6);
__sub_128_128 (d6, b7, t);
__mul_64x128_full (t2, t, 1000ull, b5);
__sub_128_128 (d5, b6, t);
__mul_64x128_full (t2, t, 1000ull, b4);
__sub_128_128 (d4, b5, t);
__mul_64x128_full (t2, t, 1000ull, b3);
__sub_128_128 (d3, b4, t);
__mul_64x128_full (t2, t, 1000ull, b2);
__sub_128_128 (d2, b3, t);
__mul_64x128_full (t2, t, 1000ull, b1);
__sub_128_128 (d1, b2, t);
d0 = b1;
}
dcoeff.w[0] = b2d[d11.w[0]] | (b2d[d10.w[0]] << 10) |
(b2d[d9.w[0]] << 20) | (b2d[d8.w[0]] << 30) | (b2d[d7.w[0]] << 40) |
(b2d[d6.w[0]] << 50) | (b2d[d5.w[0]] << 60);
dcoeff.w[1] =
(b2d[d5.w[0]] >> 4) | (b2d[d4.w[0]] << 6) | (b2d[d3.w[0]] << 16) |
(b2d[d2.w[0]] << 26) | (b2d[d1.w[0]] << 36);
res.w[0] = dcoeff.w[0];
if (d0.w[0] >= 8) {
res.w[1] =
sign.
w[1] |
((0x18000 | ((exp >> 12) << 13) | ((d0.w[0] & 1) << 12) |
(exp & 0xfff)) << 46) | dcoeff.w[1];
} else {
res.w[1] =
sign.
w[1] | ((((exp >> 12) << 15) | (d0.w[0] << 12) | (exp & 0xfff))
<< 46) | dcoeff.w[1];
}
res.w[1] |= nanb;
BID_SWAP128 (res);
BID_RETURN (res);
}
#if DECIMAL_CALL_BY_REFERENCE
void
dpd_to_bid128 (UINT128 * pres, UINT128 * pda) {
UINT128 da = *pda;
#else
UINT128
dpd_to_bid128 (UINT128 da) {
#endif
UINT128 in = *(UINT128 *) & da;
UINT128 res;
UINT128 sign;
UINT64 exp, comb;
UINT128 trailing;
UINT64 d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11;
UINT128 bcoeff;
UINT64 tl, th;
UINT64 nanb = 0;
sign.w[1] = (in.w[HIGH_128W] & 0x8000000000000000ull);
sign.w[0] = 0;
comb = (in.w[HIGH_128W] & 0x7fffc00000000000ull) >> 46;
trailing.w[1] = (in.w[HIGH_128W] & 0x00003fffffffffffull);
trailing.w[0] = in.w[LOW_128W];
exp = 0;
if ((comb & 0x1f000) == 0x1e000) { // G0..G4 = 1111 -> Inf
res.w[HIGH_128W] = in.w[HIGH_128W] & 0xf800000000000000ull;
res.w[LOW_128W] = 0ull;
BID_RETURN (res);
} else if ((comb & 0x1f000) == 0x1f000) { // G0..G4 = 11111 -> NaN
nanb = in.w[HIGH_128W] & 0xfe00000000000000ull;
exp = 0;
d0 = 0;
} else { // Normal number
if ((comb & 0x18000) == 0x18000) { // G0..G1 = 11 -> d0 = 8 + G4
d0 = 8 + (comb & 0x01000 ? 1 : 0);
exp =
(comb & 0x04000 ? 1 : 0) * 0x2000 +
(comb & 0x02000 ? 1 : 0) * 0x1000;
// exp leading bits are G2..G3
} else {
d0 =
4 * (comb & 0x04000 ? 1 : 0) + 2 * (comb & 0x2000 ? 1 : 0) +
(comb & 0x1000 ? 1 : 0);
exp =
(comb & 0x10000 ? 1 : 0) * 0x2000 +
(comb & 0x08000 ? 1 : 0) * 0x1000;
// exp loading bits are G0..G1
}
}
d11 = d2b[(trailing.w[0]) & 0x3ff];
d10 = d2b[(trailing.w[0] >> 10) & 0x3ff];
d9 = d2b[(trailing.w[0] >> 20) & 0x3ff];
d8 = d2b[(trailing.w[0] >> 30) & 0x3ff];
d7 = d2b[(trailing.w[0] >> 40) & 0x3ff];
d6 = d2b[(trailing.w[0] >> 50) & 0x3ff];
d5 = d2b[(trailing.w[0] >> 60) | ((trailing.w[1] & 0x3f) << 4)];
d4 = d2b[(trailing.w[1] >> 6) & 0x3ff];
d3 = d2b[(trailing.w[1] >> 16) & 0x3ff];
d2 = d2b[(trailing.w[1] >> 26) & 0x3ff];
d1 = d2b[(trailing.w[1] >> 36) & 0x3ff];
tl =
d11 + (d10 * 1000ull) + (d9 * 1000000ull) + (d8 * 1000000000ull) +
(d7 * 1000000000000ull) + (d6 * 1000000000000000ull);
th =
d5 + (d4 * 1000ull) + (d3 * 1000000ull) + (d2 * 1000000000ull) +
(d1 * 1000000000000ull) + (d0 * 1000000000000000ull);
__mul_64x64_to_128 (bcoeff, th, 1000000000000000000ull);
__add_128_64 (bcoeff, bcoeff, tl);
if (!nanb)
exp += (comb & 0xfff);
res.w[0] = bcoeff.w[0];
res.w[1] = (exp << 49) | sign.w[1] | bcoeff.w[1];
res.w[1] |= nanb;
BID_SWAP128 (res);
BID_RETURN (res);
}
UINT128
bid_to_bid128 (UINT128 bq) {
UINT128 res;
UINT64 sign, comb, exp;
UINT64 trailing;
UINT64 bcoeff;
UINT128 rq;
UINT128 qcoeff;
UINT64 ba, bb;
ba = *((UINT64 *) & bq + HIGH_128W);
bb = *((UINT64 *) & bq + LOW_128W);
sign = (ba & 0x8000000000000000ull);
comb = (ba & 0x7fffc00000000000ull) >> 46;
trailing = (ba & 0x00003fffffffffffull);
if ((comb & 0x18000) == 0x18000) { // G0..G1 = 11 -> exp is G2..G11
exp = (comb >> 1) & 0x3fff;
bcoeff = ((8 + (comb & 1)) << 46) | trailing;
} else {
exp = (comb >> 3) & 0x3fff;
bcoeff = ((comb & 7) << 46) | trailing;
}
if ((comb & 0x1f000) == 0x1f000) { //NaN
ba &= 0xfe003fffffffffffULL; // make exponent 0
bcoeff &= 0x00003fffffffffffull; // NaN payloat is only T.
if ((bcoeff > 0x0000314dc6448d93ULL) || // significand is non-canonical
((bcoeff == 0x0000314dc6448d93ULL)
&& (bb >= 0x38c15b0a00000000ULL))
// significand is non-canonical
) {
bcoeff = 0ull;
ba &= ~0x00003fffffffffffull;
bb = 0ull;
}
*((UINT64 *) & rq + HIGH_128W) = ba;
*((UINT64 *) & rq + LOW_128W) = bb;
return rq;
} else if ((comb & 0x1e000) == 0x1e000) { //Inf
ba &= 0xf800000000000000ULL; // make exponent and significand 0
bb = 0;
*((UINT64 *) & rq + HIGH_128W) = ba;
*((UINT64 *) & rq + LOW_128W) = bb;
return rq;
}
if ((bcoeff > 0x0001ed09bead87c0ull)
|| ((bcoeff == 0x0001ed09bead87c0ull)
&& (bb > 0x378d8e63ffffffffull))) {
// significand is non-canonical
bcoeff = 0ull;
bb = 0ull;
}
*((UINT64 *) & qcoeff + 1) = bcoeff;
*((UINT64 *) & qcoeff + 0) = bb;
get_BID128_fast (&res, sign, exp, qcoeff);
BID_SWAP128 (res);
return res;
}
UINT32
bid32_canonize (UINT32 ba) {
FPSC bidrnd;
unsigned int rnd = 0;
UINT32 res;
UINT32 sign, comb, exp;
UINT32 trailing;
UINT32 bcoeff;
sign = (ba & 0x80000000);
comb = (ba & 0x7ff00000) >> 20;
trailing = (ba & 0x000fffff);
if ((comb & 0x600) == 0x600) { // G0..G1 = 11 -> exp is G2..G11
exp = (comb >> 1) & 0xff;
bcoeff = ((8 + (comb & 1)) << 20) | trailing;
} else {
exp = (comb >> 3) & 0xff;
bcoeff = ((comb & 7) << 20) | trailing;
}
if ((comb & 0x7c0) == 0x7c0) { //NaN
ba &= 0xfe0fffff; // make exponent 0
bcoeff &= 0x000fffff; // NaN payloat is only T.
if (bcoeff >= 1000000)
ba &= 0xfff00000; //treat non-canonical significand
return ba;
} else if ((comb & 0x780) == 0x780) { //Inf
ba &= 0xf8000000; // make exponent and significand 0
return ba;
}
if (bcoeff >= 10000000)
bcoeff = 0;
rnd = bidrnd = ROUNDING_TO_NEAREST;
res = get_BID32 (sign, exp, bcoeff, rnd, &bidrnd);
return res;
}
UINT64
bid64_canonize (UINT64 ba) {
UINT64 res;
UINT64 sign, comb, exp;
UINT64 trailing;
UINT64 bcoeff;
sign = (ba & 0x8000000000000000ull);
comb = (ba & 0x7ffc000000000000ull) >> 50;
trailing = (ba & 0x0003ffffffffffffull);
if ((comb & 0x1800) == 0x1800) { // G0..G1 = 11 -> exp is G2..G11
exp = (comb >> 1) & 0x3ff;
bcoeff = ((8 + (comb & 1)) << 50) | trailing;
} else {
exp = (comb >> 3) & 0x3ff;
bcoeff = ((comb & 7) << 50) | trailing;
}
if ((comb & 0x1f00) == 0x1f00) { //NaN
ba &= 0xfe03ffffffffffffULL; // make exponent 0
bcoeff &= 0x0003ffffffffffffull; // NaN payloat is only T.
if (bcoeff >= 1000000000000000ull)
ba &= 0xfe00000000000000ull; // treat non canonical significand and zero G6-G12
return ba;
} else if ((comb & 0x1e00) == 0x1e00) { //Inf
ba &= 0xf800000000000000ULL; // make exponent and significand 0
return ba;
}
if (bcoeff >= 10000000000000000ull) {
bcoeff = 0ull;
}
res = very_fast_get_BID64 (sign, exp, bcoeff);
return res;
}
UINT128
bid128_canonize (UINT128 bq) {
UINT128 res;
UINT64 sign, comb, exp;
UINT64 trailing;
UINT64 bcoeff;
UINT128 rq;
UINT128 qcoeff;
UINT64 ba, bb;
ba = *((UINT64 *) & bq + HIGH_128W);
bb = *((UINT64 *) & bq + LOW_128W);
sign = (ba & 0x8000000000000000ull);
comb = (ba & 0x7fffc00000000000ull) >> 46;
trailing = (ba & 0x00003fffffffffffull);
if ((comb & 0x18000) == 0x18000) { // G0..G1 = 11 -> exp is G2..G11
exp = (comb >> 1) & 0x3fff;
bcoeff = ((8 + (comb & 1)) << 46) | trailing;
} else {
exp = (comb >> 3) & 0x3fff;
bcoeff = ((comb & 7) << 46) | trailing;
}
if ((comb & 0x1f000) == 0x1f000) { //NaN
ba &= 0xfe003fffffffffffULL; // make exponent 0
bcoeff &= 0x00003fffffffffffull; // NaN payload is only T.
if ((bcoeff > 0x0000314dc6448d93ULL) || // significand is non-canonical
((bcoeff == 0x0000314dc6448d93ULL)
&& (bb >= 0x38c15b0a00000000ULL))
// significand is non-canonical
) {
bcoeff = 0ull;
ba &= ~0x00003fffffffffffull;
bb = 0ull;
}
*((UINT64 *) & rq + HIGH_128W) = ba;
*((UINT64 *) & rq + LOW_128W) = bb;
return rq;
} else if ((comb & 0x1e000) == 0x1e000) { //Inf
ba &= 0xf800000000000000ULL; // make exponent and significand 0
bb = 0;
*((UINT64 *) & rq + HIGH_128W) = ba;
*((UINT64 *) & rq + LOW_128W) = bb;
return rq;
}
if ((bcoeff > 0x0001ed09bead87c0ull) || // significand is non-canonical
((bcoeff == 0x0001ed09bead87c0ull)
&& (bb > 0x378d8e63ffffffffull))
// significand is non-canonical
) {
bcoeff = 0ull;
bb = 0ull;
}
*((UINT64 *) & qcoeff + 1) = bcoeff;
*((UINT64 *) & qcoeff + 0) = bb;
get_BID128_fast (&res, sign, exp, qcoeff);
BID_SWAP128 (res);
return res;
}