nibble swapping

Discussion of chess software programming and technical issues.

Moderator: Ras

lucasart
Posts: 3243
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

nibble swapping

Post by lucasart »

I'm trying to write a function that swaps the nibbles of a bitboard two by two.

Just to clarify what that means:
- a nibble is 4 bits (half a byte)
- a bitboard is therefore 16 nibbles: b = N0,N1, ..., N14,N15
- function should return: f(b) = N1,N0, N3,N2, ..., N15,N14

Is there a smart way to perform that operation really fast ?

Thank you
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
mar
Posts: 2672
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: nibble swapping

Post by mar »

lucasart wrote:I'm trying to write a function that swaps the nibbles of a bitboard two by two.

Just to clarify what that means:
- a nibble is 4 bits (half a byte)
- a bitboard is therefore 16 nibbles: b = N0,N1, ..., N14,N15
- function should return: f(b) = N1,N0, N3,N2, ..., N15,N14

Is there a smart way to perform that operation really fast ?

Thank you
Maybe shift left and mask or shift right and mask?
Like ((b << 4) & maskhi) | ((b>>4) & masklo)?
User avatar
Evert
Posts: 2929
Joined: Sat Jan 22, 2011 12:42 am
Location: NL

Re: nibble swapping

Post by Evert »

mar wrote:Maybe shift left and mask or shift right and mask?
Like ((b << 4) & maskhi) | ((b>>4) & masklo)?
That's almost certainly the only portable solution. Note that it can be done on an entire bitboard in one go, assuming the encoding is A1=0, B1=1,...,H8=63, using exactly that code (and using suitable bitmasks).

Should be fast enough.
lucasart
Posts: 3243
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: nibble swapping

Post by lucasart »

mar wrote:
lucasart wrote:I'm trying to write a function that swaps the nibbles of a bitboard two by two.

Just to clarify what that means:
- a nibble is 4 bits (half a byte)
- a bitboard is therefore 16 nibbles: b = N0,N1, ..., N14,N15
- function should return: f(b) = N1,N0, N3,N2, ..., N15,N14

Is there a smart way to perform that operation really fast ?

Thank you
Maybe shift left and mask or shift right and mask?
Like ((b << 4) & maskhi) | ((b>>4) & masklo)?
Thanks. Simple and portable :D
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
User avatar
Evert
Posts: 2929
Joined: Sat Jan 22, 2011 12:42 am
Location: NL

Re: nibble swapping

Post by Evert »

There may also be something relevant at http://chessprogramming.wikispaces.com/ ... Techniques
User avatar
hgm
Posts: 28452
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: nibble swapping

Post by hgm »

mar wrote:Maybe shift left and mask or shift right and mask?
Like ((b << 4) & maskhi) | ((b>>4) & masklo)?
Indeed, that is also the method I use for diagonal mirroring of position indexes in the fairygen EGT generator. (Except that the groups of bits I want to swap are only 3-wide rank and file number there. So I use b<<3 & 07070707070 | b>>3 & 0707070707).

For non-8x8 square boards I had a hard time finding something similarly simple. In the end I chose for keeping two separate keys, one collecting all rank coordinates, the other all file coordinates, so that I can do mirroring in one dimension or the other by subtracting the index from a constant. The total index is then rankIndex*WIDTH + fileIndex or fileIndex*WIDTH + rankIndex, depending on the diagonal mirror class I need.
User avatar
Don
Posts: 5106
Joined: Tue Apr 29, 2008 4:27 pm

Re: nibble swapping

Post by Don »

lucasart wrote:I'm trying to write a function that swaps the nibbles of a bitboard two by two.

Just to clarify what that means:
- a nibble is 4 bits (half a byte)
- a bitboard is therefore 16 nibbles: b = N0,N1, ..., N14,N15
- function should return: f(b) = N1,N0, N3,N2, ..., N15,N14

Is there a smart way to perform that operation really fast ?

Thank you
You could try using a 64k table that does the swapping 16 bits at a time. I don't know how fast or slow it would be but it would be worth a quick test.

My best guess is that the shift intensive expression will be faster because even with lookup tables you will have to do a fair amount of shifting as well as 4 memory accesses and additional cache pressure.
Capital punishment would be more effective as a preventive measure if it were administered prior to the crime.