After some tinkering I was able to get Scorpio 202 compiled under linux on a 32bit machine.
To fix the uint64 problem just run this in the src directory, and run make
perl -p -i.bak -e 's/UINT64\((0x[a-fA-F0-9]*)\)/UINT64(${1}ULL)/g;' util.cpp
Compiled for me using Ubuntu, gcc/g++ 4.2.3 P4 32bit machine.
Hope that helps someone else from going grey
-Josh
Scorpio 202 Under Linux Resolved
Moderators: hgm, Rebel, chrisw
-
- Posts: 1342
- Joined: Wed Mar 08, 2006 9:41 pm
- Location: Morgantown, WV, USA
-
- Posts: 4185
- Joined: Tue Mar 14, 2006 11:34 am
- Location: Ethiopia
Re: Scorpio 202 Under Linux Resolved
Appending ULL at the end of the hash values did not work
for the 64 bit linux that why I removed it . It seems it is required for the 32 bit linux though. I will make the changes in the next version. Thanks Daniel
for the 64 bit linux that why I removed it . It seems it is required for the 32 bit linux though. I will make the changes in the next version. Thanks Daniel
-
- Posts: 750
- Joined: Mon Mar 27, 2006 7:45 pm
- Location: Finland
Re: Scorpio 202 Under Linux Resolved
What errors do you get without the ULL postfix? And are you sure you're using the latest, patched version of Scorpio 202?
ULL implies that you're using the C99 "long long" data type, which should not be used in C++ (and isn't used in the latest Scorpio beta). On my 64-bit Ubuntu machine g++ warns about it, but without the postfix there are no problems.
ULL implies that you're using the C99 "long long" data type, which should not be used in C++ (and isn't used in the latest Scorpio beta). On my 64-bit Ubuntu machine g++ warns about it, but without the postfix there are no problems.
-
- Posts: 750
- Joined: Mon Mar 27, 2006 7:45 pm
- Location: Finland
Re: Scorpio 202 Under Linux Resolved
I tried a 32-bit compile, and you were right, it doesn't compile without the ULL suffix because "long" is only 4 bytes.
However, rather than running the perl command which appends ULL to all 64-bit integer literals in util.cpp, you should change line #69 in scorpio.h from "#define UINT64" to "#define UINT64(x) (x##ULL)". Then the source compiles, but g++ warns about the use of C99 "long long". To get rid of those warnings you can pass the "-Wno-long-long" option to g++.
Sad to see that there doesn't seem to be a fully ISO C++ standard-compliant way to use 64-bit integer literals.
However, rather than running the perl command which appends ULL to all 64-bit integer literals in util.cpp, you should change line #69 in scorpio.h from "#define UINT64" to "#define UINT64(x) (x##ULL)". Then the source compiles, but g++ warns about the use of C99 "long long". To get rid of those warnings you can pass the "-Wno-long-long" option to g++.
Sad to see that there doesn't seem to be a fully ISO C++ standard-compliant way to use 64-bit integer literals.
-
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: Scorpio 202 Under Linux Resolved
The C++ standard does not specify a data type that is (at least) 64 bit wide. The existing extensions defined by compilers are (signed or unsigned) "__int64" (Microsoft) and "long long" (several other compilers). This is also the reason for the lack of a standard way to use 64 bit literals, and also 64 bit format string parts.ilari wrote:Sad to see that there doesn't seem to be a fully ISO C++ standard-compliant way to use 64-bit integer literals.
Therefore programmers who need 64 bit data types, literals, and/or format string parts should have definitions like this:
Code: Select all
#ifdef _MSC_VER
typedef signed __int64 int64;
typedef unsigned __int64 uint64;
#else
typedef signed long long int64;
typedef unsigned long long uint64;
#endif /* _MSC_VER */
#if defined(_MSC_VER) && _MSC_VER <= 1200
#define CONST64(x) (x ## i64)
#define FMT64d "I64d"
#define FMT64x "I64x"
#else
#define CONST64(x) (x ## LL)
#define FMT64d "lld"
#define FMT64x "llx"
#endif /* _MSC_VER */
Sven
-
- Posts: 750
- Joined: Mon Mar 27, 2006 7:45 pm
- Location: Finland
Re: Scorpio 202 Under Linux Resolved
Instead of "long long" I prefer to use the exact-width int64_t and uint64_t data types in stdint.h, because "long long" isn't guaranteed to be exactly 64 bits.Sven Schüle wrote:The C++ standard does not specify a data type that is (at least) 64 bit wide. The existing extensions defined by compilers are (signed or unsigned) "__int64" (Microsoft) and "long long" (several other compilers).
-
- Posts: 892
- Joined: Sun Nov 19, 2006 9:16 pm
- Location: Russia
Re: Scorpio 202 Under Linux Resolved
1) Good complier should do explicit warning when literal number do not fit into specified integer size. 1/2 of bitboards do not fit in positive signed long long int range, using two's complement negative numbers or abuse silent overflow do not guaranteed to be portable.Sven Schüle wrote:Edit: I don't know whether using some "unsigned" specifier for literals, like "ULL" instead of "LL", is really necessary. Did anybody try using "LL" (resp. "i64" for older MSVC) for 64 bit literals that have the sign bit set, and then let them appear in an unsigned context? Should be no problem, I think, the bits of the constant just don't change. I also think it is clean programming. If you write 'a' then it is always the numerical representation of an 'a' regardless whether you assign it to a char, an unsigned char, an int, or an unsigned int variable, or use it in expressions of these types. Unfortunately you need some specifier for the 64 bit width of a literal, otherwise it may be cut down to 32 bit.
2) Magic Bitboard Multiplication Keys will not work with signed multiplication operation. Even when sign overflow is not significant, using signed literals in arithmetic operations could lead to performance penalty because signed multiplication/division operations are slower then their unsigned versions.
-
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: Scorpio 202 Under Linux Resolved
Accepted, thanks for your corrections. Ad 1), unfortunately there are also "bad compilers" in this sense ... Ad 2), you're probably right concerning the slower signed multiplication. So to be safe about the desired data type for 64 bit integer literals, I should extend my definitions by adding a CONST64U macro, like in this example:Aleks Peshkov wrote:1) Good complier should do explicit warning when literal number do not fit into specified integer size. 1/2 of bitboards do not fit in positive signed long long int range, using two's complement negative numbers or abuse silent overflow do not guaranteed to be portable.Sven Schüle wrote:Edit: I don't know whether using some "unsigned" specifier for literals, like "ULL" instead of "LL", is really necessary. Did anybody try using "LL" (resp. "i64" for older MSVC) for 64 bit literals that have the sign bit set, and then let them appear in an unsigned context? Should be no problem, I think, the bits of the constant just don't change. I also think it is clean programming. If you write 'a' then it is always the numerical representation of an 'a' regardless whether you assign it to a char, an unsigned char, an int, or an unsigned int variable, or use it in expressions of these types. Unfortunately you need some specifier for the 64 bit width of a literal, otherwise it may be cut down to 32 bit.
2) Magic Bitboard Multiplication Keys will not work with signed multiplication operation. Even when sign overflow is not significant, using signed literals in arithmetic operations could lead to performance penalty because signed multiplication/division operations are slower then their unsigned versions.
Code: Select all
#if defined(_MSC_VER) && _MSC_VER <= 1200
#define CONST64(x) (x ## i64)
#define CONST64U(x) (x ## ui64)
#define FMT64d "I64d"
#define FMT64x "I64x"
#else
#define CONST64(x) (x ## LL)
#define CONST64U(x) (x ## ULL)
#define FMT64d "lld"
#define FMT64x "llx"
#endif /* _MSC_VER */
Just to fully convince me of your "magic bitboard" point: can you give a brief code example where using signed 64 bit integer literals would logically break the code for magic bitboard keys, when not considering performance issues? I definitely feel that you're right but I also would like to learn by seeing the problem in terms of "offending" code ...
Sven
-
- Posts: 892
- Joined: Sun Nov 19, 2006 9:16 pm
- Location: Russia
Re: Scorpio 202 Under Linux Resolved
I suspect that you did not explicitly turn on all warning levels. Microsoft C++ is rather verbose about signed/unsigned mismatch.Sven Schüle wrote:Ad 1), unfortunately there are also "bad compilers" in this sense ...
I vote for using unsigned literals and types everywhere instead of signed.Ad 2), you're probably right concerning the slower signed multiplication. So to be safe about the desired data type for 64 bit integer literals, I should extend my definitions by adding a CONST64U macro, like in this example:Code: Select all
#if defined(_MSC_VER) && _MSC_VER <= 1200 #define CONST64(x) (x ## i64) #define CONST64U(x) (x ## ui64) #define FMT64d "I64d" #define FMT64x "I64x" #else #define CONST64(x) (x ## LL) #define CONST64U(x) (x ## ULL) #define FMT64d "lld" #define FMT64x "llx" #endif /* _MSC_VER */
In my chess program I do not have any signed numbers, except in code comparing position evaluation scores. Intermediate evaluation gathered using a couple/quad of 16-bit unsigned registers.
Magic bitboard literals do not used directly, but stored in preinitialised array, so the array type definition matters. There are some other cases when ULL or LL may influence correctness, for example, deBruijin bitboard serialization code.Just to fully convince me of your "magic bitboard" point: can you give a brief code example where using signed 64 bit integer literals would logically break the code for magic bitboard keys, when not considering performance issues? I definitely feel that you're right but I also would like to learn by seeing the problem in terms of "offending" code ...
-
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: Scorpio 202 Under Linux Resolved
That might be the reason, although usually I have a high warning level, too (but not "-pedantic" for g++ or /W4 for MSVC++). And btw 0xffffffffffffffffLL (resp. 0xffffffffffffffffi64) is a correct literal, I think there is nothing wrong with it, and I do not know any compiler that emits a warning when this value is assigned to an unsigned 64 bit variable, or even worse, generates any bad code in this case. MSVC++ and g++ don't AFAIK. Same for 32 bit 0xffffffff (you do not need an 'u' at the end) or even 16 bit int.Aleks Peshkov wrote:I suspect that you did not explicitly turn on all warning levels. Microsoft C++ is rather verbose about signed/unsigned mismatch.Sven Schüle wrote:Ad 1), unfortunately there are also "bad compilers" in this sense ...
Code: Select all
#include <stdio.h>
int main()
{
unsigned short us = 0xffff;
signed short ss = 0xffff;
unsigned int ui = 0xffffffff;
signed int si = 0xffffffff;
unsigned long long ull = 0xffffffffffffffffLL;
signed long long sll = 0xffffffffffffffffLL;
printf("us=%u ss=%d\n", us, ss);
printf("ui=%u si=%d\n", ui, si);
printf("ull=%llu sll=%lld\n", ull, sll);
return 0;
}
Code: Select all
us=65535 ss=-1
ui=4294967295 si=-1
ull=18446744073709551615 sll=-1
I vote for using signed where appropriate, and unsigned where appropriate. And I also vote for writing code as simple as possible. Therefore I use unsigned integers for things that cannot go negative but signed integers for things that can.I vote for using unsigned literals and types everywhere instead of signed.
In my chess program I do not have any signed numbers, except in code comparing position evaluation scores. Intermediate evaluation gathered using a couple/quad of 16-bit unsigned registers.
Typical "unsigned" examples in my chess programs are square IDs (e.g. 0..127 with 0x88 board, 0..119 or 0..120 with 10x12 board, 0..63 with bitboards), piece types (0=no piece, 1=pawn, ..., 6=king), colors (e.g. 0=white, 1=black, 2=empty, 3=border), anything that counts the number of something, tells the size of something, denotes the index of something within an array or other container. Also evaluation weights, square distances, time values, ...
Typical "signed" examples are evaluation scores (for positional properties or for moves - in both cases it is most natural for me that a score can be negative) or square offsets that are added to or subtracted from a square ID to get another square ID. Here "unsigned" does not make any sense for me; of course it may make sense in other programs depending on the overall design and implementation, although I think that this might make such a program more complex.
There are at least two difficult areas where these simple and natural rules tend to make some trouble IMO. One is code where you do subtraction of unsigned integers for some reason, and the other is code where you use (system) library functions that deal with signed integers but your own code wants the corresponding variables to be unsigned. In both cases careful decisions must be taken, and I admit that I have never been successful in getting this point 100% perfectly satisfying in my code.
Sven