Skip to content

Commit 4857102

Browse files
committed
add BIT.bit32 Lua 5.2 compat submodule; add btest and arshift
1 parent 9867d21 commit 4857102

File tree

3 files changed

+213
-21
lines changed

3 files changed

+213
-21
lines changed

CHANGES.txt

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
2011-11-26
2-
Add functions: tobit, tohex, rshift, lshift, extract, replace, bswap, rrotate, lrotate, rol, ror
1+
2011-11-29
2+
Add functions: tobit, tohex, rshift, lshift, arshift, extract, replace, bswap, rrotate, lrotate, rol, ror, btest
3+
Add BIT.bit32 Lua 5.2 compatibility submodule.
34
Add test suite.
45

56
2011-09-11 - initial import

lmod/bit/numberlua.lua

+191-16
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ LUA MODULE
44
55
bit.numberlua - Bitwise operations implemented in pure Lua as numbers.
66
7+
SYNOPSIS
8+
9+
local bit = require 'bit.numberlua'
10+
print(bit.band(0xff00ff00, 0x00ff00ff)) --> 0xffffffff
11+
12+
-- Interface providing strong Lua 5.2 'bit32' compatibility
13+
local bit32 = require 'bit.numberlua'.bit32
14+
assert(bit32.band(-1) == 0xffffffff)
15+
716
DESCRIPTION
817
918
This library implements bitwise operations entirely in Lua.
@@ -24,6 +33,11 @@ DESCRIPTION
2433
The `xor` function in this module is based partly on Roberto Ierusalimschy's
2534
post in http://lua-users.org/lists/lua-l/2002-09/msg00134.html .
2635
36+
The included BIT.bit32 sublibrary aims to provide 100% compatibility with
37+
the Lua 5.2 "bit32" library. This compatbility is at the cost of some
38+
efficiency since inputted numbers are normalized and more general
39+
forms (e.g. multi-argument bitwise operators) are supported.
40+
2741
STATUS
2842
2943
WARNING: Not all corner cases have been tested and documented.
@@ -32,6 +46,9 @@ STATUS
3246
are currently some differences. Addressing these differences may
3347
be improved in the future but it is not yet fully determined how to
3448
resolve these differences.
49+
50+
The BIT.bit32 library passes the Lua 5.2 test suite (bitwise.lua)
51+
http://www.lua.org/tests/5.2/ .
3552
3653
API
3754
@@ -45,15 +62,15 @@ API
4562
4663
BIT.band(x, y) --> z
4764
48-
Similar to function in Lua 5.2 and BitOp but required two arguments.
65+
Similar to function in Lua 5.2 and BitOp but requires two arguments.
4966
5067
BIT.bor(x, y) --> z
5168
52-
Similar to function in Lua 5.2 and BitOp but required two arguments.
69+
Similar to function in Lua 5.2 and BitOp but requires two arguments.
5370
5471
BIT.bxor(x, y) --> z
5572
56-
Similar to function in Lua 5.2 and BitOp but required two arguments.
73+
Similar to function in Lua 5.2 and BitOp but requires two arguments.
5774
5875
BIT.bnot(x) --> z
5976
@@ -91,12 +108,30 @@ API
91108
92109
BIT.arshift
93110
94-
NOT IMPLEMENTED yet. Similar to function in Lua 5.2 and BitOp.
111+
Similar to function in Lua 5.2 and BitOp.
95112
96113
BIT.btest
97114
98-
NOT IMPLEMENTED yet. Similar to function in Lua 5.2.
115+
Similar to function in Lua 5.2 with requires two arguments.
99116
117+
BIT.bit32
118+
119+
This table contains functions that aim to provide 100% compatibility
120+
with the Lua 5.2 "bit32" library.
121+
122+
bit32.arshift (x, disp) --> z
123+
bit32.band (...) --> z
124+
bit32.bnot (x) --> z
125+
bit32.bor (...) --> z
126+
bit32.btest (...) --> true | false
127+
bit32.bxor (...) --> z
128+
bit32.extract (x, field [, width]) --> z
129+
bit32.replace (x, v, field [, width]) --> z
130+
bit32.lrotate (x, disp) --> z
131+
bit32.lshift (x, disp) --> z
132+
bit32.rrotate (x, disp) --> z
133+
bit32.rshift (x, disp) --> z
134+
100135
DEPENDENCIES
101136
102137
None (other than Lua 5.1 or 5.2).
@@ -140,6 +175,9 @@ local M = {_TYPE='module', _NAME='bit.numberlua', _VERSION='000.003.2011-11-29'}
140175

141176
local floor = math.floor
142177

178+
local MOD = 2^32
179+
local MODM = MOD-1
180+
143181
local function memoize(f)
144182
local mt = {}
145183
local t = setmetatable({}, mt)
@@ -184,24 +222,24 @@ end
184222
M.bxor = make_bitop {[0]={[0]=0,[1]=1},[1]={[0]=1,[1]=0}, n=4}
185223
local bxor = M.bxor
186224

187-
local F8 = 2^32 - 1
188-
function M.bnot(a) return F8 - a end
225+
function M.bnot(a) return MODM - a end
189226
local bnot = M.bnot
190227

191228
function M.band(a,b) return ((a+b) - bxor(a,b))/2 end
192229
local band = M.band
193230

194-
function M.bor(a,b) return F8 - band(F8 - a, F8 - b) end
231+
function M.bor(a,b) return MODM - band(MODM - a, MODM - b) end
232+
local bor = M.bor
195233

196234
local lshift, rshift -- forward declare
197235

198-
function M.rshift(a,disp) -- Lua5.2 style
236+
function M.rshift(a,disp) -- Lua5.2 insipred
199237
if disp < 0 then return lshift(a,-disp) end
200238
return floor(a % 2^32 / 2^disp)
201239
end
202240
rshift = M.rshift
203241

204-
function M.lshift(a,disp) -- Lua5.2 style
242+
function M.lshift(a,disp) -- Lua5.2 inspired
205243
if disp < 0 then return rshift(a,-disp) end
206244
return (a * 2^disp) % 2^32
207245
end
@@ -218,18 +256,20 @@ function M.tohex(x, n) -- BitOp style
218256
return ('%0'..n..(up and 'X' or 'x')):format(x)
219257
end
220258

221-
function M.extract(n, field, width) -- Lua5.2 style
259+
function M.extract(n, field, width) -- Lua5.2 inspired
222260
width = width or 1
223261
return band(rshift(n, field), 2^width-1)
224262
end
263+
local extract = M.extract
225264

226-
function M.replace(n, v, field, width) -- Lua5.2 style
265+
function M.replace(n, v, field, width) -- Lua5.2 inspired
227266
width = width or 1
228267
local mask1 = 2^width-1
229268
v = band(v, mask1) -- required by spec?
230269
local mask = bnot(lshift(mask1, field))
231270
return band(n, mask) + lshift(v, field)
232271
end
272+
local replace = M.replace
233273

234274
function M.bswap(x) -- BitOp style
235275
local a = band(x, 0xff); x = rshift(x, 8)
@@ -239,18 +279,153 @@ function M.bswap(x) -- BitOp style
239279
return lshift(lshift(lshift(a, 8) + b, 8) + c, 8) + d
240280
end
241281

242-
function M.rrotate(x, disp) -- Lua5.2 style
282+
function M.rrotate(x, disp) -- Lua5.2 inspired
243283
disp = disp % 32
244284
local low = band(x, 2^disp-1)
245285
return rshift(x, disp) + lshift(low, 32-disp)
246286
end
247287
local rrotate = M.rrotate
248288

249-
function M.lrotate(x, disp) -- Lua5.2 style
289+
function M.lrotate(x, disp) -- Lua5.2 inspired
250290
return rrotate(x, -disp)
251291
end
292+
local lrotate = M.lrotate
293+
294+
M.rol = M.lrotate -- LuaOp inspired
295+
M.ror = M.rrotate -- LuaOp insipred
296+
297+
298+
function M.arshift(x, disp) -- Lua5.2 inspired
299+
local z = rshift(x, disp)
300+
if x >= 0x80000000 then z = z + lshift(2^disp-1, 32-disp) end
301+
return z
302+
end
303+
304+
function M.btest(x, y) -- Lua5.2 inspired
305+
return band(x, y) ~= 0
306+
end
307+
308+
--
309+
-- Start Lua 5.2 "bit32" compat section.
310+
--
311+
312+
M.bit32 = {} -- Lua 5.2 'bit32' compatibility
313+
314+
315+
local function bit32_bnot(x)
316+
return (-1 - x) % MOD
317+
end
318+
M.bit32.bnot = bit32_bnot
319+
320+
local function bit32_bxor(a, b, c, ...)
321+
local z
322+
if b then
323+
a = a % MOD
324+
b = b % MOD
325+
z = bxor(a, b)
326+
if c then
327+
z = bxor(z, c, ...)
328+
end
329+
return z
330+
elseif a then
331+
return a % MOD
332+
else
333+
return 0
334+
end
335+
end
336+
M.bit32.bxor = bit32_bxor
337+
338+
local function bit32_band(a, b, c, ...)
339+
local z
340+
if b then
341+
a = a % MOD
342+
b = b % MOD
343+
z = ((a+b) - bxor(a,b)) / 2
344+
if c then
345+
z = band(z, c, ...)
346+
end
347+
return z
348+
elseif a then
349+
return a % MOD
350+
else
351+
return MODM
352+
end
353+
end
354+
M.bit32.band = bit32_band
355+
356+
local function bit32_bor(a, b, c, ...)
357+
local z
358+
if b then
359+
a = a % MOD
360+
b = b % MOD
361+
z = MODM - band(MODM - a, MODM - b)
362+
if c then
363+
z = bor(z, c, ...)
364+
end
365+
return z
366+
elseif a then
367+
return a % MOD
368+
else
369+
return 0
370+
end
371+
end
372+
M.bit32.bor = bit32_bor
373+
374+
function M.bit32.btest(...)
375+
return bit32_band(...) ~= 0
376+
end
377+
378+
function M.bit32.lrotate(x, disp)
379+
return lrotate(x % MOD, disp)
380+
end
381+
382+
function M.bit32.rrotate(x, disp)
383+
return rrotate(x % MOD, disp)
384+
end
385+
386+
function M.bit32.lshift(x,disp)
387+
if disp > 31 or disp < -31 then return 0 end
388+
return lshift(x % MOD, disp)
389+
end
390+
391+
function M.bit32.rshift(x,disp)
392+
if disp > 31 or disp < -31 then return 0 end
393+
return rshift(x % MOD, disp)
394+
end
395+
396+
function M.bit32.arshift(x,disp)
397+
x = x % MOD
398+
if disp >= 0 then
399+
if disp > 31 then
400+
return (x >= 0x80000000) and MODM or 0
401+
else
402+
local z = rshift(x, disp)
403+
if x >= 0x80000000 then z = z + lshift(2^disp-1, 32-disp) end
404+
return z
405+
end
406+
else
407+
return lshift(x, -disp)
408+
end
409+
end
410+
411+
function M.bit32.extract(x, field, ...)
412+
local width = ... or 1
413+
if field < 0 or field > 31 or width < 0 or field+width > 32 then error 'out of range' end
414+
x = x % MOD
415+
return extract(x, field, ...)
416+
end
417+
418+
function M.bit32.replace(x, v, field, ...)
419+
local width = ... or 1
420+
if field < 0 or field > 31 or width < 0 or field+width > 32 then error 'out of range' end
421+
x = x % MOD
422+
v = v % MOD
423+
return replace(x, v, field, ...)
424+
end
425+
426+
427+
-- TODO? Likewise add LuaOp "bit" compat section?
428+
-- M.bit32 = {} -- LuaOp "bit" compatibility
252429

253-
M.rol = M.lrotate -- LuaOp style
254-
M.ror = M.rrotate -- LuaOp style
255430

256431
return M

test.lua

+19-3
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ checkeq(bit.band(0xffffffff,0), 0)
4242
checkeq(bit.band(0xa207f158,0x2e1054c9), 0x22005048)
4343
-- note: multiple args not currently supported
4444

45+
-- bit.btest
46+
checkeq(bit.btest(0,0), false)
47+
checkeq(bit.btest(0xf000,0xf000), true)
48+
checkeq(bit.btest(0xffffffff,0), false)
49+
4550
--- bit.bor
4651
checkeq(bit.bor(0,0), 0)
4752
checkeq(bit.bor(0xffffffff,0xffffffff), 0xffffffff)
@@ -82,9 +87,20 @@ checkeq(bit.ror, bit.rrotate)
8287
checkeq(bit.bswap(0x12345678), 0x78563412)
8388
checkeq(bit.bswap(0x78563412), 0x12345678)
8489

85-
--TODO
8690
-- bit.arshift
87-
-- bit.btest
88-
91+
checkeq(bit.arshift(0, 0), 0)
92+
checkeq(bit.arshift(0xffffffff, 0), 0xffffffff)
93+
checkeq(bit.arshift(0xffffffff, 4), 0xffffffff)
94+
checkeq(bit.arshift(0xffffffff, 32), 0xffffffff)
95+
checkeq(bit.arshift(0x7fffffff, 4), 0x07ffffff)
96+
checkeq(bit.arshift(0x7fffffff, 31), 0)
97+
checkeq(bit.arshift(0x7fffffff, 32), 0)
98+
99+
-- Note: optionally run bitwise.lua from Lua test suite.
100+
-- http://www.lua.org/tests/5.2/
101+
if TEST_BIT32 then
102+
bit32 = require 'bit.numberlua' . bit32
103+
dofile 'bitwise.lua'
104+
end
89105

90106
print 'DONE'

0 commit comments

Comments
 (0)