Search code examples
pythonbinarybit-shift

Circular shift of a bit in python (equivalent of Fortran's ISHFTC)


I want to achieve the equivalent of the ISHFTC function in Fortran using python. What is the best way to do this?

For example,

x = '0100110'
s = int(x, 2)
s_shifted = ISHFTC(s,1,7) #shifts to left by 1
#binary representation of s_shifted should be 1001100

My attempt based on Circular shift in c

def ISHFTC(n, d,N):  
    return (n << d)|(n >> (N - d)) 

However, this does not do what I want. Example,

ISHFTC(57,1,6) #57 is '111001'

gives 115 which is '1110011' whereas I want '110011'


Solution

  • Your attempted solution does not work because Python has unlimited size integers.

    It works in C (for specific values of N, depending on the type used, typically something like 8 or 32), because the bits that are shifted out to the left are automatically truncated.

    You need to do this explicitly in Python to get the same behaviour. Truncating a value to the lowest N bits can be done be using % (1 << N) (the remainder of dividing by 2N).

    Example: ISHFTC(57, 1, 6)

    We want to keep the 6 bits inside |......| and truncate all bits to the left. The bits to the right are truncated automatically, because the these are already the 6 least significant bits.

    n                  |111001|
    a = n << d        1|110010|
    m = (1 << N)      1|000000|
    b = a % m         0|110010|
    
    c = n >> (N - d)   |000001|(11001)
    
    result = b | c     |110011|
    

    Resulting code:

    def ISHFTC(n, d, N):  
        return ((n << d) % (1 << N)) | (n >> (N - d))
              #  ^^^^^^ a
              #             ^^^^^^ m
              #  ^^^^^^^^^^^^^^^^^ b
              #                         ^^^^^^^^^^^^ c
    
    >>> ISHFTC(57, 1, 6)
    51
    >>> bin(_)
    '0b110011'