@compiler >= 4.3 namespace Bitwise = // bit shift 'x' right 'n' postions function bsr(n : int, x : int) : int = let step = 2^n let res = x / step if (x >= 0 || x mod step == 0) res else res - 1 // bit shift 'x' left 'n' positions function bsl(n : int, x : int) : int = x * 2^n // bit shift 'x' left 'n' positions, limit at 'lim' bits function bsli(n : int, x : int, lim : int) : int = (x * 2^n) mod (2^lim) // bitwise 'and' for arbitrary precision integers function band(a : int, b : int) : int = if (a >= 0 && b >= 0) uband_(a, b) elif (b >= 0) ubnand_(b, -1 - a) elif (a >= 0) ubnand_(a, -1 - b) else -1 - ubor_(-1 - a, -1 - b) // bitwise 'or' for arbitrary precision integers function bor : (int, int) => int bor(0, b) = b bor(a, 0) = a bor(a : int, b : int) : int = if (a >= 0 && b >= 0) ubor_(a, b) elif (b >= 0) -1 - ubnand_(-1 - a, b) elif (a >= 0) -1 - ubnand_(-1 - b, a) else -1 - uband_(-1 - a, -1 - b) // bitwise 'xor' for arbitrary precision integers function bxor : (int, int) => int bxor(0, b) = b bxor(a, 0) = a bxor(a, b) = if (a >= 0 && b >= 0) ubxor_(a, b) elif (b >= 0) -1 - ubxor_(-1 - a, b) elif (a >= 0) -1 - ubxor_(a, -1 - b) else ubxor_(-1 - a, -1 - b) // bitwise 'not' for arbitrary precision integers function bnot(a : int) = bxor(a, -1) // Bitwise 'and' for non-negative integers function uband(a : int, b : int) : int = require(a >= 0 && b >= 0, "uband is only defined for non-negative integers") switch((a, b)) (0, _) => 0 (_, 0) => 0 _ => uband__(a, b, 1, 0) private function uband_(a, b) = uband__(a, b, 1, 0) private function uband__(0, b, val, acc) = acc uband__(a, 0, val, acc) = acc uband__(a, b, val, acc) = switch (a mod 2 + b mod 2) 2 => uband__(a / 2, b / 2, val * 2, acc + val) _ => uband__(a / 2, b / 2, val * 2, acc) // Bitwise 'or' for non-negative integers function ubor(a, b) = require(a >= 0 && b >= 0, "ubor is only defined for non-negative integers") switch((a, b)) (0, _) => b (_, 0) => a _ => ubor__(a, b, 1, 0) private function ubor_(a, b) = ubor__(a, b, 1, 0) private function ubor__(0, 0, val, acc) = acc ubor__(a, b, val, acc) = switch (a mod 2 + b mod 2) 0 => ubor__(a / 2, b / 2, val * 2, acc) _ => ubor__(a / 2, b / 2, val * 2, acc + val) //Bitwise 'xor' for non-negative integers function ubxor : (int, int) => int ubxor(0, b) = b ubxor(a, 0) = a ubxor(a, b) = require(a >= 0 && b >= 0, "ubxor is only defined for non-negative integers") ubxor__(a, b, 1, 0) private function ubxor_(a, b) = ubxor__(a, b, 1, 0) private function ubxor__(0, 0, val, acc) = acc ubxor__(a, b, val, acc) = switch(a mod 2 + b mod 2) 1 => ubxor__(a / 2, b / 2, val * 2, acc + val) _ => ubxor__(a / 2, b / 2, val * 2, acc) private function ubnand_(a, b) = ubnand__(a, b, 1, 0) private function ubnand__(0, b, val, acc) = acc ubnand__(a, b, val, acc) = switch((a mod 2, b mod 2)) (1, 0) => ubnand__(a / 2, b / 2, val * 2, acc + val) _ => ubnand__(a / 2, b / 2, val * 2, acc)