A Neat Trick

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Michael Sherwin
Posts: 3196
Joined: Fri May 26, 2006 3:00 am
Location: WY, USA
Full name: Michael Sherwin

A Neat Trick

Post by Michael Sherwin »

If it works. One might guess by my signature that I'm not a fan of "if" statements. While coding a white pawn on the 5th rank I was determined to code a cep capture without using an if statement. I probably spent over two hours on it. It was only after giving up and going to the kitchen to get some food that the solution came to me. A cep square is stored as a bb and not a square value.

Code: Select all

          sq = ts - (epbit[t][ply[t] - 1] & (one << (ts - 8)) << 3);
          target = board[t][sq];
Since I have an e.p. bit the idea is to create a bit from the ts - 8 and and them together giving a zero or a one. Then shifting left the zero or one by 3 to get a zero or 8 and then subtracting it from the ts to get the target square. It is probably slower than just using an "if" but it is the principle of the idea! :P
If you are on a sidewalk and the covid goes beep beep
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through
User avatar
hgm
Posts: 27817
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: A Neat Trick

Post by hgm »

I don't understand your code, because I have no idea what t, ply[] and epbit[][] are. And it looks fishy, because you seem to subtract a bitboard from a square number. But what would be wrong with

sq = ts ^ 8*(epbitboard == one<<ts);

?
Michael Sherwin
Posts: 3196
Joined: Fri May 26, 2006 3:00 am
Location: WY, USA
Full name: Michael Sherwin

Re: A Neat Trick

Post by Michael Sherwin »

hgm wrote: Sat Apr 11, 2020 7:51 am I don't understand your code, because I have no idea what t, ply[] and epbit[][] are. And it looks fishy, because you seem to subtract a bitboard from a square number. But what would be wrong with

sq = ts ^ 8*(epbitboard == one<<ts);

?
I should have said how the code is structured. The var t is the thread index that gets passed everywhere. And I'm using arrays instead of a structure because I spent a couple of hours searching the internet on the subject and the consensus by the more intelligent sounding posters is that arrays are faster. So when a pawn double move is made the bit bb is stored in an array indexed by half move count after ply[t]++ so it is available at the next half move. In epbit[t][ply[t] - 1], the -1 is because ply[t]++ was made earlier basically a six of one half a dozen of another situation. So what it does is and, let's say 010 with 010 to get a 1 or say 010 with 100 to get a zero therefore 1 << 3 is eight or 0 << 3 is zero and therefore sq = ts - 8 or sq = ts - 0;

Let's see if I understand your code. Does every possible ep square have bit 8 set? Okay, yes they do! What about blacks ep squares 24 - 31? Okay so yes they also do! But there is a problem, "(epbitboard == one<<ts)" is just a hidden if statement, dos it not, still requiring a conditional branch? Or does the compiler have ways around that
If you are on a sidewalk and the covid goes beep beep
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through
User avatar
hgm
Posts: 27817
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: A Neat Trick

Post by hgm »

No, statements like that do not require a branch on i386 architecture. There are instructions SETcc which copy a condition code (like the EQ flag) to the AL register. So you just do the compare, which sets the condition codes, and then SETEQ to get a 0 or 1 depending on the result.

Thanks for the explanation. The problem I have with your code is that 010 & 010 doesn't give you 1. It gives you 010 = 2. And 2<<3 = 16.

Why do you pass the bitboard with e.p. square anyway? Wouldn't it be much simpler to pass the square number?
Ras
Posts: 2488
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: A Neat Trick

Post by Ras »

hgm wrote: Sat Apr 11, 2020 4:29 pmNo, statements like that do not require a branch on i386 architecture.
Donald Knuth: "Premature optimization is the root of all evil (or at least most of it) in programming."
Rasmus Althoff
https://www.ct800.net
User avatar
hgm
Posts: 27817
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: A Neat Trick

Post by hgm »

Undoubtedly very wise. But I am not sure how it applies here. An efficient ptogramming style is not the same as optimization. I would say that intentionally writing poor code is an even deeper root of evil.
Ras
Posts: 2488
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: A Neat Trick

Post by Ras »

hgm wrote: Sat Apr 11, 2020 5:24 pmBut I am not sure how it applies here.
Generating code so clever that not even the programmer will understand it two weeks from now, without having checked the disassembly whether ifs would even compile to branch instructions, and all of that in a part of the program that doesn't take relevant runtime - in a new project before having reached the "it works correctly" stage.
Rasmus Althoff
https://www.ct800.net
User avatar
hgm
Posts: 27817
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: A Neat Trick

Post by hgm »

I guess it depends on what you are used to. For me this is the natural way to do things, while if-statements are cumbersome, difficult to understand and error-prone.
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: A Neat Trick

Post by mvanthoor »

Ras wrote: Sat Apr 11, 2020 5:11 pm
hgm wrote: Sat Apr 11, 2020 4:29 pmNo, statements like that do not require a branch on i386 architecture.
Donald Knuth: "Premature optimization is the root of all evil (or at least most of it) in programming."
"... except when cutting out code that shouldn't have been there in the first place."
- Me :lol:

"One of my most productive days was throwing away 1,000 lines of code."
- Ken Thompson
Last edited by mvanthoor on Sat Apr 11, 2020 10:05 pm, edited 1 time in total.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
Michael Sherwin
Posts: 3196
Joined: Fri May 26, 2006 3:00 am
Location: WY, USA
Full name: Michael Sherwin

Re: A Neat Trick

Post by Michael Sherwin »

hgm wrote: Sat Apr 11, 2020 4:29 pm No, statements like that do not require a branch on i386 architecture. There are instructions SETcc which copy a condition code (like the EQ flag) to the AL register. So you just do the compare, which sets the condition codes, and then SETEQ to get a 0 or 1 depending on the result.

Thanks for the explanation. The problem I have with your code is that 010 & 010 doesn't give you 1. It gives you 010 = 2. And 2<<3 = 16.

Why do you pass the bitboard with e.p. square anyway? Wouldn't it be much simpler to pass the square number?
I guess that I was hallucinating. So instead of a shift to the left by 3 a shift right (epsq - 3) is needed or something like that. But that is all moot because your way satisfies the no conditional branch goal and is obviously faster. THANKS

Also it is stored as a bb because in the move generator i have this:

Code: Select all

          case RANK5:
            bb = (wPawnMoves[fs] & empty) | (wPawnCapts[fs] & (bPieces | epbit[t][ply[t]]));
            typ = WCEP;
            break;
If you are on a sidewalk and the covid goes beep beep
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through