Problem with mpz_tstbit on Windows...

wraithx at morpheus.net wraithx at morpheus.net
Sat Feb 4 19:08:51 UTC 2017


Hello all,

I recently found out that mpz_tstbit does not always work as expected on 
Windows.  I found this out while using GMP 6.1.1, but looking at the source, it 
seems like this problem has been around since at least GMP 4.x up to GMP 6.x. 
The problem occurs when passing a 64-bit index into mpz_tstbit.  Since the 
function uses an unsigned long for the index, the index is truncated to 32-bits 
on Windows computers and will return incorrect results when the index is >= 2^32.

I am providing a small test case that shows the problem I am experiencing.  I 
compiled this with the MinGW-W64 toolchain, inside an msys shell.  Here is some 
system info:

gcc -v = gcc version 5.3.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)
uname -a = MINGW32_NT-6.1 HOLMES 1.0.17(0.48/3/2) 2011-04-24 23:39 i686 Msys
./config.guess = i686-pc-mingw32
I call "./configure" with no options
./configure actually recognizes the computer as broadwell-pc-mingw32
CFLAGS='-O2 -pedantic -fomit-frame-pointer -m64 -mtune=broadwell -march=broadwell'

I compiled my test program, included at the end of this email, with:
gcc -o a.exe test.c -lgmp

Which gives the following output:
num bits in num3 = 4300000000
bit 4294967290 : mpz_tstbit = 1
bit 4294967291 : mpz_tstbit = 1
bit 4294967292 : mpz_tstbit = 1
bit 4294967293 : mpz_tstbit = 1
bit 4294967294 : mpz_tstbit = 1
bit 4294967295 : mpz_tstbit = 1
bit 4294967296 : mpz_tstbit = 0
bit 4294967297 : mpz_tstbit = 0
bit 4294967298 : mpz_tstbit = 0
bit 4294967299 : mpz_tstbit = 0

The variable num3 has its most significant 4.2e9 bits all equal to 1.  The least 
significant 100e6 bits are all 0.  Thus, the output above should all report 
"mpz_tstbit = 1".  The lines reporting "mpz_tstbit = 0" are in error.  Thank you 
for your time.  Please let me know if you need any additional information.

-David C.

#include <stdio.h>
#include <gmp.h>

int main(void) {
   mpz_t num1, num2, num3;
   unsigned long long i = 4294967290, j = 0;

   mpz_init_set_ui(num1, 1);
   mpz_init_set_ui(num2, 1);
   mpz_init(num3);

   mpz_mul_2exp(num1, num1, 4200000000);
   mpz_sub_ui(num1, num1, 1);
   mpz_mul_2exp(num2, num2,  100000000);
   mpz_mul(num3, num1, num2);

   printf("num bits in num3 = %llu\n", mpz_sizeinbase(num3, 2));

   for (j = 0; j < 10; j++)
     printf("bit %llu : mpz_tstbit = %d\n", i+j, mpz_tstbit(num3, i+j));

   return 0;
}


More information about the gmp-bugs mailing list