Unsigned right shift operator in Swift?

Discussion of chess software programming and technical issues.

Moderators: hgm, Dann Corbit, Harvey Williamson

User avatar
phhnguyen
Posts: 1431
Joined: Wed Apr 21, 2010 4:58 am
Location: Australia
Full name: Nguyen Hong Pham

Unsigned right shift operator in Swift?

Post by phhnguyen »

I have been coding my chess app in Swift and want to implement a random function with a code modified from Java one. That function uses some unsigned right shift operators (>>>) and I don't know how to implement it correctly in Swift.

My function works mainly with long (Int64) and speed is not a big problem.

Sorry for being lazy to do it myself and thanks in advance for any helps!

The unsigned right shift operator is defined from Java doc as the following:

Code: Select all

The value of n >>> s is n right-shifted s bit positions with zero-extension, where:
- If n is positive, then the result is the same as that of n >> s.
- If n is negative and the type of the left-hand operand is int, then the result is equal to that of the expression &#40;n >> s&#41; + &#40;2 << ~s&#41;.
- If n is negative and the type of the left-hand operand is long, then the result is equal to that of the expression &#40;n >> s&#41; + &#40;2L << ~s&#41;.

The added term &#40;2 << ~s&#41; or &#40;2L << ~s&#41; cancels out the propagated sign bit.
Dann Corbit
Posts: 12482
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: Unsigned right shift operator in Swift?

Post by Dann Corbit »

This is going to sound stupid, but why not just divide by powers of 2 in a table?

If the optimizer is any good, it will turn the operations into shifts anyway.
jwes
Posts: 778
Joined: Sat Jul 01, 2006 7:11 am

Re: Unsigned right shift operator in Swift?

Post by jwes »

Dividing by powers of 2 is equivalent to signed right shift.
User avatar
hgm
Posts: 27701
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Unsigned right shift operator in Swift?

Post by hgm »

Just define an array mask[63], which you initialize as

Code: Select all

mask&#91;63&#93; = 1;
for&#40;i=62; i>= 0; i--) mask&#91;i&#93; = 2*mask&#91;i+1&#93; + 1;
Then everywhere you need k >>> n, do

Code: Select all

&#40;k >> n&#41; & mask&#91;n&#93;
(This assumes Swift has a bitwise AND operation.)

If that is not the case, you can replace x = k>>>n by

Code: Select all

if&#40;n > 0&#41; &#123;
  x = k>>1;
  if&#40;x < 0&#41; x -= 1<<63;
  x >>= n-1;
&#125; else x = k;
User avatar
phhnguyen
Posts: 1431
Joined: Wed Apr 21, 2010 4:58 am
Location: Australia
Full name: Nguyen Hong Pham

Re: Unsigned right shift operator in Swift?

Post by phhnguyen »

Thanks a lot Muller and all other people!

Both ways can be coded in Swift. I prefer to the first one (using mask).
mar
Posts: 2552
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Unsigned right shift operator in Swift?

Post by mar »

jwes wrote:Dividing by powers of 2 is equivalent to signed right shift.
Sorry but this is not true (assuming 2's complement representation):
-1 >> 1 = -1
-1 / 2 = 0
signed shift right can be thought of as rounding towards -infinity, say you have a fixed point number x with n bits fractional part. this is nice as it allows trivial rounding towards nearest integer:
ix = (x + (1 << (n-1)) >> n

I have another obvious table-free version for doing unsigned logical shift right (untested) but I doubt it'd be competitive with hgm's solution in terms of performance:

Code: Select all

&#40;k >> n&#41; ^ ( &#40;k & 0x8000000000000000ll&#41; >> n ) * 2
(assuming * has higher precedence than xor and that *2 will be optimized to either shift or addition)

Alternatively one could omit *2 and instead do second >> by n-1, but this won't work for cases where n is zero

EDIT: since I assume this is for bitboards, it's very likely that MSBit will be zero in most cases, so perhaps doing a special case for k >= 0 might help (if you can tell the compiler that's the likely case to happen).