Bit Utils |
|
-- Bitwise XOR - thanks to Reuben Thomas local floor = math.floor function bxor (a,b) local r = 0 for i = 0, 31 do local x = a / 2 + b / 2 if x ~= floor (x) then r = r + 2^i end a = floor (a / 2) b = floor (b / 2) end return r end
If you need speed, the following is a lot faster (Arno Wagner <arno@wagner.name>):
function bin_xor(x, y) local z = 0 for i = 0, 31 do if (x % 2 == 0) then -- x had a '0' in bit i if ( y % 2 == 1) then -- y had a '1' in bit i y = y - 1 z = z + 2 ^ i -- set bit i of z to '1' end else -- x had a '1' in bit i x = x - 1 if (y % 2 == 0) then -- y had a '0' in bit i z = z + 2 ^ i -- set bit i of z to '1' else y = y - 1 end end y = y / 2 x = x / 2 end return z end
It is also possible to do this without using the power function. The below implementation should be faster than the above in most cases. Though admittedly I have not verified this experimentally.
function xor(a,b) pow = 1 c = 0 while a > 0 or b > 0 do c = c + (XOR_l[(a % 2)+1][(b % 2)+1] * pow) a = math.floor(a/2) b = math.floor(b/2) pow = pow * 2 end return c end XOR_l = { {0,1}, {1,0}, }
function testflag(set, flag) return set % (2*flag) >= flag end function setflag(set, flag) if set % (2*flag) >= flag then return set end return set + flag end function clrflag(set, flag) -- clear flag if set % (2*flag) >= flag then return set - flag end return set end -- Test suite local b = { ['_0000'] = 0, ['_0001'] = 1, ['_0010'] = 2, ['_0011'] = 3, ['_1000'] = 8, ['_1010'] = 10, ['_1011'] = 11, } assert(not testflag(b._0000, b._0001)) assert(not testflag(b._0000, b._0010)) assert(not testflag(b._0010, b._0001)) assert( testflag(b._0010, b._0010)) assert(setflag(b._0000, b._0001) == b._0001) assert(setflag(b._0000, b._0010) == b._0010) assert(setflag(b._1010, b._0001) == b._1011) assert(setflag(b._1010, b._0010) == b._1010) assert(clrflag(b._0000, b._0001) == b._0000) assert(clrflag(b._0000, b._0010) == b._0000) assert(clrflag(b._1010, b._0001) == b._1010) assert(clrflag(b._1010, b._0010) == b._1000)