decNumber dn, dn2, dn3;
REAL_VALUE_TYPE to;
char string[256];
+ int scale = 0;
decContextDefault (&set, DEC_INIT_DECIMAL128);
set.traps = 0;
set.round = DEC_ROUND_DOWN;
decimal128ToNumber ((const decimal128 *) r->sig, &dn);
+ if (precision > 128 && decNumberIsFinite (&dn) && dn.exponent > 19)
+ {
+ /* libdecNumber doesn't really handle too large integers.
+ So when precision is large and exponent as well, trim the
+ exponent and adjust the resulting wide_int by multiplying
+ it multiple times with 10^19. */
+ scale = dn.exponent / 19;
+ dn.exponent %= 19;
+ }
decNumberToIntegralValue (&dn2, &dn, &set);
decNumberZero (&dn3);
function. */
decNumberToString (&dn, string);
real_from_string (&to, string);
- return real_to_integer (&to, fail, precision);
+ bool failp = false;
+ wide_int w = real_to_integer (&to, &failp, precision);
+ if (failp)
+ *fail = true;
+ if (scale && !failp)
+ {
+ wide_int wm = wi::uhwi (HOST_WIDE_INT_UC (10000000000000000000),
+ w.get_precision ());
+ bool isneg = wi::neg_p (w);
+ if (isneg)
+ w = -w;
+ enum wi::overflow_type ovf = wi::OVF_NONE;
+ do
+ {
+ if (scale & 1)
+ {
+ w = wi::umul (w, wm, &ovf);
+ if (ovf)
+ break;
+ }
+ scale >>= 1;
+ if (!scale)
+ break;
+ wm = wi::umul (wm, wm, &ovf);
+ }
+ while (!ovf);
+ if (ovf)
+ {
+ *fail = true;
+ if (isneg)
+ return wi::set_bit_in_zero (precision - 1, precision);
+ else
+ return ~wi::set_bit_in_zero (precision - 1, precision);
+ }
+ if (isneg)
+ w = -w;
+ }
+ return w;
}
/* Perform the decimal floating point operation described by CODE.
static void do_fix_trunc (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
static unsigned long rtd_divmod (REAL_VALUE_TYPE *, REAL_VALUE_TYPE *);
-static void decimal_from_integer (REAL_VALUE_TYPE *);
+static void decimal_from_integer (REAL_VALUE_TYPE *, int);
static void decimal_integer_string (char *, const REAL_VALUE_TYPE *,
size_t);
}
if (fmt.decimal_p ())
- decimal_from_integer (r);
+ /* We need at most one decimal digits for each 3 bits of input
+ precision. */
+ decimal_from_integer (r, val_in.get_precision () / 3);
if (fmt)
real_convert (r, fmt, r);
}
/* Convert a real with an integral value to decimal float. */
static void
-decimal_from_integer (REAL_VALUE_TYPE *r)
+decimal_from_integer (REAL_VALUE_TYPE *r, int digits)
{
char str[256];
- decimal_integer_string (str, r, sizeof (str) - 1);
- decimal_real_from_string (r, str);
+ if (digits <= 256)
+ {
+ decimal_integer_string (str, r, sizeof (str) - 1);
+ decimal_real_from_string (r, str);
+ }
+ else
+ {
+ char *s = XALLOCAVEC (char, digits);
+ decimal_integer_string (s, r, digits - 1);
+ decimal_real_from_string (r, s);
+ }
}
/* Returns 10**2**N. */
--- /dev/null
+/* PR middle-end/120631 */
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2" } */
+
+#if __BITINT_MAXWIDTH__ >= 2048
+_Decimal128 a = 123456789135792468012345678900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0dl;
+_BitInt(2048) b = 123456789135792468012345678900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb;
+_Decimal64 c = 123456789135790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0dd;
+_BitInt(1536) d = 123456789135790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb;
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 2048
+ if (a != b || (_BitInt(2048)) a != b || c != d || (_BitInt(1536)) c != d)
+ __builtin_abort ();
+ _Decimal128 e = 123456789135792468012345678900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0dl;
+ _BitInt(2048) f = 123456789135792468012345678900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb;
+ _Decimal128 g = 123456789135792468012345678900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb;
+ _BitInt(2048) h = 123456789135792468012345678900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0dl;
+ _Decimal64 i = 123456789135790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0dd;
+ _BitInt(1536) j = 123456789135790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb;
+ _Decimal64 k = 123456789135790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb;
+ _BitInt(1536) l = 123456789135790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0dd;
+ if (e != g || f != h || i != k || j != l)
+ __builtin_abort ();
+#endif
+}