Difference between revisions of "Right Shift"

From Second Life Wiki
Jump to navigation Jump to search
(New page: {{LSL Header}} Here's a function to pass a signed 32 bit integer along with a value indicating how far to shift the bits. This method is primarily needed to shift bits for negative integer...)
 
Line 1: Line 1:
{{LSL Header}}
{{LSL Header}}{{RightToc}}
 
== Bitwise vs. Arithmetic ==
 
There are two types of Right Shifts, that can be performed on an integer. They are: Bitwise and Arithmetic. LSL currently only supports Arithmetic. The difference between the two modes is how it fills the bits revealed. In bitwise mode, the revealed bits are always zero; in Arithmetic mode, it duplicates the old top bit to all the new bits. If you take the expression <code>int >> count</code> where ''int'' is arithmetically shifted right ''count'' bits, then this is the same mathematically as doing <code>int / (2 <sup>count</sup>)</code> or in LSL <code>int / llPow(2.0, count)</code>.
 
== How to do Bitwise Right Shifts in LSL ==
 
Since LSL does not have a bitwise right shift operator you have to do it yourself. There are two methods for doing this, each with it's advantages and disadvantages.
 
=== Method 1 ===
<lsl>(value >> count) & ~((~value) >> count);</lsl>
This method is good when count is dynamic.
It works because all the bits that need to be turned on will be turned on both sides of the AND but on only one side will the arithmetic right shift cause the sign bit to be extended. The result of the and is a value that is always a bitwise right shift.
 
=== Method 2 ===
<lsl>(value >> count) & mask;</lsl>
This method can only be used when count is a constant value. You use a constant mask to remove the extended sign bits. Example: <code>(value >> 5) & 0x07FFFFFF</code> As you can see the top five bits have been turned off in the mask value, if you have trouble seeing that, you can just use the lookup table below.
 
{|
|+'''Mask Lookup Table'''
|
{|{{Prettytable}}
|-{{Hl2}}
! Shift
! Mask
|-
| 0
| {{LSL Hex|0xFFFFFFFF|}}
|-
| 1
| {{LSL Hex|0x7FFFFFFF|}}
|-
| 2
| {{LSL Hex|0x3FFFFFFF|}}
|-
| 3
| {{LSL Hex|0x1FFFFFFF|}}
|-
| 4
| {{LSL Hex|0x0FFFFFFF|}}
|-
| 5
| {{LSL Hex|0x07FFFFFF|}}
|-
| 6
| {{LSL Hex|0x03FFFFFF|}}
|-
| 7
| {{LSL Hex|0x01FFFFFF|}}
|-
| 8
| {{LSL Hex|0x00FFFFFF|}}
|-
| 9
| {{LSL Hex|0x007FFFFF|}}
|-
| 10
| {{LSL Hex|0x003FFFFF|}}
|}
|
{|{{Prettytable}}
|-{{Hl2}}
! Shift
! Mask
|-
| 11
| {{LSL Hex|0x001FFFFF|}}
|-
| 12
| {{LSL Hex|0x000FFFFF|}}
|-
| 13
| {{LSL Hex|0x0007FFFF|}}
|-
| 14
| {{LSL Hex|0x0003FFFF|}}
|-
| 15
| {{LSL Hex|0x0001FFFF|}}
|-
| 16
| {{LSL Hex|0x0000FFFF|}}
|-
| 17
| {{LSL Hex|0x00007FFF|}}
|-
| 18
| {{LSL Hex|0x00003FFF|}}
|-
| 19
| {{LSL Hex|0x00001FFF|}}
|-
| 20
| {{LSL Hex|0x00000FFF|}}
|-
| 21
| {{LSL Hex|0x000007FF|}}
|}
|
{|{{Prettytable}}
|-{{Hl2}}
! Shift
! Mask
|-
| 22
| {{LSL Hex|0x000003FF|}}
|-
| 23
| {{LSL Hex|0x000001FF|}}
|-
| 24
| {{LSL Hex|0x000000FF|}}
|-
| 25
| {{LSL Hex|0x0000007F|}}
|-
| 26
| {{LSL Hex|0x0000003F|}}
|-
| 27
| {{LSL Hex|0x0000001F|}}
|-
| 28
| {{LSL Hex|0x0000000F|}}
|-
| 29
| {{LSL Hex|0x00000007|}}
|-
| 30
| {{LSL Hex|0x00000003|}}
|-
| 31
| {{LSL Hex|0x00000001|}}
|-
| 32
| {{LSL Hex|0x00000000|}}
|}
|}
 
== Example Bitwise Right Shift Function ==
 
Here's a function to pass a signed 32 bit integer along with a value indicating how far to shift the bits. This method is primarily needed to shift bits for negative integers, as the regular bit shift operators work just fine for positive values.
Here's a function to pass a signed 32 bit integer along with a value indicating how far to shift the bits. This method is primarily needed to shift bits for negative integers, as the regular bit shift operators work just fine for positive values.


== RightShift.lsl ==
<lsl>// the lsl right shift is an arithmetic right shift,
 
// this means it more closely resembles dividing by a
<lsl>
// positive power of two then a bitwise right shift.
// right shift doesn't work well for signed integers.
// To perform a bitwise right shift you need to be smart
// we essentially perform the operation as if it was
integer rightShift(integer value, integer count)
// an unsigned integer.
integer rightShift(integer value, integer bits)
{
{
     // positive numbers are fine
     return (value >> count) & ~((~value) >> count);
    if(value >= 0)
}</lsl>
        return value >> bits;
'''Example Usage:'''
 
<lsl>default
    // remove bit sign
    value = value ^ 0x80000000;
   
    // move bits
    value = value >> bits;
   
    // inject signed bit to new location
    value = value | (integer)(llPow(2, 31 - bits));
   
    return value;
}
default
{
{
     state_entry()
     state_entry()

Revision as of 03:23, 3 February 2008

Bitwise vs. Arithmetic

There are two types of Right Shifts, that can be performed on an integer. They are: Bitwise and Arithmetic. LSL currently only supports Arithmetic. The difference between the two modes is how it fills the bits revealed. In bitwise mode, the revealed bits are always zero; in Arithmetic mode, it duplicates the old top bit to all the new bits. If you take the expression int >> count where int is arithmetically shifted right count bits, then this is the same mathematically as doing int / (2 count) or in LSL int / llPow(2.0, count).

How to do Bitwise Right Shifts in LSL

Since LSL does not have a bitwise right shift operator you have to do it yourself. There are two methods for doing this, each with it's advantages and disadvantages.

Method 1

<lsl>(value >> count) & ~((~value) >> count);</lsl> This method is good when count is dynamic. It works because all the bits that need to be turned on will be turned on both sides of the AND but on only one side will the arithmetic right shift cause the sign bit to be extended. The result of the and is a value that is always a bitwise right shift.

Method 2

<lsl>(value >> count) & mask;</lsl> This method can only be used when count is a constant value. You use a constant mask to remove the extended sign bits. Example: (value >> 5) & 0x07FFFFFF As you can see the top five bits have been turned off in the mask value, if you have trouble seeing that, you can just use the lookup table below.

Mask Lookup Table
Shift Mask
0 0xFFFFFFFF
1 0x7FFFFFFF
2 0x3FFFFFFF
3 0x1FFFFFFF
4 0x0FFFFFFF
5 0x07FFFFFF
6 0x03FFFFFF
7 0x01FFFFFF
8 0x00FFFFFF
9 0x007FFFFF
10 0x003FFFFF
Shift Mask
11 0x001FFFFF
12 0x000FFFFF
13 0x0007FFFF
14 0x0003FFFF
15 0x0001FFFF
16 0x0000FFFF
17 0x00007FFF
18 0x00003FFF
19 0x00001FFF
20 0x00000FFF
21 0x000007FF
Shift Mask
22 0x000003FF
23 0x000001FF
24 0x000000FF
25 0x0000007F
26 0x0000003F
27 0x0000001F
28 0x0000000F
29 0x00000007
30 0x00000003
31 0x00000001
32 0x00000000

Example Bitwise Right Shift Function

Here's a function to pass a signed 32 bit integer along with a value indicating how far to shift the bits. This method is primarily needed to shift bits for negative integers, as the regular bit shift operators work just fine for positive values.

<lsl>// the lsl right shift is an arithmetic right shift, // this means it more closely resembles dividing by a // positive power of two then a bitwise right shift. // To perform a bitwise right shift you need to be smart integer rightShift(integer value, integer count) {

   return (value >> count) & ~((~value) >> count);

}</lsl> Example Usage: <lsl>default {

   state_entry()
   {
       // output should be 268435449
       llSay(DEBUG_CHANNEL, (string)rightShift(-99, 4));
       // before: 1111 1111 1111 1111 1111 1111 1001 1101
       // after:  0000 1111 1111 1111 1111 1111 1111 1001
   }

}</lsl>