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}, }
If speed is not your concern, the following could be shorter.
local function nand(x,y,z) z=z or 2^16 if z<2 then return 1-x*y else return nand((x-x%z)/z,(y-y%z)/z,math.sqrt(z))*z+nand(x%z,y%z,math.sqrt(z)) end end math["not"]=function(y,z) return nand(nand(0,0,z),y,z) end math["and"]=function(x,y,z) return nand(math["not"](0,z),nand(x,y,z),z) end math["or"]=function(x,y,z) return nand(math["not"](x,z),math["not"](y,z),z) end math["xor"]=function(x,y,z) return math["and"](nand(x,y,z),math["or"](x,y,z),z) end
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 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)