About definitions in fruit

Programming Topics (Computer Chess) and technical aspects as test techniques, book building, program tuning etc

Moderator: Andres Valverde

About definitions in fruit

Postby Uri Blass » 02 Aug 2005, 09:55

I think that I understand the file colour.h of Fruit but I do not understand the reasons for the complex definitions in it.

#define COLOUR_IS_OK(colour) (((colour)&~1)==0)

I wonder what is the reason for that definition.

It seems to me simpler to write

#define COLOUR_IS_OK(colour)
(((colour)==0)||((colour)==1))

Later:

#define COLOUR_IS_WHITE(colour) ((colour)==White)
#define COLOUR_IS_BLACK(colour) ((colour)!=White)

I do not understand why colour!=White and not colour==Black in the second definition.

Later:

#define COLOUR_IS(piece,colour) (FLAG_IS((piece),COLOUR_FLAG(colour)))
#define FLAG_IS(piece,flag) (((piece)&(flag))!=0)

#define COLOUR_OPP(colour) ((colour)^(White^Black))
#define COLOUR_FLAG(colour) ((colour)+1)

Note that I never use definitions inside definitions in Movei and I did not know that it is correct code but
I do not understand the order of definitions and it seems that COLOUR_IS use definitions that are only defined later.

I also do not understand the reason for
#define COLOUR_OPP(colour) ((colour)^(White^Black))

Fruit has
const int White = 0;
const int Black = 1;
so I think that it is more simple to write
#define COLOUR_OPP(colour) ((colour)^1)

Also it is more clear to write
#define COLOUR_FLAG(colour) (1<<(colour))
and not
#define COLOUR_FLAG(colour) ((colour)+1)

These definitions are equal for colour=0 and colour=1 and I wonder what is the reason for prefering (colour)+1(speed optimization?)

I also understand that
COLOUR_IS(piece,colour) gives me 1 only if some piece has specific colour and piece is probably some information about some square that include the colour in 2 bits(piece&1 only if it is white when piece&2 only if it is black when neither of them if it is empty)

Uri
User avatar
Uri Blass
 
Posts: 727
Joined: 09 Oct 2004, 05:59
Location: Tel-Aviv

Re: About definitions in fruit

Postby Alessandro Scotti » 02 Aug 2005, 10:19

Hi Uri,
I think Fruit definitions are faster than what you suggest.
It's usually better to compare a value against zero rather than other values because processors keep an internal flag that is set if the last arithmetic operation returned zero, and always updated. So when you do "color & ~1", after the "and" operation the CPU already knows if the result was zero or not: the "== 0" part is free.
Similar reason for comparing against White (zero). Here the result is free if color was somehow resulting from an arithmetic expression, but even if it's not, comparing against zero is preferrable. For example on Intel CPUs testing if register EAX is zero could be implemented with "TEST EAX, EAX", which is faster than "CMP EAX, something". (At least, this used to be true some years ago, I don't know how that applies to newer processors).
I'm sure compilers know some other tricks as well, and they're pretty happy to find zero constants! :-)
User avatar
Alessandro Scotti
 
Posts: 306
Joined: 20 Nov 2004, 00:10
Location: Rome, Italy

Re: About definitions in fruit

Postby Uri Blass » 02 Aug 2005, 10:44

I wonder if compilers are so stupid not to translate both 1 and 2 to the same code when x is an integer or if there is a case when both expressions do not give the same value.

1)((x==0)||(x==1))
2)((x&~1)==0)

Uri
User avatar
Uri Blass
 
Posts: 727
Joined: 09 Oct 2004, 05:59
Location: Tel-Aviv

Re: About definitions in fruit

Postby Alessandro Scotti » 02 Aug 2005, 10:54

Uri Blass wrote:I wonder if compilers are so stupid not to translate both 1 and 2 to the same code when x is an integer

1)((x==0)||(x==1))
2)((x&~1)==0)
i


I just did the test using MSVC++ .NET 2003:

1)
test esi, esi
je ...
cmp esi, 1
jne ...

2)
test esi, -2 ; ~1
je ...

So case 2 saves a full compare, and the compiler even replaced "and" with "test", which is faster (it works like "and" but throws away the result, saving the write cycle).
User avatar
Alessandro Scotti
 
Posts: 306
Joined: 20 Nov 2004, 00:10
Location: Rome, Italy

Re: About definitions in fruit

Postby Dann Corbit » 02 Aug 2005, 18:08

Uri Blass wrote:I wonder if compilers are so stupid not to translate both 1 and 2 to the same code when x is an integer or if there is a case when both expressions do not give the same value.

1)((x==0)||(x==1))
2)((x&~1)==0)

Uri


This is the one that is not nearly as good:
1)((x==0)||(x==1))

An OR requires by the C and C++ standard a short circuit if the first test is true (the second condition is not even tested). That sounds good, but it implies a branch and therefore a possible missed branch prediction. The code of Fabien is clearly better in that case. A missed branch prediction is absurdly expensive.

A really good compiler might turn expression 1) into something better somehow, but the alternative is the better way to do it.

In any case, this test is not important and if you change it to the way you wrote it, it will not change the performance of Fruit even by 1%. If it is something that is executed millions of times, then it will become important. So that particular bit of code is the wrong place to focus.

On the other hand, if you get into the habit of writing branchless code when possible (and if the branchless code is obvious in what it does) then that is a good habit.
Dann Corbit
 


Return to Programming and Technical Discussions

Who is online

Users browsing this forum: No registered users and 27 guests