mersenneforum.org

mersenneforum.org (https://www.mersenneforum.org/index.php)
-   Programming (https://www.mersenneforum.org/forumdisplay.php?f=29)
-   -   Using long long's in Mingw with 32-bit Windows XP (https://www.mersenneforum.org/showthread.php?t=12525)

grandpascorpion 2009-09-30 23:57

Using long long's in Mingw with 32-bit Windows XP
 
Hi,

I'm using Mingw version 5.1.6 within Windows XP (32-bit).

I'd like to use 64-bit integers within C code but I'm running into problems.

unsigned long z = 2*3*4*5*6*7*8*9*10*11*12;
long long unsigned int zz = z*13*14;
printf("Here is zz: %I64u\n";

After checking on-line, I found that the correct format to use is (the Microsoft-specific) %I64u, but this prints the lower 32 bits only. (Note: making [I][B]z[/B][/I] a "long long unsigned int" doesn't change the output)

==============================================

I found a different problem doing simple arithmetic:

unsigned long z = 2*3*4*5*6*7*8*9*10*11*12;
long long unsigned int zz = z*13*14;
long long unsigned int b = 175*z;
long long unsigned int c = zz-b; // 7 * factorial(12)
printf("c is %I64u\n",c);

The correct answer is only: 3353011200 (< 2^32) but this code prints out an incorrect number (18446744072767595220) that is more greater than 2^32.
//////////////////////////////////////////////////////////

Any insight would be appreciated. Thanks.

(The background is that I have some gmplib code that I wrote which I want to speed up, if possible. I think I could do so by replacing some of the "big ints" with long longs.)

R. Gerbicz 2009-10-01 00:12

"long long unsigned int" is in wrong order. I think you want:
"unsigned long long int".

And if %I64u doesn't works then try the other format: %llu. One of them should be good.

grandpascorpion 2009-10-01 00:28

Mea culpa
 
Sorry, I see my error.

I was doing calculations with an "unsigned long int" and wasn't doing an apparently necessary cast to "unsigned long long int". Both using the long long type and explicitly casting the long to it worked.

%I64u is definitely the format to use in this scenario.

And it turns out, the position of "unsigned" doesn't matter.

Thanks for your feedback though.


=====================================

Unfortunately, it looks like there isn't built-in functions to initialize/set an mpz_t to a long long.
mpz_init_set_ui(a,b) just sets a to the lower 32-bits of b.

rogue 2009-10-01 00:36

[QUOTE=R. Gerbicz;191568]"long long unsigned int" is in wrong order. I think you want:
"unsigned long long int".

And if %I64u doesn't works then try the other format: %llu. One of them should be good.[/QUOTE]

"long long int" is redundant. "long long" is sufficient. For portable code, %llu should be used.

Also if you are using MinGW, there is probably a header called stdint.h. This has a predefined uint64_t variable type.

Finally, I try to avoid using "int" because some compilers treat an int as a 16 bit value (aka short int), even though the CPU and OS are 32-bit. You could use long, which will be 32 bits or 64 bits (depending upon the compiler, OS, and compiler options). I don't know if any compiler defines a long as 16 bits. I always use stdint.h to guarantee portability. Unfortunately M$ doesn't have such a header in Visual Studio, but you can #typedef those datatypes using WORD and DWORD appropriately to ensure portability.

grandpascorpion 2009-10-01 01:03

[QUOTE=rogue;191574]"long long int" is redundant. "long long" is sufficient. For portable code, %llu should be used.

Also if you are using MinGW, there is probably a header called stdint.h. This has a predefined uint64_t variable type.

Finally, I try to avoid using "int" because some compilers treat an int as a 16 bit value (aka short int), even though the CPU and OS are 32-bit. You could use long, which will be 32 bits or 64 bits (depending upon the compiler, OS, and compiler options). I don't know if any compiler defines a long as 16 bits. I always use stdint.h to guarantee portability. Unfortunately M$ doesn't have such a header in Visual Studio, but you can #typedef those datatypes using WORD and DWORD appropriately to ensure portability.[/QUOTE]

Unfortunately, %llu doesn't work for Mingw but thanks for the stdint tip.
It's unlikely I would port it but if so I could I always have conditional compilation based on that format string.

jasonp 2009-10-01 01:26

If you include inttypes.h, you get macros to insert into format strings that will print 64-bit values correctly. On my mingw installation they are
[CODE]
inttypes.h:#define PRId64 "I64d"
inttypes.h:#define PRIi64 "I64i"
inttypes.h:#define PRIo64 "I64o"
inttypes.h:#define PRIu64 "I64u"
inttypes.h:#define PRIx64 "I64x"
inttypes.h:#define PRIX64 "I64X"
[/CODE]

Admittedly it makes the format string painful to write, i.e.

printf("I have computed %" PRId64 "\n", answer);

grandpascorpion 2009-10-01 02:14

[QUOTE=jasonp;191579]If you include inttypes.h, you get macros to insert into format strings that will print 64-bit values correctly. On my mingw installation they are
[CODE]
inttypes.h:#define PRId64 "I64d"
inttypes.h:#define PRIi64 "I64i"
inttypes.h:#define PRIo64 "I64o"
inttypes.h:#define PRIu64 "I64u"
inttypes.h:#define PRIx64 "I64x"
inttypes.h:#define PRIX64 "I64X"
[/CODE]

Admittedly it makes the format string painful to write, i.e.

printf("I have computed %" PRId64 "\n", answer);[/QUOTE]

Ugly but portable :) . Thanks.

ldesnogu 2009-10-04 12:13

[quote=jasonp;191579]If you include inttypes.h, you get macros to insert into format strings that will print 64-bit values correctly. On my mingw installation they are
[code]
inttypes.h:#define PRId64 "I64d"
inttypes.h:#define PRIi64 "I64i"
inttypes.h:#define PRIo64 "I64o"
inttypes.h:#define PRIu64 "I64u"
inttypes.h:#define PRIx64 "I64x"
inttypes.h:#define PRIX64 "I64X"
[/code]Admittedly it makes the format string painful to write, i.e.

printf("I have computed %" PRId64 "\n", answer);[/quote]
It's ugly but it has another advantage on top of working on 32-bit Windows and Linux: it will do the correct thing when you go to a 64-bit platform where a 64-bit integer is defined as a long instead of a long long (%lu vs %llu).


All times are UTC. The time now is 00:05.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.