Bitwise operators in Python

share on google plus share on facebook share on twitter share on linkedin share via email

Python has logical operators (like ‘and’) and bitwise operators (like ‘&’). Bitwise operators are not that common in Python code, but they can be extremely useful in some cases. For example, in RhinoPython they are used to work with geometry type filters.

The geometry types in the rhinoscripsyntax package are defined in the selection module and can be accessed like this:

 
import rhinoscriptsyntax as rs

print rs.filter.point    # prints 1
print rs.filter.curve    # prints 4
print rs.filter.surface  # prints 8

The entire list of values can be found on GitHub, but i will copy the code here for simplicity:

class filter:
    allobjects = 0
    point = 1
    pointcloud = 2
    curve = 4
    surface = 8
    polysurface = 16
    mesh = 32
    light = 256
    annotation = 512
    instance = 4096
    textdot = 8192
    grip = 16384
    detail = 32768
    hatch = 65536
    morph = 13072
    cage = 134217728
    phantom = 268435456
    clippingplane = 536870912
    extrusion = 1073741824

Notice that the values correspond to powers of 2. Therefore they each correspond to a different digit in the binary system:

print bin(rs.filter.point)    # prints '0b1'
print bin(rs.filter.curve)    # prints '0b100'
print bin(rs.filter.surface)  # prints '0b1000' 

This is where bitwise operators come in. Bitwise operators compare corresponding digits in two binary numbers and return a result in binary form accordingly.

Bitwise ‘and’ (&) returns a binary number with 1 at digits where both of the corresponding digits of the operands are 1:

print 0 & 1    # prints 0 (0000), since 0000 'and' 0001 => 0000
print 2 & 3    # prints 2 (0010), since 0010 'and' 0011 => 0010
print 2 & 7    # prints 2 (0010), since 0010 'and' 0111 => 0010 
print 15 & 10  # prints 10 (1010), since 1111 'and' 1010 => 1010  

Bitwise ‘or’ (|) returns a binary number with 1 at digits where at least one of the digits of the operands was 1:

print 0 & 1    # prints 1 (0001), since 0000 'and' 0001 => 0001
print 2 & 3    # prints 3 (0011), since 0010 'and' 0011 => 0011
print 2 & 7    # prints 7 (0111), since 0010 'and' 0111 => 0111 
print 15 & 10  # prints 15 (1111), since 1111 'and' 1010 => 1111  

Getting back to the example of geometry filters in rhinoscriptsyntax, this snippet returns the guids of both points and curves:

guids = rs.ObjectsByType(rs.filter.point | rs.filter.curve)

What happens in the background is the following. The result of the combined filter is:

filter = rs.filter.point | rs.filter.curve
print filter  # prints 5 (0101), since 0001 'or' 0100 => 0101

Comparing this combined filter with the filter values of the different geometry types using bitwise ‘and’ the function can figure out which types to include in the result:

include_points   = False
include_curves   = False
include_surfaces = False

if filter & rs.filter.point: 
    include_points = True

if filter & rs.filter.curve: 
    include_curves = True

if filter & rs.filter.surface: 
    include_surfaces = True

print include_points    # prints True
print include_curves    # prints True
print include_surfaces  # prints False

Leave a response

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>