6171

GMP Bit shift doesn't work on negative numbers

I found this function at php.net. It seems to work on positive numbers, but fails on negative ones:

```function gmp_shiftr(\$x,\$n) { // shift right return(gmp_div(\$x,gmp_pow(2,\$n))); } echo -1 >> 8; //returns -1, presumably correctly echo "<br />"; echo gmp_strval(gmp_shiftr(-1,8)); //returns 0, presumably incorrectly ```

How could I fix up the function to work with negatives?

Two ideas I have:

Maybe I could do something along the lines of

```if (whatever) { \$a >> \$b} else{ gmp_shiftr(\$a, \$b) }? ```

Or, maybe I could subtract something from the negative results depending on their value..?

I just want to get the value that >> would give, but also get it for >32bit numbers when I use GMP.

Looking at the GMP documentation for the division routines, there's a function

```void mpz_tdiv_q_2exp (mpz_t q, mpz_t n, unsigned long int b) ```

that seems like it might be what you want: an arithmetic right shift that treats `n` as if it were represented in twos-complement, and (I think) shifts it `b` places to the right. Unfortunately, that level of the API doesn't seem to be exposed by PHP GMP.

I found a bit twiddling hack for doing sign extension when the number of bits in the representation is unknown:

```unsigned b; // number of bits representing the number in x int x; // sign extend this b-bit number to r int r; // resulting sign-extended number int const m = 1U << (b - 1); // mask can be pre-computed if b is fixed x = x & ((1U << b) - 1); // (Skip this if bits in x above position b are already zero.) r = (x ^ m) - m; ```

Since bitwise AND and XOR are supported by PHP GMP, you might be able to make this work...