How can I implement bitwise operators in Lua language?
Specifically, I need a XOR operator/method.
In Lua 5.2, you can use functions in bit32 library.
In Lua 5.3, bit32 library is obsoleted because there are now native bitwise operators.
print(3 & 5) -- bitwise and
print(3 | 5) -- bitwise or
print(3 ~ 5) -- bitwise xor
print(7 >> 1) -- bitwise right shift
print(7 << 1) -- bitwise left shift
print(~7) -- bitwise not
Output:
1
7
6
3
14
-8
In Lua 5.2, you can use the bit32.bxor function.
Since you're referencing the floor function 3 times, using an excessive number of loops for most operations (numbers less than 2^31 don't need all 31 loops), are using the ^ operator, and aren't capitalizing on the fact that a and b might be wildly different numbers with different magnitudes, you're losing a lot of efficiency. The function also isn't localized, and you're doing two more division operations than you need to. I wrote this to be reasonably fast.
In general, you're going to see improvements of about 3 to 20 times.
local function BitXOR(a,b)--Bitwise xor
local p,c=1,0
while a>0 and b>0 do
local ra,rb=a%2,b%2
if ra~=rb then c=c+p end
a,b,p=(a-ra)/2,(b-rb)/2,p*2
end
if a<b then a=b end
while a>0 do
local ra=a%2
if ra>0 then c=c+p end
a,p=(a-ra)/2,p*2
end
return c
end
If you need more than this, say AND, OR, and NOT, then I've got you covered there, too.
local function BitOR(a,b)--Bitwise or
local p,c=1,0
while a+b>0 do
local ra,rb=a%2,b%2
if ra+rb>0 then c=c+p end
a,b,p=(a-ra)/2,(b-rb)/2,p*2
end
return c
end
local function BitNOT(n)
local p,c=1,0
while n>0 do
local r=n%2
if r<1 then c=c+p end
n,p=(n-r)/2,p*2
end
return c
end
local function BitAND(a,b)--Bitwise and
local p,c=1,0
while a>0 and b>0 do
local ra,rb=a%2,b%2
if ra+rb>1 then c=c+p end
a,b,p=(a-ra)/2,(b-rb)/2,p*2
end
return c
end
Don't worry, you won't need to change anything.
If you're needing an efficient way to do bitwise shifts, I wrote an article about that a while ago. Here's some functions which wrap the technique:
function lshift(x, by)
return x * 2 ^ by
end
function rshift(x, by)
return math.floor(x / 2 ^ by)
end
Try:
function xor(a,b)
return (a or b) and not (a and b)
end
From the OP; moved from question into this answer.
This is how I implemented XOR in Lua:
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
This is very simple. use NAND logic.
https://en.wikipedia.org/wiki/NAND_logic
function xor(a,b)
return not( not( a and not( a and b ) ) and not( b and not( a and b ) ) )
end
if you also need 1,0 inputs insert the following to the function
a = a==1 or a == true -- to accept nil, 1, 0, true or false
b = b==1 or b == true -- to accept nil, 1, 0, true or false
Hope this helps someone.
Related
I have this Lua code in Lua 5.3 for Base64:
local bs = { [0] =
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/',
}
local function base64(s)
local byte, rep = string.byte, string.rep
local pad = 2 - ((#s-1) % 3)
s = (s..rep('\0', pad)):gsub("...", function(cs)
local a, b, c = byte(cs, 1, 3)
return bs[a>>2] .. bs[(a&3)<<4|b>>4] .. bs[(b&15)<<2|c>>6] .. bs[c&63]
end)
return s:sub(1, #s-pad) .. rep('=', pad)
end
I wanted to use it in older versions, but the problem is it does have the bitwise operators (not library). I can easily replace the symbols to the corresponding functions, but I don't know the precedence of Lua bitwise operators.
New user to LUA creating a protocol dissector for Wireshark.
referring to Lua - Bitwise Logical Operations,
I need a function in Lua to create a string based on a converted hex value:
local function HexToCircuitID(val)
-- input: 0x9D81
-- output: "630.1.01"
local e = ((val >> 4) & 0x3) + 1
local f = val & 0xF
local g = val >> 6
return string.format("%d.%d.%02d",e,f,g)
end
the interpreter has a problem with "unexpected symbol near '>' " for the first line with the right-shift operator.
Also, I'm not sure the string format function will operate the same as in C (new to Lua). This function is to create a ProtoField that appears as:
CircuitId: 630.1.01
where the actual value of the field is 0x9D81.
You can use bit.rshift(x, n) to right shift and bit.band(x1[,x2...]) to &.
The function then becomes:
local function HexToCircuitID(val)
-- input: 0x9D81
-- output: "630.1.01"
local e = bit.band(bit.rshift(val, 4), 0x3) + 1
local f = bit.band(val, 0xF)
local g = bit.rshift(val, 6)
--return string.format("%d.%d.%02d",e,f,g)
return string.format("%d.%d.%02d",g,f,e)
end
To get the order right I had to change e,f,g to g,f,e.
This will work in the latest version of Wireshark, which uses Lua 5.2. As Nifim mentioned, you have to use the bit library rather than bitwise operators, as they were introduced in Lua 5.3.
What does this code do?
It's all Lua for World of Warcraft 3.5.5
function __(r) local d = string.sub(r,0x0001,string.len(r)-0x0040) local k = string.sub(r,string.len(r)-0x003F, string.len(r)) d = string.gsub(d, '[^'..k..'=]', '') return (d:gsub('.', function(x) if (x == '=') then return '' end local r,f='',(k:find(x)-1) for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end return r; end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x) if (#x ~= 8) then return '' end local c=0 for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end return string.char(c) end)) end _={_=_G} _._["\108\111\097\100\115\116\114\105\110\103"](_._["\095\095"]("SuperLongStringThatWasRemovedForPrivacyReasons"))()
Now what I am guessing is that this is some sort of encrypted code or something? I am not really sure. What do you guys think it is? / Do you know what this code would do when ran?
NOTE: The really long string... really is long. It's about 150,000 characters long.
The code is equivalent to
loadstring(
decode_from_base64(
("SuperLongStringThatWasRemovedForPrivacyReasons"):sub(1, -65)
)
)()
So, SuperLongStringThatWasRemovedForPrivacyReasons is actually a base-64 encoded Lua program (program may be Lua source or Lua bytecode).
You can easily decode it yourself, there are a lot of online base-64 decoders available.
I'm studying Lua, using the book Programming in Lua, first edition. I'm having trouble understanding metatables.
This is the code and explanations that appear on page 108:
Set = {}
function Set.new (t)
local set = {}
for _, l in ipairs(t) do set[l] = true end
return set
end
function Set.union (a,b)
local res = Set.new{}
for k in pairs(a) do res[k] = true end
for k in pairs(b) do res[k] = true end
return res
end
function Set.intersection (a,b)
local res = Set.new{}
for k in pairs(a) do
res[k] = b[k]
end
return res
end
To help checking our examples, we also define a function to print sets:
function Set.tostring (set)
local s = "{"
local sep = ""
for e in pairs(set) do
s = s .. sep .. e
sep = ", "
end
return s .. "}"
end
function Set.print (s)
print(Set.tostring(s))
end
Now, we want to make the addition operator (+) compute the union of two sets. For that, we will arrange that all tables representing sets share a metatable and this metatable will define how they react to the addition operator. Our first step is to create a regular table that we will use as the metatable for sets. To avoid polluting our namespace, we will store it in the Set table:
Set.mt = {} -- metatable for sets
The next step is to modify the Set.new function, which creates sets. The new version has only one extra line, which sets mt as the metatable for the tables that it creates:
function Set.new (t) -- 2nd version
local set = {}
setmetatable(set, Set.mt)
for _, l in ipairs(t) do set[l] = true end
return set
end
After that, every set we create with Set.new will have that same table as its metatable:
s1 = Set.new{10, 20, 30, 50}
s2 = Set.new{30, 1}
print(getmetatable(s1)) --> table: 00672B60
print(getmetatable(s2)) --> table: 00672B60
Finally, we add to the metatable the so-called metamethod, a field __add that describes how to perform the union:
Set.mt.__add = Set.union
Whenever Lua tries to add two sets, it will call this function, with the two operands as arguments.
With the metamethod in place, we can use the addition operator to do set unions:
s3 = s1 + s2
Set.print(s3) --> {1, 10, 20, 30, 50}
When I tried to run it, I got the result: { union, mt, intersection, tostring, new, print} instead of the numbers in s3. Seems I've printed the contents of the metatables instead. Can someone explain what's happening here? The book describes version 5.0 and I'm using Lua 5.1. Could that be causing this?
There is a bug in the code you ran, not in the code you've posted in the question:
In Set.tostring, line 28, you changed for e in pairs(set) to for e in pairs(Set) and so it always shows the contents of Set, not the contents of the given set.
For a function inside another function, does Lua "instantiate" the inner function on each call to the outer function? If so, would bar() in the code below perform worse than foo()?
local function a()
print 'a'
end
function foo()
a()
end
function bar()
function b()
print 'b'
end
b()
end
Test case 1: a and b both global, no embedding.
$ cat junk.lua ; time lua junk.lua
function a(n)
return n + 1
end
function b(n)
return a(n)
end
for c = 1, 10000000 do
b(c)
end
real 0m1.743s
user 0m1.740s
sys 0m0.000s
User time: 1.74s.
Test case 2: a local, b global, no embedding.
local function a(n)
return n + 1
end
function b(n)
return a(n)
end
for c = 1, 10000000 do
b(c)
end
real 0m1.388s
user 0m1.390s
sys 0m0.000s
User time 1.39s.
Test case 3: a and b both local, no embedding.
$ cat junk.lua ; time lua junk.lua
local function a(n)
return n + 1
end
local function b(n)
return a(n)
end
for c = 1, 10000000 do
b(c)
end
real 0m1.194s
user 0m1.200s
sys 0m0.000s
User time 1.2s.
Test case 4: a embedded in b, a global, b local.
$ cat junk.lua ; time lua junk.lua
local function b(n)
function a(n)
return n + 1
end
return a(n)
end
for c = 1, 10000000 do
b(c)
end
real 0m2.804s
user 0m2.790s
sys 0m0.000s
User time: 2.79s. (!)
Test case 5: a embedded in b, both local.
$ cat junk.lua ; time lua junk.lua
local function b(n)
local function a(n)
return n + 1
end
return a(n)
end
for c = 1, 10000000 do
b(c)
end
real 0m2.540s
user 0m2.530s
sys 0m0.000s
User time: 2.53s.
Result summary:
It's easy to write tests to confirm or deny intuitions about performance. You should probably do this instead of relying on crowd-sourcing the answer. (The crowd is often wrong, you see.)
Making functions local instead of global has a significant positive impact on function call overhead. (About 30% better in this set of test cases when both functions were local.)
Embedding a function in another function has a serious negative impact on function call overhead. (About 110% worse in this set of test cases when both functions were local.)
Did I mention that testing is probably a good idea in lieux of trusting the crowd?
bar will be slower because you are creating a new function object every time. If you want to declare functions inside a function you probably want to return a closure.
local bar = function()
local f = function()
-- Lots of stuff...
end
local g = function()
-- Also lots of stuff
end
return function()
-- Do something with f and g...
end
end
local created_f = bar()
created_f()
created_f() -- Now you can skip the function initialization.
Roberto has written a pretty comprehensive article on Lua Performance Tips like this.