Skip to content

Commit d7df179

Browse files
committed
add BIT.bit LuaBitOp compatibility interface
1 parent 4857102 commit d7df179

File tree

5 files changed

+219
-15
lines changed

5 files changed

+219
-15
lines changed

CHANGES.txt

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
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.
4-
Add test suite.
2+
Added functions: tobit, tohex, rshift, lshift, arshift, extract, replace, bswap, rrotate, lrotate, rol, ror, btest
3+
Added BIT.bit32 Lua 5.2 compatibility submodule.
4+
Added BIT.bit LuaBitOp compatibility submodule.
5+
Added test suite.
56

67
2011-09-11 - initial import
78

README.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
Bitwise operations implemented entirely in Lua.
2+
Includes Lua 5.2 'bit32' and (LuaJIT) LuaBitOp 'bit' compatibility interfaces.
23

34
See comments in lmod/bit/numberlua.lua for details.

contrib/bittest.lua

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
-- This file was taken from LuaBitOp http://bitop.luajit.org/ .
2+
-- Test cases for bit operations library. Public domain.
3+
4+
local bit = require"bit"
5+
6+
local vb = {
7+
0, 1, -1, 2, -2, 0x12345678, 0x87654321,
8+
0x33333333, 0x77777777, 0x55aa55aa, 0xaa55aa55,
9+
0x7fffffff, 0x80000000, 0xffffffff
10+
}
11+
12+
local function cksum(name, s, r)
13+
local z = 0
14+
for i=1,#s do z = (z + string.byte(s, i)*i) % 2147483629 end
15+
if z ~= r then
16+
error("bit."..name.." test failed (got "..z..", expected "..r..")", 0)
17+
end
18+
end
19+
20+
local function check_unop(name, r)
21+
local f = bit[name]
22+
local s = ""
23+
if pcall(f) or pcall(f, "z") or pcall(f, true) then
24+
error("bit."..name.." fails to detect argument errors", 0)
25+
end
26+
for _,x in ipairs(vb) do s = s..","..tostring(f(x)) end
27+
cksum(name, s, r)
28+
end
29+
30+
local function check_binop(name, r)
31+
local f = bit[name]
32+
local s = ""
33+
if pcall(f) or pcall(f, "z") or pcall(f, true) then
34+
error("bit."..name.." fails to detect argument errors", 0)
35+
end
36+
for _,x in ipairs(vb) do
37+
for _,y in ipairs(vb) do s = s..","..tostring(f(x, y)) end
38+
end
39+
cksum(name, s, r)
40+
end
41+
42+
local function check_binop_range(name, r, yb, ye)
43+
local f = bit[name]
44+
local s = ""
45+
if pcall(f) or pcall(f, "z") or pcall(f, true) or pcall(f, 1, true) then
46+
error("bit."..name.." fails to detect argument errors", 0)
47+
end
48+
for _,x in ipairs(vb) do
49+
for y=yb,ye do s = s..","..tostring(f(x, y)) end
50+
end
51+
cksum(name, s, r)
52+
end
53+
54+
local function check_shift(name, r)
55+
check_binop_range(name, r, 0, 31)
56+
end
57+
58+
-- Minimal sanity checks.
59+
assert(0x7fffffff == 2147483647, "broken hex literals")
60+
assert(0xffffffff == -1 or 0xffffffff == 2^32-1, "broken hex literals")
61+
assert(tostring(-1) == "-1", "broken tostring()")
62+
assert(tostring(0xffffffff) == "-1" or tostring(0xffffffff) == "4294967295", "broken tostring()")
63+
64+
-- Basic argument processing.
65+
assert(bit.tobit(1) == 1)
66+
assert(bit.band(1) == 1)
67+
assert(bit.bxor(1,2) == 3)
68+
assert(bit.bor(1,2,4,8,16,32,64,128) == 255)
69+
70+
-- Apply operations to test vectors and compare checksums.
71+
check_unop("tobit", 277312)
72+
check_unop("bnot", 287870)
73+
check_unop("bswap", 307611)
74+
75+
check_binop("band", 41206764)
76+
check_binop("bor", 51253663)
77+
check_binop("bxor", 79322427)
78+
79+
check_shift("lshift", 325260344)
80+
check_shift("rshift", 139061800)
81+
check_shift("arshift", 111364720)
82+
check_shift("rol", 302401155)
83+
check_shift("ror", 302316761)
84+
85+
check_binop_range("tohex", 47880306, -8, 8)
86+

lmod/bit/numberlua.lua

+113-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
33
LUA MODULE
44
5-
bit.numberlua - Bitwise operations implemented in pure Lua as numbers.
5+
bit.numberlua - Bitwise operations implemented in pure Lua as numbers,
6+
with Lua 5.2 'bit32' and (LuaJIT) LuaBitOp 'bit' compatibility interfaces.
67
78
SYNOPSIS
89
@@ -13,6 +14,10 @@ SYNOPSIS
1314
local bit32 = require 'bit.numberlua'.bit32
1415
assert(bit32.band(-1) == 0xffffffff)
1516
17+
-- Interface providing strong (LuaJIT) LuaBitOp 'bit' compatibility
18+
local bit = require 'bit.numberlua'.bit
19+
assert(bit.tobit(0xffffffff) == -1)
20+
1621
DESCRIPTION
1722
1823
This library implements bitwise operations entirely in Lua.
@@ -33,10 +38,11 @@ DESCRIPTION
3338
The `xor` function in this module is based partly on Roberto Ierusalimschy's
3439
post in http://lua-users.org/lists/lua-l/2002-09/msg00134.html .
3540
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.
41+
The included BIT.bit32 and BIT.bit sublibraries aims to provide 100%
42+
compatibility with the Lua 5.2 "bit32" and (LuaJIT) LuaBitOp "bit" library.
43+
This compatbility is at the cost of some efficiency since inputted
44+
numbers are normalized and more general forms (e.g. multi-argument
45+
bitwise operators) are supported.
4046
4147
STATUS
4248
@@ -48,7 +54,9 @@ STATUS
4854
resolve these differences.
4955
5056
The BIT.bit32 library passes the Lua 5.2 test suite (bitwise.lua)
51-
http://www.lua.org/tests/5.2/ .
57+
http://www.lua.org/tests/5.2/ . The BIT.bit library passes the LuaBitOp
58+
test suite (bittest.lua). However, these have not been tested on
59+
platforms with Lua compiled with 32-bit integer numbers.
5260
5361
API
5462
@@ -131,6 +139,24 @@ API
131139
bit32.lshift (x, disp) --> z
132140
bit32.rrotate (x, disp) --> z
133141
bit32.rshift (x, disp) --> z
142+
143+
BIT.bit
144+
145+
This table contains functions that aim to provide 100% compatibility
146+
with the LuaBitOp "bit" library (from LuaJIT).
147+
148+
bit.tobit(x) --> y
149+
bit.tohex(x [,n]) --> y
150+
bit.bnot(x) --> y
151+
bit.bor(x1 [,x2...]) --> y
152+
bit.band(x1 [,x2...]) --> y
153+
bit.bxor(x1 [,x2...]) --> y
154+
bit.lshift(x, n) --> y
155+
bit.rshift(x, n) --> y
156+
bit.arshift(x, n) --> y
157+
bit.rol(x, n) --> y
158+
bit.ror(x, n) --> y
159+
bit.bswap(x) --> y
134160
135161
DEPENDENCIES
136162
@@ -248,13 +274,15 @@ lshift = M.lshift
248274
function M.tohex(x, n) -- BitOp style
249275
n = n or 8
250276
local up
251-
if n < 0 then
277+
if n <= 0 then
278+
if n == 0 then return '' end
252279
up = true
253280
n = - n
254281
end
255282
x = band(x, 16^n-1)
256283
return ('%0'..n..(up and 'X' or 'x')):format(x)
257284
end
285+
local tohex = M.tohex
258286

259287
function M.extract(n, field, width) -- Lua5.2 inspired
260288
width = width or 1
@@ -278,6 +306,7 @@ function M.bswap(x) -- BitOp style
278306
local d = band(x, 0xff)
279307
return lshift(lshift(lshift(a, 8) + b, 8) + c, 8) + d
280308
end
309+
local bswap = M.bswap
281310

282311
function M.rrotate(x, disp) -- Lua5.2 inspired
283312
disp = disp % 32
@@ -300,6 +329,7 @@ function M.arshift(x, disp) -- Lua5.2 inspired
300329
if x >= 0x80000000 then z = z + lshift(2^disp-1, 32-disp) end
301330
return z
302331
end
332+
local arshift = M.arshift
303333

304334
function M.btest(x, y) -- Lua5.2 inspired
305335
return band(x, y) ~= 0
@@ -424,8 +454,82 @@ function M.bit32.replace(x, v, field, ...)
424454
end
425455

426456

427-
-- TODO? Likewise add LuaOp "bit" compat section?
428-
-- M.bit32 = {} -- LuaOp "bit" compatibility
457+
--
458+
-- Start LuaBitOp "bit" compat section.
459+
--
460+
461+
M.bit = {} -- LuaBitOp "bit" compatibility
462+
463+
function M.bit.tobit(x)
464+
x = x % MOD
465+
if x >= 0x80000000 then x = x - MOD end
466+
return x
467+
end
468+
local bit_tobit = M.bit.tobit
469+
470+
function M.bit.tohex(x, ...)
471+
return tohex(x % MOD, ...)
472+
end
473+
474+
function M.bit.bnot(x)
475+
return bit_tobit(bnot(x % MOD))
476+
end
477+
478+
local function bit_bor(a, b, c, ...)
479+
if c then
480+
return bit_bor(bit_bor(a, b), c, ...)
481+
elseif b then
482+
return bit_tobit(bor(a % MOD, b % MOD))
483+
else
484+
return bit_tobit(a)
485+
end
486+
end
487+
M.bit.bor = bit_bor
488+
489+
local function bit_band(a, b, c, ...)
490+
if c then
491+
return bit_band(bit_band(a, b), c, ...)
492+
elseif b then
493+
return bit_tobit(band(a % MOD, b % MOD))
494+
else
495+
return bit_tobit(a)
496+
end
497+
end
498+
M.bit.band = bit_band
499+
500+
local function bit_bxor(a, b, c, ...)
501+
if c then
502+
return bit_bxor(bit_bxor(a, b), c, ...)
503+
elseif b then
504+
return bit_tobit(bxor(a % MOD, b % MOD))
505+
else
506+
return bit_tobit(a)
507+
end
508+
end
509+
M.bit.bxor = bit_bxor
510+
511+
function M.bit.lshift(x, n)
512+
return bit_tobit(lshift(x % MOD, n % 32))
513+
end
429514

515+
function M.bit.rshift(x, n)
516+
return bit_tobit(rshift(x % MOD, n % 32))
517+
end
518+
519+
function M.bit.arshift(x, n)
520+
return bit_tobit(arshift(x % MOD, n % 32))
521+
end
522+
523+
function M.bit.rol(x, n)
524+
return bit_tobit(lrotate(x % MOD, n % 32))
525+
end
526+
527+
function M.bit.ror(x, n)
528+
return bit_tobit(rrotate(x % MOD, n % 32))
529+
end
530+
531+
function M.bit.bswap(x)
532+
return bit_tobit(bswap(x % MOD))
533+
end
430534

431535
return M

test.lua

+15-3
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,23 @@ checkeq(bit.arshift(0x7fffffff, 4), 0x07ffffff)
9696
checkeq(bit.arshift(0x7fffffff, 31), 0)
9797
checkeq(bit.arshift(0x7fffffff, 32), 0)
9898

99-
-- Note: optionally run bitwise.lua from Lua test suite.
99+
-- BIT.bit32.
100+
-- Optionally run bitwise.lua from Lua test suite.
100101
-- http://www.lua.org/tests/5.2/
101102
if TEST_BIT32 then
102-
bit32 = require 'bit.numberlua' . bit32
103-
dofile 'bitwise.lua'
103+
_G.bit32 = require 'bit.numberlua' . bit32
104+
dofile 'contrib/bitwise.lua'
104105
end
105106

107+
-- BIT.bit
108+
-- Optionally run bittest.lua (included) from LuaBitOp test suite.
109+
-- http://bitop.luajit.org/
110+
--if TEST_BIT then
111+
package.loaded.bit = bit.bit
112+
dofile 'contrib/bittest.lua'
113+
--end
114+
115+
-- BIT.bit.
116+
117+
106118
print 'DONE'

0 commit comments

Comments
 (0)