in reply to Re: Implementing a signed/sign-propagating right bitwise shift
in thread Implementing a signed/sign-propagating right bitwise shift

Slowly, please. :-) Bitwise anything is new to me, and I struggle with even understanding what it means.

Yes, I can see how (1 << $firstbit) is a constant. But its purpose is to get at that first bit, 0b10000000000000000000000000000000, i.e. 2**31. What is a better way to do that? I originally had "2**$firstbit" in place of "(1 << $firstbit)". Would that be better here? Is that what you mean by 'extracting' it?

As for your second paragraph, you'll have to slow down and explain how to do what you're saying, as you lost me completely with everything beginning with "checking the high-bit."

In any case, thanks!

  • Comment on Re^2: Implementing a signed/sign-propagating right bitwise shift

Replies are listed 'Best First'.
Re^3: Implementing a signed/sign-propagating right bitwise shift
by ikegami (Patriarch) on Feb 16, 2012 at 17:57 UTC

    He was suggesting that you do something like:

    my $firstbit = ($longsize * 8) - 1; my $firstbit_mask = 1 << $firstbit;

    then use $firstbit_mask instead of 1 << $firstbit_mask. This cuts down on the number of shifts to do.


    As for the second paragraph:

    use constant NUM_BITS = $Config{ivsize} * 8; use constant SIGN_BIT = 1 << ( NUM_BITS - 1 ); use constant ALL_BITS = -1; sub sr_signed { my ($p, $q) = @_; if ($p & SIGN_BIT) { return ($p >> $q) | ($ALL_BITS << (NUM_BITS - $q)); } else { return $p >> $q; } }

    Example:

    Shift 10101111...10101100 by 3 10101111...10101100 >> 3 |||||||| ||||| \\\\\\\\ \\\\\ \\\\\\\\ \\\\\ |||||||| ||||| 00010101111...10101 11111111...11111111 << (NUM_BITS-3) ||| _____________/// /// ||| 11100000...00000000 00010101111...10101 | 11100000...00000000 ------------------- 11110101111...10101

    (Note that ivsize should be used, not longsize.)

Re^3: Implementing a signed/sign-propagating right bitwise shift
by jethro (Monsignor) on Feb 16, 2012 at 18:01 UTC

    a) if you do something in a loop that is executed 32 times, that something is done 32 times. If you do it before the loop it is only done once. That should make anything faster. So you could do this:

    my $highbitset= (1<< $firstbit); foreach ... ... $x & $highbitset) != 0);

    As you can see the bitshift is only done once and inside the loop the constant contents of the variable is used instead.

    b) What you do is (for negative 32bit numbers): loop $y times: shift by one, set the high bit, shift by one, set the high bit ...

    What you could do: No loop, just shift by $y. set all high bits at once (With high bits I mean all the bits shifted in as 0 instead of 1).

    And the value you need to set all high-bits at once would be what? 0b10000... if $y==1, 0b11000.... if $y==2, and so on to 0b1111... if $y=32. This value is just 0b111111.... shifted left 32-$y times, i.e. 0b1111.... << 32-$y.

    More generally I would specify that as -1 << ($longsize*8 - $y)

      Thanks; I get it now. The reason I had the loop in the first place is because that was how I had to work the math in my head: one step at a time, like a monkey with a scratch pad. (I also originally had a print statement at every step of the loop to be sure that it was doing what I thought it was doing!)