How to sequentially set bits - python

When the if statement is true I want to sequentially set every bit in the left shift operation one at a time rather than setting all bits at once. Any idea on how I could implement this?
if (reg_test == arduino_reg7.value):
Reg_Value |= (0x1A << 20)

If I understand, you want to have `Reg_Value' be set to each of these in succession:
0bxxxx_xxxx_xxxx_xxxx_xxxx_xxxx
0bxxx1_xxxx_xxxx_xxxx_xxxx_xxxx
0bxx01_xxxx_xxxx_xxxx_xxxx_xxxx
0bx101_xxxx_xxxx_xxxx_xxxx_xxxx
0b1101_xxxx_xxxx_xxxx_xxxx_xxxx
Where the 'x' bits are left unmodified
I would suggest:
if (reg_test == arduino_reg7.value):
bval = 0x1A
for i in range(20,28):
Reg_Value |= (bval << 20) & (1 << (i+1))
This allows for any byte value (bval) to be placed in bits 20-27 one bit at a time, in ascending order. Any higher-order bits are also left unchanged.
You could simplify the (1 << (i+1)) to (1 << i) by changing the range to range(21, 29). But bits are typically numbered from 0, and this affects bits 20-27, not 21-28.
You could also change it to (2 << i) and leave the range, but I think that obscures what you're really doing -- though that's a personal preference. Unless timing is extremely critical, the extra +1 won't make a difference.

Assuming that your value of 0x1A is constant then you could simply create a list where each element represents one of the 3 bits. Then:
bits = [0x10 << 20, 0x8 << 20, 0x2 << 20]
if (reg_test == arduino_reg7.value):
for b in bits:
Reg_Value |= b
If 0x1A is not constant, then you could build your array of bits like this:
v = 0x1a # or some other 8-bit value
bits = []
b = 1
while v > 0:
if v & 1:
bits.append(b<<20)
b <<= 1
v >>= 1

Related

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'
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'

Python3 logical left shift

By default the 'left shift' operation in Python ( << ) acts as an arithmetic shift and appends a 0 bit to the end of the bits representing the int.
For example:
100 << 1 returns 200
In the binary representation we can see that 100 = 0b1100100 (7 bits) and 100 << 1 = 0b11001000 (8 bits)
In Python 3 what is the best way to perform a logical left shift where the number of bits stays constant, but the values are shifted to the left one?
For example:
100 << 1 would return 72
In the binary representation 100 = 0b1100100 and 100 << 1 = 0b1001000
We've kept the same 7 bits, but just shifted to the left one and appended a 0 to the end.
You can use int.bitlength to get the number of bits required to represent the number, then and the result of the shift with (1 << bitlength) - 1 to restrict the result to that many bits:
def lls_const_bits(n):
return (n << 1) & ((1 << n.bit_length()) - 1)
print(lls_const_bits(100))
Output:
72
If you want to restrict the output to a fixed number of bits b, you would need to mask with (1 << b) - 1:
def lls_const_bits(n, b):
return (n << 1) & ((1 << b) - 1)
print(lls_const_bits(100, 7))
Output:
72

bitwise operation and Two's complement in python

I have an array of (short) data which is shifted 4 to left and it is also a signed number. I need to plot it around zero.
for instance: if the number in the array is 0b0000000011111111 and I shift it to left by 4, I will get 0b000000001111. it is fine.
for instance: if the number in the array is 0b100011111111 and I shift it to left by 4, I will get 0b000010001111. It is fine, but now it is not a negative number.
can someone help ?
You have to write your own implementation of the arithmetic right shift of a 16-bit value, if this is what you need. I suggest you this one, very easy to understand:
def arithmetic_right_shift_on_16_bits(val, n):
# Get the sign bit
s = val & 0x8000
# Perform the shifts, padding with the sign bit
for _ in range(n):
val >>= 1
val |= s
return val
a = arithmetic_right_shift_on_16_bits(0b0000000011111111, 4)
print(bin(a)) # 0b1111
b = arithmetic_right_shift_on_16_bits(0b1000000011111111, 4)
print(bin(b)) # 0b1111100000001111
This does not happen in Python:
>>> bin(0b0000000011111111 >> 4) # 15
'0b1111'
>>> bin(0b100011111111 >> 4) # 143
'0b10001111'
BTW, the number you show as an example of a negative short integer is not one, because you gave only 12 bits. So I will assume that the number of interest is 0b1000000011111111. As Python does not use 2's complement, it is shown as 33023. But you can do the 2's complement by hand: for a short int (16 bits), you just substract 0x10000 to the number.
You can then write:
def short_signed_right_shift(x, i):
if x < 0 or x >= 0x10000: raise ValueError # only accept 16 bits numbers
return x >> i if (x < 0x7FFF) else 0x10000 + ((x - 0x10000) >> i)
You can then use it:
>>> bin(short_signed_right_shift(0b0000000011111111, 4))
'0b1111'
>>> bin(short_signed_right_shift(0b1000000011111111, 4))
'0b1111100000001111'

Creating a bit mask with BigInts

Is there a more efficient way of performing the following calculation? It works fine, but something tells me that x &= (1 << 8) - 1 ^ 1 << 3 can be written to avoid some calculations and increase speed.
def unset_mask(width, index):
return (1 << width) - 1 ^ 1 << index
x = 0b11111111
x &= unset_mask(8, 3)
assert x == 0b11110111
Actually, you don't need to state the width. Bigints behave the right way when you do this:
>>> bin(255 & ~(1 << 3))
'0b11110111'
>>> bin(65535 & ~(1 << 3))
'0b1111111111110111'
>>> bin(75557863725914323419135 & ~(1 << 3))
'0b1111111111111111111111111111111111111111111111111111111111111111111111110111'
It's because negative numbers have an "infinite" string of ones preceding them. So when you complement a positive number (which starts with an "infinte" string of zeros), you get a negative number (-(x + 1) to be exact). Just don't trust the bin representation of negative numbers; it doesn't reflect the actual bits in memory.
So you would rewrite unset_mask like so:
def unset_mask(index):
return ~(1 << index)
x = 0b11111111
x &= unset_mask(3)
print x == 0b11110111 # prints True
You can use this to clear a bit in x:
x &= ~(1 << index)
This will unset the bit:
x ^= 1 << 3 & x
In a function:
def unset_bit(x, n):
return 1 << n & x ^ x

Please help me understand a bit shift operation

def different(s):
x = len(s)
for i in range(1, 1 << x):
u.append([s[j] for j in range(x) if (i & (1 << j))])
It takes a list and makes different combinations
(a,b,c) = ((a,b,c),(a,b),(a,c) ...)
But what does the range do? From 1 to what. I don't understand the "<<"
and also, if (i & (1 << j)) what does this do? It checks if i and 2 to the power of j? Doesn't make any sense to me.
The range function returns a list of numbers from zero to the given number minus one. It also has two- and three-argument forms (see the doc for more info):
range(n) == [0, 1, 2, ..., n - 1]
<< is the left-shift operator, and has the effect of multiplying the left hand side by two to the power of the right hand side:
x << n == x * 2**n
Thus the above range function (range(1, 1 << x)) returns [1, 2, 3, ..., 2**x - 1].
In the seconds usage of <<, the left-shift is being used as a bit-mask. It moves the 1-bit into the j-th bit, and performs a bit-wise and with i, so the result will be non-zero (and pass the if test) if and only if the j-th bit of i is set. For example:
j = 4
1 << j = 0b1000 (binary notation)
i = 41 = 0b101001
i & (1 << j) = 0b101001
& 0b001000
= 0b001000 (non-zero, the if-test passes)
i = 38 = 0b100110
i & (1 << j) = 0b100110
& 0b001000
= 0b000000 (zero, the if-test fails)
In short, x & (1 << y) is non-zero iff the y-th bit of x is set.
<< is the binary left shift operator. 1 << x is a way of saying two to the power of x.

Categories