/* 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;
}
