--- /dev/null
+! { dg-do run }
+! { dg-additional-options "-fno-range-check -w" }
+!
+! Check that we can print large constants
+!
+! "-fno-range-check -w" is used so the testcase compiles even with targets
+! that don't support large integer kinds.
+
+program test
+ use iso_fortran_env, only : ikinds => integer_kinds
+ implicit none
+
+ ! Largest integer kind
+ integer, parameter :: k = ikinds(size(ikinds))
+ integer, parameter :: hk = k / 2
+
+ if (k <= 8) stop
+
+ call check(9000000000000000000_k, "9000000000000000000")
+ call check(90000000000000000000_k, "90000000000000000000")
+ call check(int(huge(1_hk), kind=k), "9223372036854775807")
+ call check(2_k**63, "9223372036854775808")
+ call check(10000000000000000000_k, "10000000000000000000")
+ call check(18446744065119617024_k, "18446744065119617024")
+ call check(2_k**64 - 1, "18446744073709551615")
+ call check(2_k**64, "18446744073709551616")
+ call check(20000000000000000000_k, "20000000000000000000")
+ call check(huge(0_k), "170141183460469231731687303715884105727")
+ call check(huge(0_k)-1, "170141183460469231731687303715884105726")
+
+ call check(-9000000000000000000_k, "-9000000000000000000")
+ call check(-90000000000000000000_k, "-90000000000000000000")
+ call check(-int(huge(1_hk), kind=k), "-9223372036854775807")
+ call check(-2_k**63, "-9223372036854775808")
+ call check(-10000000000000000000_k, "-10000000000000000000")
+ call check(-18446744065119617024_k, "-18446744065119617024")
+ call check(-(2_k**64 - 1), "-18446744073709551615")
+ call check(-2_k**64, "-18446744073709551616")
+ call check(-20000000000000000000_k, "-20000000000000000000")
+ call check(-huge(0_k), "-170141183460469231731687303715884105727")
+ call check(-(huge(0_k)-1), "-170141183460469231731687303715884105726")
+ call check(-huge(0_k)-1, "-170141183460469231731687303715884105728")
+
+ call check(2_k * huge(1_hk), "18446744073709551614")
+ call check((-2_k) * huge(1_hk), "-18446744073709551614")
+
+contains
+
+ subroutine check (i, str)
+ implicit none
+ integer(kind=k), intent(in), value :: i
+ character(len=*), intent(in) :: str
+
+ character(len=100) :: buffer
+ write(buffer,*) i
+ if (adjustl(buffer) /= adjustl(str)) call abort
+ end subroutine
+
+end
+
}
/* Determine the number of unsigned HOST_WIDE_INTs that are required
- for representing the value. The code to calculate count is
+ for representing the absolute value. The code to calculate count is
extracted from the GMP manual, section "Integer Import and Export":
http://gmplib.org/manual/Integer-Import-and-Export.html */
numb = CHAR_BIT * sizeof (HOST_WIDE_INT);
count = (mpz_sizeinbase (x, 2) + numb - 1) / numb;
HOST_WIDE_INT *val = res.write_val ();
- /* Write directly to the wide_int storage if possible, otherwise leave
+ /* Read the absolute value.
+
+ Write directly to the wide_int storage if possible, otherwise leave
GMP to allocate the memory for us. It might be slightly more efficient
to use mpz_tdiv_r_2exp for the latter case, but the situation is
pathological and it seems safer to operate on the original mpz value
memcpy (val, valres, count * sizeof (HOST_WIDE_INT));
free (valres);
}
- res.set_len (canonize (val, count, prec));
+ /* Zero-extend the absolute value to PREC bits. */
+ if (count < BLOCKS_NEEDED (prec) && val[count - 1] < 0)
+ val[count++] = 0;
+ else
+ count = canonize (val, count, prec);
+ res.set_len (count);
if (mpz_sgn (x) < 0)
res = -res;