Scorpio 202 Under Linux Resolved

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
jshriver
Posts: 1342
Joined: Wed Mar 08, 2006 9:41 pm
Location: Morgantown, WV, USA

Scorpio 202 Under Linux Resolved

Post by jshriver »

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
Daniel Shawul
Posts: 4185
Joined: Tue Mar 14, 2006 11:34 am
Location: Ethiopia

Re: Scorpio 202 Under Linux Resolved

Post by Daniel Shawul »

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
User avatar
ilari
Posts: 750
Joined: Mon Mar 27, 2006 7:45 pm
Location: Finland

Re: Scorpio 202 Under Linux Resolved

Post by ilari »

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.
User avatar
ilari
Posts: 750
Joined: Mon Mar 27, 2006 7:45 pm
Location: Finland

Re: Scorpio 202 Under Linux Resolved

Post by ilari »

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.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Scorpio 202 Under Linux Resolved

Post by Sven »

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.
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.

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&#40;_MSC_VER&#41; && _MSC_VER <= 1200
#define CONST64&#40;x&#41;  &#40;x ## i64&#41;
#define FMT64d      "I64d"
#define FMT64x      "I64x"
#else
#define CONST64&#40;x&#41; &#40;x ## LL&#41;
#define FMT64d      "lld"
#define FMT64x      "llx"
#endif /* _MSC_VER */
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.

Sven
User avatar
ilari
Posts: 750
Joined: Mon Mar 27, 2006 7:45 pm
Location: Finland

Re: Scorpio 202 Under Linux Resolved

Post by ilari »

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).
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.
Aleks Peshkov
Posts: 892
Joined: Sun Nov 19, 2006 9:16 pm
Location: Russia

Re: Scorpio 202 Under Linux Resolved

Post by Aleks Peshkov »

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.
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.

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.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Scorpio 202 Under Linux Resolved

Post by Sven »

Aleks Peshkov wrote:
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.
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.

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.
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:

Code: Select all

#if defined&#40;_MSC_VER&#41; && _MSC_VER <= 1200 
#define CONST64&#40;x&#41;   &#40;x ## i64&#41; 
#define CONST64U&#40;x&#41;  &#40;x ## ui64&#41; 
#define FMT64d       "I64d" 
#define FMT64x       "I64x" 
#else 
#define CONST64&#40;x&#41;   &#40;x ## LL&#41; 
#define CONST64U&#40;x&#41;  &#40;x ## ULL&#41; 
#define FMT64d       "lld" 
#define FMT64x       "llx" 
#endif /* _MSC_VER */
This allows for both signed and unsigned 64 bit integer literals, just as they are needed.

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
Aleks Peshkov
Posts: 892
Joined: Sun Nov 19, 2006 9:16 pm
Location: Russia

Re: Scorpio 202 Under Linux Resolved

Post by Aleks Peshkov »

Sven Schüle wrote:Ad 1), unfortunately there are also "bad compilers" in this sense ...
I suspect that you did not explicitly turn on all warning levels. Microsoft C++ is rather verbose about signed/unsigned mismatch.
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&#40;_MSC_VER&#41; && _MSC_VER <= 1200 
#define CONST64&#40;x&#41;   &#40;x ## i64&#41; 
#define CONST64U&#40;x&#41;  &#40;x ## ui64&#41; 
#define FMT64d       "I64d" 
#define FMT64x       "I64x" 
#else 
#define CONST64&#40;x&#41;   &#40;x ## LL&#41; 
#define CONST64U&#40;x&#41;  &#40;x ## ULL&#41; 
#define FMT64d       "lld" 
#define FMT64x       "llx" 
#endif /* _MSC_VER */
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.
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 ...
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.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Scorpio 202 Under Linux Resolved

Post by Sven »

Aleks Peshkov wrote:
Sven Schüle wrote:Ad 1), unfortunately there are also "bad compilers" in this sense ...
I suspect that you did not explicitly turn on all warning levels. Microsoft C++ is rather verbose about signed/unsigned mismatch.
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.

Code: Select all

#include <stdio.h>

int main&#40;)
&#123;
    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&#40;"us=%u ss=%d\n",   us, ss&#41;;
    printf&#40;"ui=%u si=%d\n",   ui, si&#41;;
    printf&#40;"ull=%llu sll=%lld\n", ull, sll&#41;;

    return 0;
&#125;
should compile pretty everywhere (***) without warnings (except older MSVC which needs "i64" suffix, "__int64" type and "I64d" format spec instead, as already stated - I just wanted to omit all these macros in the example above) and always print:

Code: Select all

us=65535 ss=-1
ui=4294967295 si=-1
ull=18446744073709551615 sll=-1
(***) Edit: Of course I know that the size of short/int/long long is not guaranteed to be 16/32/64 bit, so of course this is not a valid portable program. The point is a different one, however.
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.
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.

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