Home
/
Bitwise Operations
Bitwise Operations
Levython provides low-level bitwise operations for efficient bit manipulation and system programming.
Bitwise Operators
| Operator |
Name |
Example |
Result |
& |
AND |
12 & 10 |
8 |
| |
OR |
12 | 10 |
14 |
^ |
XOR |
12 ^ 10 |
6 |
~ |
NOT |
~12 |
-13 |
<< |
Left shift |
5 << 2 |
20 |
>> |
Right shift |
20 >> 2 |
5 |
Basic Examples
AND Operation
# Bitwise AND
# 12 = 1100
# 10 = 1010
# ----
# 1000 = 8
result <- 12 & 10
say(result) # Output: 8
# Check if bit is set
flags <- 0b1101 # Binary literal
if (flags & 0b0100) != 0 then
say("Bit 2 is set")
end
OR Operation
# Bitwise OR
# 12 = 1100
# 10 = 1010
# ----
# 1110 = 14
result <- 12 | 10
say(result) # Output: 14
# Set a bit
flags <- 0b1001
flags <- flags | 0b0100 # Set bit 2
say(flags) # Output: 13 (0b1101)
XOR Operation
# Bitwise XOR
# 12 = 1100
# 10 = 1010
# ----
# 0110 = 6
result <- 12 ^ 10
say(result) # Output: 6
# Toggle a bit
flags <- 0b1101
flags <- flags ^ 0b0100 # Toggle bit 2
say(flags) # Output: 9 (0b1001)
NOT Operation
# Bitwise NOT (complement)
result <- ~12
say(result) # Output: -13
# Explanation: ~12 flips all bits
# 12 = 00001100 → 11110011 = -13 (two's complement)
Shift Operations
# Left shift (multiply by 2^n)
result <- 5 << 2 # 5 * 2^2 = 20
say(result) # Output: 20
# Right shift (divide by 2^n)
result <- 20 >> 2 # 20 / 2^2 = 5
say(result) # Output: 5
# Efficient power of 2 multiplication
x <- 7
x2 <- x << 1 # x * 2 = 14
x4 <- x << 2 # x * 4 = 28
x8 <- x << 3 # x * 8 = 56
Common Patterns
Bit Masking
# Extract specific bits
value <- 0b11010110
mask <- 0b00001111
lower_bits <- value & mask
say(lower_bits) # Output: 6 (0b0110)
# Extract bytes from integer
num <- 0x12345678
byte0 <- num & 0xFF # 0x78
byte1 <- (num >> 8) & 0xFF # 0x56
byte2 <- (num >> 16) & 0xFF # 0x34
byte3 <- (num >> 24) & 0xFF # 0x12
Set/Clear/Toggle Bits
# Set bit at position n
fun set_bit(value, n)
return value | (1 << n)
end
# Clear bit at position n
fun clear_bit(value, n)
return value & ~(1 << n)
end
# Toggle bit at position n
fun toggle_bit(value, n)
return value ^ (1 << n)
end
# Check if bit n is set
fun is_bit_set(value, n)
return (value & (1 << n)) != 0
end
# Example usage
flags <- 0
flags <- set_bit(flags, 2) # Set bit 2
flags <- set_bit(flags, 5) # Set bit 5
say(flags) # Output: 36 (0b100100)
flags <- clear_bit(flags, 2) # Clear bit 2
say(flags) # Output: 32 (0b100000)
Swap Without Temporary
# XOR swap trick
a <- 10
b <- 20
say("Before: a=" + str(a) + ", b=" + str(b))
a <- a ^ b
b <- a ^ b
a <- a ^ b
say("After: a=" + str(a) + ", b=" + str(b))
# Output: a=20, b=10
Count Set Bits
# Count number of 1 bits (population count)
fun popcount(n)
count <- 0
while n > 0 do
count <- count + (n & 1)
n <- n >> 1
end
return count
end
say(popcount(0b1011)) # Output: 3
say(popcount(15)) # Output: 4 (0b1111)
Check Power of Two
# Check if number is power of 2
fun is_power_of_two(n)
return n > 0 and (n & (n - 1)) == 0
end
say(is_power_of_two(16)) # true
say(is_power_of_two(15)) # false
say(is_power_of_two(32)) # true
Practical Applications
Flags and Permissions
# Define permission flags
READ <- 1 # 0b001
WRITE <- 2 # 0b010
EXEC <- 4 # 0b100
# Grant permissions
perms <- READ | WRITE # 0b011
# Check permission
if (perms & WRITE) != 0 then
say("Write permission granted")
end
# Add permission
perms <- perms | EXEC # Now 0b111
# Remove permission
perms <- perms & ~WRITE # Remove write
Color Manipulation
# RGB color as 24-bit integer (0xRRGGBB)
fun make_color(r, g, b)
return (r << 16) | (g << 8) | b
end
fun get_red(color)
return (color >> 16) & 0xFF
end
fun get_green(color)
return (color >> 8) & 0xFF
end
fun get_blue(color)
return color & 0xFF
end
# Create color
purple <- make_color(128, 0, 128)
say("Red: " + str(get_red(purple))) # 128
say("Green: " + str(get_green(purple))) # 0
say("Blue: " + str(get_blue(purple))) # 128
Bit Packing
# Pack multiple values into single integer
fun pack(a, b, c, d)
# Pack 4 bytes into 32-bit integer
return (a << 24) | (b << 16) | (c << 8) | d
end
fun unpack(value)
a <- (value >> 24) & 0xFF
b <- (value >> 16) & 0xFF
c <- (value >> 8) & 0xFF
d <- value & 0xFF
return [a, b, c, d]
end
# Usage
packed <- pack(10, 20, 30, 40)
values <- unpack(packed)
say(values) # [10, 20, 30, 40]
Performance Tips
- Bitwise operations are extremely fast (single CPU cycle)
- Use shifts instead of multiply/divide by powers of 2
- Bit masks are faster than multiple boolean checks
- Pack related flags into single integer instead of separate booleans
- Bitwise AND with power of 2 minus 1 is fast modulo:
n & (2^k - 1)
Reference Table
| Operation |
Formula |
Use Case |
| Set bit n |
x | (1 << n) |
Turn bit on |
| Clear bit n |
x & ~(1 << n) |
Turn bit off |
| Toggle bit n |
x ^ (1 << n) |
Flip bit |
| Test bit n |
(x & (1 << n)) != 0 |
Check if set |
| Power of 2? |
(x & (x-1)) == 0 |
Validation |
| Multiply by 2^n |
x << n |
Fast multiply |
| Divide by 2^n |
x >> n |
Fast divide |