├── .travis.yml ├── CMakeLists.txt ├── Makefile ├── Makefile.mingw ├── README ├── bit.c ├── bit.def ├── bitbench.lua ├── bittest.lua ├── cmake ├── FindLua.cmake ├── dist.cmake └── lua.cmake ├── dist.info ├── doc ├── api.html ├── bluequad-print.css ├── bluequad.css ├── changes.html ├── contact.html ├── img │ └── contact.png ├── index.html ├── install.html └── semantics.html ├── installpath.lua ├── md5test.lua ├── msvcbuild.bat ├── msvctest.bat └── nsievebits.lua /.travis.yml: -------------------------------------------------------------------------------- 1 | # 2 | # LuaDist Travis-CI Hook 3 | # 4 | 5 | # We assume C build environments 6 | language: C 7 | 8 | # Try using multiple Lua Implementations 9 | env: 10 | - TOOL="gcc" # Use native compiler (GCC usually) 11 | - TOOL="clang" # Use clang 12 | - TOOL="i686-w64-mingw32" # 32bit MinGW 13 | - TOOL="x86_64-w64-mingw32" # 64bit MinGW 14 | - TOOL="arm-linux-gnueabihf" # ARM hard-float (hf), linux 15 | 16 | # Crosscompile builds may fail 17 | matrix: 18 | allow_failures: 19 | - env: TOOL="i686-w64-mingw32" 20 | - env: TOOL="x86_64-w64-mingw32" 21 | - env: TOOL="arm-linux-gnueabihf" 22 | 23 | # Install dependencies 24 | install: 25 | - git clone git://github.com/LuaDist/Tools.git ~/_tools 26 | - ~/_tools/travis/travis install 27 | 28 | # Bootstap 29 | before_script: 30 | - ~/_tools/travis/travis bootstrap 31 | 32 | # Build the module 33 | script: 34 | - ~/_tools/travis/travis build 35 | 36 | # Execute additional tests or commands 37 | after_script: 38 | - ~/_tools/travis/travis test 39 | 40 | # Only watch the master branch 41 | branches: 42 | only: 43 | - master 44 | 45 | # Notify the LuaDist Dev group if needed 46 | notifications: 47 | recipients: 48 | - luadist-dev@googlegroups.com 49 | email: 50 | on_success: change 51 | on_failure: always 52 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2012 LuaDist. 2 | # Created by Peter Drahoš 3 | # Redistribution and use of this file is allowed according to the terms of the MIT license. 4 | # For details see the COPYRIGHT file distributed with LuaDist. 5 | # Please note that the package source code is licensed under its own license. 6 | 7 | project ( luabitop C ) 8 | cmake_minimum_required ( VERSION 2.8 ) 9 | include ( cmake/dist.cmake ) 10 | include ( lua ) 11 | 12 | install_lua_module ( bit bit.c bit.def ) 13 | 14 | add_lua_test ( bittest.lua ) 15 | add_lua_test ( nsievebits.lua ) 16 | add_lua_test ( md5test.lua ) 17 | 18 | install_doc ( doc/ ) 19 | install_data ( README ) 20 | install_foo ( bitbench.lua nsievebits.lua md5test.lua ) 21 | install_test ( bittest.lua ) 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Lua BitOp -- a bit operations library for Lua 5.1/5.2. 2 | # To compile with MSVC please run: msvcbuild.bat 3 | # To compile with MinGW please run: mingw32-make -f Makefile.mingw 4 | 5 | # Include path where lua.h, luaconf.h and lauxlib.h reside: 6 | INCLUDES= -I/usr/local/include 7 | 8 | DEFINES= 9 | # Use this for the old ARM ABI with swapped FPA doubles. 10 | # Do NOT use this for modern ARM EABI with VFP or soft-float! 11 | #DEFINES= -DSWAPPED_DOUBLE 12 | 13 | # Lua executable name. Used to find the install path and for testing. 14 | LUA= lua 15 | 16 | CC= gcc 17 | CCOPT= -O2 -fomit-frame-pointer 18 | CCWARN= -Wall 19 | SOCC= $(CC) -shared 20 | SOCFLAGS= -fPIC $(CCOPT) $(CCWARN) $(DEFINES) $(INCLUDES) $(CFLAGS) 21 | SOLDFLAGS= -fPIC $(LDFLAGS) 22 | RM= rm -f 23 | INSTALL= install -p 24 | INSTALLPATH= $(LUA) installpath.lua 25 | 26 | MODNAME= bit 27 | MODSO= $(MODNAME).so 28 | 29 | all: $(MODSO) 30 | 31 | # Alternative target for compiling on Mac OS X: 32 | macosx: 33 | $(MAKE) all "SOCC=MACOSX_DEPLOYMENT_TARGET=10.4 $(CC) -dynamiclib -single_module -undefined dynamic_lookup" 34 | 35 | $(MODNAME).o: $(MODNAME).c 36 | $(CC) $(SOCFLAGS) -c -o $@ $< 37 | 38 | $(MODSO): $(MODNAME).o 39 | $(SOCC) $(SOLDFLAGS) -o $@ $< 40 | 41 | install: $(MODSO) 42 | $(INSTALL) $< `$(INSTALLPATH) $(MODNAME)` 43 | 44 | test: $(MODSO) 45 | @$(LUA) bittest.lua && echo "basic test OK" 46 | @$(LUA) nsievebits.lua && echo "nsievebits test OK" 47 | @$(LUA) md5test.lua && echo "MD5 test OK" 48 | 49 | clean: 50 | $(RM) *.o *.so *.obj *.lib *.exp *.dll *.manifest 51 | 52 | .PHONY: all macosx install test clean 53 | 54 | -------------------------------------------------------------------------------- /Makefile.mingw: -------------------------------------------------------------------------------- 1 | # Makefile for Lua BitOp -- a bit operations library for Lua 5.1/5.2. 2 | # This is a modified Makefile for MinGW. C:\MinGW\bin must be in your PATH. 3 | # Compile: mingw32-make -f Makefile.mingw 4 | # Install: mingw32-make -f Makefile.mingw install 5 | 6 | # Lua executable name. Used for testing. 7 | LUA= lua 8 | 9 | # Include path where lua.h, luaconf.h and lauxlib.h reside: 10 | INCLUDES= "-I.." 11 | 12 | # Path of lua51.dll: 13 | LUADLLPATH= "..\lua51.dll" 14 | 15 | # Path where C modules for Lua should be installed: 16 | LUACMODPATH= ".." 17 | 18 | CC= gcc 19 | CCOPT= -O2 -fomit-frame-pointer 20 | CCWARN = -Wall 21 | SOCC= $(CC) -shared 22 | SOCFLAGS= $(CCOPT) $(CCWARN) $(INCLUDES) $(CFLAGS) 23 | SOLDFLAGS= $(LDFLAGS) 24 | RM= del 25 | STRIP= strip --strip-unneeded 26 | INSTALL= copy 27 | 28 | MODNAME= bit 29 | MODSO= $(MODNAME).dll 30 | 31 | all: $(MODSO) 32 | 33 | $(MODNAME).o: $(MODNAME).c 34 | $(CC) $(SOCFLAGS) -c -o $@ $< 35 | 36 | $(MODSO): $(MODNAME).o 37 | $(SOCC) $(SOLDFLAGS) -o $@ $< $(LUADLLPATH) 38 | $(STRIP) $@ 39 | 40 | install: $(MODSO) 41 | $(INSTALL) $< $(LUACMODPATH) 42 | 43 | test: $(MODSO) 44 | @$(LUA) bittest.lua && echo "basic test OK" 45 | @$(LUA) nsievebits.lua && echo "nsievebits test OK" 46 | @$(LUA) md5test.lua && echo "MD5 test OK" 47 | 48 | clean: 49 | $(RM) *.o *.so *.obj *.lib *.exp *.dll *.manifest 50 | 51 | .PHONY: all install test clean 52 | 53 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | README for Lua BitOp 1.0.2 2 | -------------------------- 3 | 4 | Lua BitOp is a C extension module for Lua 5.1/5.2 which adds 5 | bitwise operations on numbers. 6 | 7 | Homepage: http://bitop.luajit.org/ 8 | 9 | Lua BitOp is Copyright (C) 2008-2012 Mike Pall. 10 | Lua BitOp is free software, released under the MIT license. 11 | 12 | -------------------------- 13 | 14 | Full documentation for Lua BitOp is available in HTML format. 15 | Please point your favourite browser to: 16 | 17 | doc/index.html 18 | 19 | Detailed installation instructions are here: 20 | 21 | doc/install.html 22 | 23 | -------------------------------------------------------------------------------- /bit.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Lua BitOp -- a bit operations library for Lua 5.1/5.2. 3 | ** http://bitop.luajit.org/ 4 | ** 5 | ** Copyright (C) 2008-2012 Mike Pall. All rights reserved. 6 | ** 7 | ** Permission is hereby granted, free of charge, to any person obtaining 8 | ** a copy of this software and associated documentation files (the 9 | ** "Software"), to deal in the Software without restriction, including 10 | ** without limitation the rights to use, copy, modify, merge, publish, 11 | ** distribute, sublicense, and/or sell copies of the Software, and to 12 | ** permit persons to whom the Software is furnished to do so, subject to 13 | ** the following conditions: 14 | ** 15 | ** The above copyright notice and this permission notice shall be 16 | ** included in all copies or substantial portions of the Software. 17 | ** 18 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | ** 26 | ** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] 27 | */ 28 | 29 | #define LUA_BITOP_VERSION "1.0.2" 30 | 31 | #define LUA_LIB 32 | #include "lua.h" 33 | #include "lauxlib.h" 34 | 35 | #ifdef _MSC_VER 36 | /* MSVC is stuck in the last century and doesn't have C99's stdint.h. */ 37 | typedef __int32 int32_t; 38 | typedef unsigned __int32 uint32_t; 39 | typedef unsigned __int64 uint64_t; 40 | #else 41 | #include 42 | #endif 43 | 44 | typedef int32_t SBits; 45 | typedef uint32_t UBits; 46 | 47 | typedef union { 48 | lua_Number n; 49 | #ifdef LUA_NUMBER_DOUBLE 50 | uint64_t b; 51 | #else 52 | UBits b; 53 | #endif 54 | } BitNum; 55 | 56 | /* Convert argument to bit type. */ 57 | static UBits barg(lua_State *L, int idx) 58 | { 59 | BitNum bn; 60 | UBits b; 61 | #if LUA_VERSION_NUM < 502 62 | bn.n = lua_tonumber(L, idx); 63 | #else 64 | bn.n = luaL_checknumber(L, idx); 65 | #endif 66 | #if defined(LUA_NUMBER_DOUBLE) 67 | bn.n += 6755399441055744.0; /* 2^52+2^51 */ 68 | #ifdef SWAPPED_DOUBLE 69 | b = (UBits)(bn.b >> 32); 70 | #else 71 | b = (UBits)bn.b; 72 | #endif 73 | #elif defined(LUA_NUMBER_INT) || defined(LUA_NUMBER_LONG) || \ 74 | defined(LUA_NUMBER_LONGLONG) || defined(LUA_NUMBER_LONG_LONG) || \ 75 | defined(LUA_NUMBER_LLONG) 76 | if (sizeof(UBits) == sizeof(lua_Number)) 77 | b = bn.b; 78 | else 79 | b = (UBits)(SBits)bn.n; 80 | #elif defined(LUA_NUMBER_FLOAT) 81 | #error "A 'float' lua_Number type is incompatible with this library" 82 | #else 83 | #error "Unknown number type, check LUA_NUMBER_* in luaconf.h" 84 | #endif 85 | #if LUA_VERSION_NUM < 502 86 | if (b == 0 && !lua_isnumber(L, idx)) { 87 | luaL_typerror(L, idx, "number"); 88 | } 89 | #endif 90 | return b; 91 | } 92 | 93 | /* Return bit type. */ 94 | #define BRET(b) lua_pushnumber(L, (lua_Number)(SBits)(b)); return 1; 95 | 96 | static int bit_tobit(lua_State *L) { BRET(barg(L, 1)) } 97 | static int bit_bnot(lua_State *L) { BRET(~barg(L, 1)) } 98 | 99 | #define BIT_OP(func, opr) \ 100 | static int func(lua_State *L) { int i; UBits b = barg(L, 1); \ 101 | for (i = lua_gettop(L); i > 1; i--) b opr barg(L, i); BRET(b) } 102 | BIT_OP(bit_band, &=) 103 | BIT_OP(bit_bor, |=) 104 | BIT_OP(bit_bxor, ^=) 105 | 106 | #define bshl(b, n) (b << n) 107 | #define bshr(b, n) (b >> n) 108 | #define bsar(b, n) ((SBits)b >> n) 109 | #define brol(b, n) ((b << n) | (b >> (32-n))) 110 | #define bror(b, n) ((b << (32-n)) | (b >> n)) 111 | #define BIT_SH(func, fn) \ 112 | static int func(lua_State *L) { \ 113 | UBits b = barg(L, 1); UBits n = barg(L, 2) & 31; BRET(fn(b, n)) } 114 | BIT_SH(bit_lshift, bshl) 115 | BIT_SH(bit_rshift, bshr) 116 | BIT_SH(bit_arshift, bsar) 117 | BIT_SH(bit_rol, brol) 118 | BIT_SH(bit_ror, bror) 119 | 120 | static int bit_bswap(lua_State *L) 121 | { 122 | UBits b = barg(L, 1); 123 | b = (b >> 24) | ((b >> 8) & 0xff00) | ((b & 0xff00) << 8) | (b << 24); 124 | BRET(b) 125 | } 126 | 127 | static int bit_tohex(lua_State *L) 128 | { 129 | UBits b = barg(L, 1); 130 | SBits n = lua_isnone(L, 2) ? 8 : (SBits)barg(L, 2); 131 | const char *hexdigits = "0123456789abcdef"; 132 | char buf[8]; 133 | int i; 134 | if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; } 135 | if (n > 8) n = 8; 136 | for (i = (int)n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; } 137 | lua_pushlstring(L, buf, (size_t)n); 138 | return 1; 139 | } 140 | 141 | static const struct luaL_Reg bit_funcs[] = { 142 | { "tobit", bit_tobit }, 143 | { "bnot", bit_bnot }, 144 | { "band", bit_band }, 145 | { "bor", bit_bor }, 146 | { "bxor", bit_bxor }, 147 | { "lshift", bit_lshift }, 148 | { "rshift", bit_rshift }, 149 | { "arshift", bit_arshift }, 150 | { "rol", bit_rol }, 151 | { "ror", bit_ror }, 152 | { "bswap", bit_bswap }, 153 | { "tohex", bit_tohex }, 154 | { NULL, NULL } 155 | }; 156 | 157 | /* Signed right-shifts are implementation-defined per C89/C99. 158 | ** But the de facto standard are arithmetic right-shifts on two's 159 | ** complement CPUs. This behaviour is required here, so test for it. 160 | */ 161 | #define BAD_SAR (bsar(-8, 2) != (SBits)-2) 162 | 163 | LUALIB_API int luaopen_bit(lua_State *L) 164 | { 165 | UBits b; 166 | lua_pushnumber(L, (lua_Number)1437217655L); 167 | b = barg(L, -1); 168 | if (b != (UBits)1437217655L || BAD_SAR) { /* Perform a simple self-test. */ 169 | const char *msg = "compiled with incompatible luaconf.h"; 170 | #ifdef LUA_NUMBER_DOUBLE 171 | #ifdef _WIN32 172 | if (b == (UBits)1610612736L) 173 | msg = "use D3DCREATE_FPU_PRESERVE with DirectX"; 174 | #endif 175 | if (b == (UBits)1127743488L) 176 | msg = "not compiled with SWAPPED_DOUBLE"; 177 | #endif 178 | if (BAD_SAR) 179 | msg = "arithmetic right-shift broken"; 180 | luaL_error(L, "bit library self-test failed (%s)", msg); 181 | } 182 | #if LUA_VERSION_NUM < 502 183 | luaL_register(L, "bit", bit_funcs); 184 | #else 185 | luaL_newlib(L, bit_funcs); 186 | #endif 187 | return 1; 188 | } 189 | 190 | -------------------------------------------------------------------------------- /bit.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | luaopen_bit 3 | -------------------------------------------------------------------------------- /bitbench.lua: -------------------------------------------------------------------------------- 1 | -- Microbenchmark for bit operations library. Public domain. 2 | 3 | local bit = require"bit" 4 | 5 | if not bit.rol then -- Replacement function if rotates are missing. 6 | local bor, shl, shr = bit.bor, bit.lshift, bit.rshift 7 | function bit.rol(a, b) return bor(shl(a, b), shr(a, 32-b)) end 8 | end 9 | 10 | if not bit.bswap then -- Replacement function if bswap is missing. 11 | local bor, band, shl, shr = bit.bor, bit.band, bit.lshift, bit.rshift 12 | function bit.bswap(a) 13 | return bor(shr(a, 24), band(shr(a, 8), 0xff00), 14 | shl(band(a, 0xff00), 8), shl(a, 24)); 15 | end 16 | end 17 | 18 | local base = 0 19 | 20 | local function bench(name, t) 21 | local n = 2000000 22 | repeat 23 | local tm = os.clock() 24 | t(n) 25 | tm = os.clock() - tm 26 | if tm > 1 then 27 | local ns = tm*1000/(n/1000000) 28 | io.write(string.format("%-15s %6.1f ns\n", name, ns-base)) 29 | return ns 30 | end 31 | n = n + n 32 | until false 33 | end 34 | 35 | -- The overhead for the base loop is subtracted from the other measurements. 36 | base = bench("loop baseline", function(n) 37 | local x = 0; for i=1,n do x = x + i end 38 | end) 39 | 40 | bench("tobit", function(n) 41 | local f = bit.tobit or bit.cast 42 | local x = 0; for i=1,n do x = x + f(i) end 43 | end) 44 | 45 | bench("bnot", function(n) 46 | local f = bit.bnot 47 | local x = 0; for i=1,n do x = x + f(i) end 48 | end) 49 | 50 | bench("bor/band/bxor", function(n) 51 | local f = bit.bor 52 | local x = 0; for i=1,n do x = x + f(i, 1) end 53 | end) 54 | 55 | bench("shifts", function(n) 56 | local f = bit.lshift 57 | local x = 0; for i=1,n do x = x + f(i, 1) end 58 | end) 59 | 60 | bench("rotates", function(n) 61 | local f = bit.rol 62 | local x = 0; for i=1,n do x = x + f(i, 1) end 63 | end) 64 | 65 | bench("bswap", function(n) 66 | local f = bit.bswap 67 | local x = 0; for i=1,n do x = x + f(i) end 68 | end) 69 | 70 | -------------------------------------------------------------------------------- /bittest.lua: -------------------------------------------------------------------------------- 1 | -- Test cases for bit operations library. Public domain. 2 | 3 | local bit = require"bit" 4 | 5 | local vb = { 6 | 0, 1, -1, 2, -2, 0x12345678, 0x87654321, 7 | 0x33333333, 0x77777777, 0x55aa55aa, 0xaa55aa55, 8 | 0x7fffffff, 0x80000000, 0xffffffff 9 | } 10 | 11 | local function cksum(name, s, r) 12 | local z = 0 13 | for i=1,#s do z = (z + string.byte(s, i)*i) % 2147483629 end 14 | if z ~= r then 15 | error("bit."..name.." test failed (got "..z..", expected "..r..")", 0) 16 | end 17 | end 18 | 19 | local function check_unop(name, r) 20 | local f = bit[name] 21 | local s = "" 22 | if pcall(f) or pcall(f, "z") or pcall(f, true) then 23 | error("bit."..name.." fails to detect argument errors", 0) 24 | end 25 | for _,x in ipairs(vb) do s = s..","..tostring(f(x)) end 26 | cksum(name, s, r) 27 | end 28 | 29 | local function check_binop(name, r) 30 | local f = bit[name] 31 | local s = "" 32 | if pcall(f) or pcall(f, "z") or pcall(f, true) then 33 | error("bit."..name.." fails to detect argument errors", 0) 34 | end 35 | for _,x in ipairs(vb) do 36 | for _,y in ipairs(vb) do s = s..","..tostring(f(x, y)) end 37 | end 38 | cksum(name, s, r) 39 | end 40 | 41 | local function check_binop_range(name, r, yb, ye) 42 | local f = bit[name] 43 | local s = "" 44 | if pcall(f) or pcall(f, "z") or pcall(f, true) or pcall(f, 1, true) then 45 | error("bit."..name.." fails to detect argument errors", 0) 46 | end 47 | for _,x in ipairs(vb) do 48 | for y=yb,ye do s = s..","..tostring(f(x, y)) end 49 | end 50 | cksum(name, s, r) 51 | end 52 | 53 | local function check_shift(name, r) 54 | check_binop_range(name, r, 0, 31) 55 | end 56 | 57 | -- Minimal sanity checks. 58 | assert(0x7fffffff == 2147483647, "broken hex literals") 59 | assert(0xffffffff == -1 or 0xffffffff == 2^32-1, "broken hex literals") 60 | assert(tostring(-1) == "-1", "broken tostring()") 61 | assert(tostring(0xffffffff) == "-1" or tostring(0xffffffff) == "4294967295", "broken tostring()") 62 | 63 | -- Basic argument processing. 64 | assert(bit.tobit(1) == 1) 65 | assert(bit.band(1) == 1) 66 | assert(bit.bxor(1,2) == 3) 67 | assert(bit.bor(1,2,4,8,16,32,64,128) == 255) 68 | 69 | -- Apply operations to test vectors and compare checksums. 70 | check_unop("tobit", 277312) 71 | check_unop("bnot", 287870) 72 | check_unop("bswap", 307611) 73 | 74 | check_binop("band", 41206764) 75 | check_binop("bor", 51253663) 76 | check_binop("bxor", 79322427) 77 | 78 | check_shift("lshift", 325260344) 79 | check_shift("rshift", 139061800) 80 | check_shift("arshift", 111364720) 81 | check_shift("rol", 302401155) 82 | check_shift("ror", 302316761) 83 | 84 | check_binop_range("tohex", 47880306, -8, 8) 85 | 86 | -------------------------------------------------------------------------------- /cmake/FindLua.cmake: -------------------------------------------------------------------------------- 1 | # Locate Lua library 2 | # This module defines 3 | # LUA_EXECUTABLE, if found 4 | # LUA_FOUND, if false, do not try to link to Lua 5 | # LUA_LIBRARIES 6 | # LUA_INCLUDE_DIR, where to find lua.h 7 | # LUA_VERSION_STRING, the version of Lua found (since CMake 2.8.8) 8 | # 9 | # Note that the expected include convention is 10 | # #include "lua.h" 11 | # and not 12 | # #include 13 | # This is because, the lua location is not standardized and may exist 14 | # in locations other than lua/ 15 | 16 | #============================================================================= 17 | # Copyright 2007-2009 Kitware, Inc. 18 | # Modified to support Lua 5.2 by LuaDist 2012 19 | # 20 | # Distributed under the OSI-approved BSD License (the "License"); 21 | # see accompanying file Copyright.txt for details. 22 | # 23 | # This software is distributed WITHOUT ANY WARRANTY; without even the 24 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 25 | # See the License for more information. 26 | #============================================================================= 27 | # (To distribute this file outside of CMake, substitute the full 28 | # License text for the above reference.) 29 | # 30 | # The required version of Lua can be specified using the 31 | # standard syntax, e.g. FIND_PACKAGE(Lua 5.1) 32 | # Otherwise the module will search for any available Lua implementation 33 | 34 | # Always search for non-versioned lua first (recommended) 35 | SET(_POSSIBLE_LUA_INCLUDE include include/lua) 36 | SET(_POSSIBLE_LUA_EXECUTABLE lua) 37 | SET(_POSSIBLE_LUA_LIBRARY lua) 38 | 39 | # Determine possible naming suffixes (there is no standard for this) 40 | IF(Lua_FIND_VERSION_MAJOR AND Lua_FIND_VERSION_MINOR) 41 | SET(_POSSIBLE_SUFFIXES "${Lua_FIND_VERSION_MAJOR}${Lua_FIND_VERSION_MINOR}" "${Lua_FIND_VERSION_MAJOR}.${Lua_FIND_VERSION_MINOR}" "-${Lua_FIND_VERSION_MAJOR}.${Lua_FIND_VERSION_MINOR}") 42 | ELSE(Lua_FIND_VERSION_MAJOR AND Lua_FIND_VERSION_MINOR) 43 | SET(_POSSIBLE_SUFFIXES "52" "5.2" "-5.2" "51" "5.1" "-5.1") 44 | ENDIF(Lua_FIND_VERSION_MAJOR AND Lua_FIND_VERSION_MINOR) 45 | 46 | # Set up possible search names and locations 47 | FOREACH(_SUFFIX ${_POSSIBLE_SUFFIXES}) 48 | LIST(APPEND _POSSIBLE_LUA_INCLUDE "include/lua${_SUFFIX}") 49 | LIST(APPEND _POSSIBLE_LUA_EXECUTABLE "lua${_SUFFIX}") 50 | LIST(APPEND _POSSIBLE_LUA_LIBRARY "lua${_SUFFIX}") 51 | ENDFOREACH(_SUFFIX) 52 | 53 | # Find the lua executable 54 | FIND_PROGRAM(LUA_EXECUTABLE 55 | NAMES ${_POSSIBLE_LUA_EXECUTABLE} 56 | ) 57 | 58 | # Find the lua header 59 | FIND_PATH(LUA_INCLUDE_DIR lua.h 60 | HINTS 61 | $ENV{LUA_DIR} 62 | PATH_SUFFIXES ${_POSSIBLE_LUA_INCLUDE} 63 | PATHS 64 | ~/Library/Frameworks 65 | /Library/Frameworks 66 | /usr/local 67 | /usr 68 | /sw # Fink 69 | /opt/local # DarwinPorts 70 | /opt/csw # Blastwave 71 | /opt 72 | ) 73 | 74 | # Find the lua library 75 | FIND_LIBRARY(LUA_LIBRARY 76 | NAMES ${_POSSIBLE_LUA_LIBRARY} 77 | HINTS 78 | $ENV{LUA_DIR} 79 | PATH_SUFFIXES lib64 lib 80 | PATHS 81 | ~/Library/Frameworks 82 | /Library/Frameworks 83 | /usr/local 84 | /usr 85 | /sw 86 | /opt/local 87 | /opt/csw 88 | /opt 89 | ) 90 | 91 | IF(LUA_LIBRARY) 92 | # include the math library for Unix 93 | IF(UNIX AND NOT APPLE) 94 | FIND_LIBRARY(LUA_MATH_LIBRARY m) 95 | SET( LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}" CACHE STRING "Lua Libraries") 96 | # For Windows and Mac, don't need to explicitly include the math library 97 | ELSE(UNIX AND NOT APPLE) 98 | SET( LUA_LIBRARIES "${LUA_LIBRARY}" CACHE STRING "Lua Libraries") 99 | ENDIF(UNIX AND NOT APPLE) 100 | ENDIF(LUA_LIBRARY) 101 | 102 | # Determine Lua version 103 | IF(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/lua.h") 104 | FILE(STRINGS "${LUA_INCLUDE_DIR}/lua.h" lua_version_str REGEX "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua .+\"") 105 | 106 | STRING(REGEX REPLACE "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([^\"]+)\".*" "\\1" LUA_VERSION_STRING "${lua_version_str}") 107 | UNSET(lua_version_str) 108 | ENDIF() 109 | 110 | INCLUDE(FindPackageHandleStandardArgs) 111 | # handle the QUIETLY and REQUIRED arguments and set LUA_FOUND to TRUE if 112 | # all listed variables are TRUE 113 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lua 114 | REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR 115 | VERSION_VAR LUA_VERSION_STRING) 116 | 117 | MARK_AS_ADVANCED(LUA_INCLUDE_DIR LUA_LIBRARIES LUA_LIBRARY LUA_MATH_LIBRARY LUA_EXECUTABLE) 118 | 119 | -------------------------------------------------------------------------------- /cmake/dist.cmake: -------------------------------------------------------------------------------- 1 | # LuaDist CMake utility library. 2 | # Provides sane project defaults and macros common to LuaDist CMake builds. 3 | # 4 | # Copyright (C) 2007-2012 LuaDist. 5 | # by David Manura, Peter Drahoš 6 | # Redistribution and use of this file is allowed according to the terms of the MIT license. 7 | # For details see the COPYRIGHT file distributed with LuaDist. 8 | # Please note that the package source code is licensed under its own license. 9 | 10 | ## Extract information from dist.info 11 | if ( NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/dist.info ) 12 | message ( FATAL_ERROR 13 | "Missing dist.info file (${CMAKE_CURRENT_SOURCE_DIR}/dist.info)." ) 14 | endif () 15 | file ( READ ${CMAKE_CURRENT_SOURCE_DIR}/dist.info DIST_INFO ) 16 | if ( "${DIST_INFO}" STREQUAL "" ) 17 | message ( FATAL_ERROR "Failed to load dist.info." ) 18 | endif () 19 | # Reads field `name` from dist.info string `DIST_INFO` into variable `var`. 20 | macro ( _parse_dist_field name var ) 21 | string ( REGEX REPLACE ".*${name}[ \t]?=[ \t]?[\"']([^\"']+)[\"'].*" "\\1" 22 | ${var} "${DIST_INFO}" ) 23 | if ( ${var} STREQUAL DIST_INFO ) 24 | message ( FATAL_ERROR "Failed to extract \"${var}\" from dist.info" ) 25 | endif () 26 | endmacro () 27 | # 28 | _parse_dist_field ( name DIST_NAME ) 29 | _parse_dist_field ( version DIST_VERSION ) 30 | _parse_dist_field ( license DIST_LICENSE ) 31 | _parse_dist_field ( author DIST_AUTHOR ) 32 | _parse_dist_field ( maintainer DIST_MAINTAINER ) 33 | _parse_dist_field ( url DIST_URL ) 34 | _parse_dist_field ( desc DIST_DESC ) 35 | message ( "DIST_NAME: ${DIST_NAME}") 36 | message ( "DIST_VERSION: ${DIST_VERSION}") 37 | message ( "DIST_LICENSE: ${DIST_LICENSE}") 38 | message ( "DIST_AUTHOR: ${DIST_AUTHOR}") 39 | message ( "DIST_MAINTAINER: ${DIST_MAINTAINER}") 40 | message ( "DIST_URL: ${DIST_URL}") 41 | message ( "DIST_DESC: ${DIST_DESC}") 42 | string ( REGEX REPLACE ".*depends[ \t]?=[ \t]?[\"']([^\"']+)[\"'].*" "\\1" 43 | DIST_DEPENDS ${DIST_INFO} ) 44 | if ( DIST_DEPENDS STREQUAL DIST_INFO ) 45 | set ( DIST_DEPENDS "" ) 46 | endif () 47 | message ( "DIST_DEPENDS: ${DIST_DEPENDS}") 48 | ## 2DO: Parse DIST_DEPENDS and try to install Dependencies with automatically using externalproject_add 49 | 50 | 51 | ## INSTALL DEFAULTS (Relative to CMAKE_INSTALL_PREFIX) 52 | # Primary paths 53 | set ( INSTALL_BIN bin CACHE PATH "Where to install binaries to." ) 54 | set ( INSTALL_LIB lib CACHE PATH "Where to install libraries to." ) 55 | set ( INSTALL_INC include CACHE PATH "Where to install headers to." ) 56 | set ( INSTALL_ETC etc CACHE PATH "Where to store configuration files" ) 57 | set ( INSTALL_SHARE share CACHE PATH "Directory for shared data." ) 58 | 59 | # Secondary paths 60 | option ( INSTALL_VERSION 61 | "Install runtime libraries and executables with version information." OFF) 62 | set ( INSTALL_DATA ${INSTALL_SHARE}/${DIST_NAME} CACHE PATH 63 | "Directory the package can store documentation, tests or other data in.") 64 | set ( INSTALL_DOC ${INSTALL_DATA}/doc CACHE PATH 65 | "Recommended directory to install documentation into.") 66 | set ( INSTALL_EXAMPLE ${INSTALL_DATA}/example CACHE PATH 67 | "Recommended directory to install examples into.") 68 | set ( INSTALL_TEST ${INSTALL_DATA}/test CACHE PATH 69 | "Recommended directory to install tests into.") 70 | set ( INSTALL_FOO ${INSTALL_DATA}/etc CACHE PATH 71 | "Where to install additional files") 72 | 73 | # Tweaks and other defaults 74 | # Setting CMAKE to use loose block and search for find modules in source directory 75 | set ( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true ) 76 | set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH} ) 77 | option ( BUILD_SHARED_LIBS "Build shared libraries" ON ) 78 | 79 | # In MSVC, prevent warnings that can occur when using standard libraries. 80 | if ( MSVC ) 81 | add_definitions ( -D_CRT_SECURE_NO_WARNINGS ) 82 | endif () 83 | 84 | # RPath and relative linking 85 | option ( USE_RPATH "Use relative linking." ON) 86 | if ( USE_RPATH ) 87 | string ( REGEX REPLACE "[^!/]+" ".." UP_DIR ${INSTALL_BIN} ) 88 | set ( CMAKE_SKIP_BUILD_RPATH FALSE CACHE STRING "" FORCE ) 89 | set ( CMAKE_BUILD_WITH_INSTALL_RPATH FALSE CACHE STRING "" FORCE ) 90 | set ( CMAKE_INSTALL_RPATH $ORIGIN/${UP_DIR}/${INSTALL_LIB} 91 | CACHE STRING "" FORCE ) 92 | set ( CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE CACHE STRING "" FORCE ) 93 | set ( CMAKE_INSTALL_NAME_DIR @executable_path/${UP_DIR}/${INSTALL_LIB} 94 | CACHE STRING "" FORCE ) 95 | endif () 96 | 97 | ## MACROS 98 | # Parser macro 99 | macro ( parse_arguments prefix arg_names option_names) 100 | set ( DEFAULT_ARGS ) 101 | foreach ( arg_name ${arg_names} ) 102 | set ( ${prefix}_${arg_name} ) 103 | endforeach () 104 | foreach ( option ${option_names} ) 105 | set ( ${prefix}_${option} FALSE ) 106 | endforeach () 107 | 108 | set ( current_arg_name DEFAULT_ARGS ) 109 | set ( current_arg_list ) 110 | foreach ( arg ${ARGN} ) 111 | set ( larg_names ${arg_names} ) 112 | list ( FIND larg_names "${arg}" is_arg_name ) 113 | if ( is_arg_name GREATER -1 ) 114 | set ( ${prefix}_${current_arg_name} ${current_arg_list} ) 115 | set ( current_arg_name ${arg} ) 116 | set ( current_arg_list ) 117 | else () 118 | set ( loption_names ${option_names} ) 119 | list ( FIND loption_names "${arg}" is_option ) 120 | if ( is_option GREATER -1 ) 121 | set ( ${prefix}_${arg} TRUE ) 122 | else () 123 | set ( current_arg_list ${current_arg_list} ${arg} ) 124 | endif () 125 | endif () 126 | endforeach () 127 | set ( ${prefix}_${current_arg_name} ${current_arg_list} ) 128 | endmacro () 129 | 130 | 131 | # install_executable ( executable_targets ) 132 | # Installs any executables generated using "add_executable". 133 | # USE: install_executable ( lua ) 134 | # NOTE: subdirectories are NOT supported 135 | set ( CPACK_COMPONENT_RUNTIME_DISPLAY_NAME "${DIST_NAME} Runtime" ) 136 | set ( CPACK_COMPONENT_RUNTIME_DESCRIPTION 137 | "Executables and runtime libraries. Installed into ${INSTALL_BIN}." ) 138 | macro ( install_executable ) 139 | foreach ( _file ${ARGN} ) 140 | if ( INSTALL_VERSION ) 141 | set_target_properties ( ${_file} PROPERTIES VERSION ${DIST_VERSION} 142 | SOVERSION ${DIST_VERSION} ) 143 | endif () 144 | install ( TARGETS ${_file} RUNTIME DESTINATION ${INSTALL_BIN} 145 | COMPONENT Runtime ) 146 | endforeach() 147 | endmacro () 148 | 149 | # install_library ( library_targets ) 150 | # Installs any libraries generated using "add_library" into apropriate places. 151 | # USE: install_library ( libexpat ) 152 | # NOTE: subdirectories are NOT supported 153 | set ( CPACK_COMPONENT_LIBRARY_DISPLAY_NAME "${DIST_NAME} Development Libraries" ) 154 | set ( CPACK_COMPONENT_LIBRARY_DESCRIPTION 155 | "Static and import libraries needed for development. Installed into ${INSTALL_LIB} or ${INSTALL_BIN}." ) 156 | macro ( install_library ) 157 | foreach ( _file ${ARGN} ) 158 | if ( INSTALL_VERSION ) 159 | set_target_properties ( ${_file} PROPERTIES VERSION ${DIST_VERSION} 160 | SOVERSION ${DIST_VERSION} ) 161 | endif () 162 | install ( TARGETS ${_file} 163 | RUNTIME DESTINATION ${INSTALL_BIN} COMPONENT Runtime 164 | LIBRARY DESTINATION ${INSTALL_LIB} COMPONENT Runtime 165 | ARCHIVE DESTINATION ${INSTALL_LIB} COMPONENT Library ) 166 | endforeach() 167 | endmacro () 168 | 169 | # helper function for various install_* functions, for PATTERN/REGEX args. 170 | macro ( _complete_install_args ) 171 | if ( NOT("${_ARG_PATTERN}" STREQUAL "") ) 172 | set ( _ARG_PATTERN PATTERN ${_ARG_PATTERN} ) 173 | endif () 174 | if ( NOT("${_ARG_REGEX}" STREQUAL "") ) 175 | set ( _ARG_REGEX REGEX ${_ARG_REGEX} ) 176 | endif () 177 | endmacro () 178 | 179 | # install_header ( files/directories [INTO destination] ) 180 | # Install a directories or files into header destination. 181 | # USE: install_header ( lua.h luaconf.h ) or install_header ( GL ) 182 | # USE: install_header ( mylib.h INTO mylib ) 183 | # For directories, supports optional PATTERN/REGEX arguments like install(). 184 | set ( CPACK_COMPONENT_HEADER_DISPLAY_NAME "${DIST_NAME} Development Headers" ) 185 | set ( CPACK_COMPONENT_HEADER_DESCRIPTION 186 | "Headers needed for development. Installed into ${INSTALL_INC}." ) 187 | macro ( install_header ) 188 | parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} ) 189 | _complete_install_args() 190 | foreach ( _file ${_ARG_DEFAULT_ARGS} ) 191 | if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" ) 192 | install ( DIRECTORY ${_file} DESTINATION ${INSTALL_INC}/${_ARG_INTO} 193 | COMPONENT Header ${_ARG_PATTERN} ${_ARG_REGEX} ) 194 | else () 195 | install ( FILES ${_file} DESTINATION ${INSTALL_INC}/${_ARG_INTO} 196 | COMPONENT Header ) 197 | endif () 198 | endforeach() 199 | endmacro () 200 | 201 | # install_data ( files/directories [INTO destination] ) 202 | # This installs additional data files or directories. 203 | # USE: install_data ( extra data.dat ) 204 | # USE: install_data ( image1.png image2.png INTO images ) 205 | # For directories, supports optional PATTERN/REGEX arguments like install(). 206 | set ( CPACK_COMPONENT_DATA_DISPLAY_NAME "${DIST_NAME} Data" ) 207 | set ( CPACK_COMPONENT_DATA_DESCRIPTION 208 | "Application data. Installed into ${INSTALL_DATA}." ) 209 | macro ( install_data ) 210 | parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} ) 211 | _complete_install_args() 212 | foreach ( _file ${_ARG_DEFAULT_ARGS} ) 213 | if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" ) 214 | install ( DIRECTORY ${_file} 215 | DESTINATION ${INSTALL_DATA}/${_ARG_INTO} 216 | COMPONENT Data ${_ARG_PATTERN} ${_ARG_REGEX} ) 217 | else () 218 | install ( FILES ${_file} DESTINATION ${INSTALL_DATA}/${_ARG_INTO} 219 | COMPONENT Data ) 220 | endif () 221 | endforeach() 222 | endmacro () 223 | 224 | # INSTALL_DOC ( files/directories [INTO destination] ) 225 | # This installs documentation content 226 | # USE: install_doc ( doc/ doc.pdf ) 227 | # USE: install_doc ( index.html INTO html ) 228 | # For directories, supports optional PATTERN/REGEX arguments like install(). 229 | set ( CPACK_COMPONENT_DOCUMENTATION_DISPLAY_NAME "${DIST_NAME} Documentation" ) 230 | set ( CPACK_COMPONENT_DOCUMENTATION_DESCRIPTION 231 | "Application documentation. Installed into ${INSTALL_DOC}." ) 232 | macro ( install_doc ) 233 | parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} ) 234 | _complete_install_args() 235 | foreach ( _file ${_ARG_DEFAULT_ARGS} ) 236 | if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" ) 237 | install ( DIRECTORY ${_file} DESTINATION ${INSTALL_DOC}/${_ARG_INTO} 238 | COMPONENT Documentation ${_ARG_PATTERN} ${_ARG_REGEX} ) 239 | else () 240 | install ( FILES ${_file} DESTINATION ${INSTALL_DOC}/${_ARG_INTO} 241 | COMPONENT Documentation ) 242 | endif () 243 | endforeach() 244 | endmacro () 245 | 246 | # install_example ( files/directories [INTO destination] ) 247 | # This installs additional examples 248 | # USE: install_example ( examples/ exampleA ) 249 | # USE: install_example ( super_example super_data INTO super) 250 | # For directories, supports optional PATTERN/REGEX argument like install(). 251 | set ( CPACK_COMPONENT_EXAMPLE_DISPLAY_NAME "${DIST_NAME} Examples" ) 252 | set ( CPACK_COMPONENT_EXAMPLE_DESCRIPTION 253 | "Examples and their associated data. Installed into ${INSTALL_EXAMPLE}." ) 254 | macro ( install_example ) 255 | parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} ) 256 | _complete_install_args() 257 | foreach ( _file ${_ARG_DEFAULT_ARGS} ) 258 | if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" ) 259 | install ( DIRECTORY ${_file} DESTINATION ${INSTALL_EXAMPLE}/${_ARG_INTO} 260 | COMPONENT Example ${_ARG_PATTERN} ${_ARG_REGEX} ) 261 | else () 262 | install ( FILES ${_file} DESTINATION ${INSTALL_EXAMPLE}/${_ARG_INTO} 263 | COMPONENT Example ) 264 | endif () 265 | endforeach() 266 | endmacro () 267 | 268 | # install_test ( files/directories [INTO destination] ) 269 | # This installs tests and test files, DOES NOT EXECUTE TESTS 270 | # USE: install_test ( my_test data.sql ) 271 | # USE: install_test ( feature_x_test INTO x ) 272 | # For directories, supports optional PATTERN/REGEX argument like install(). 273 | set ( CPACK_COMPONENT_TEST_DISPLAY_NAME "${DIST_NAME} Tests" ) 274 | set ( CPACK_COMPONENT_TEST_DESCRIPTION 275 | "Tests and associated data. Installed into ${INSTALL_TEST}." ) 276 | macro ( install_test ) 277 | parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} ) 278 | _complete_install_args() 279 | foreach ( _file ${_ARG_DEFAULT_ARGS} ) 280 | if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" ) 281 | install ( DIRECTORY ${_file} DESTINATION ${INSTALL_TEST}/${_ARG_INTO} 282 | COMPONENT Test ${_ARG_PATTERN} ${_ARG_REGEX} ) 283 | else () 284 | install ( FILES ${_file} DESTINATION ${INSTALL_TEST}/${_ARG_INTO} 285 | COMPONENT Test ) 286 | endif () 287 | endforeach() 288 | endmacro () 289 | 290 | # install_foo ( files/directories [INTO destination] ) 291 | # This installs optional or otherwise unneeded content 292 | # USE: install_foo ( etc/ example.doc ) 293 | # USE: install_foo ( icon.png logo.png INTO icons) 294 | # For directories, supports optional PATTERN/REGEX argument like install(). 295 | set ( CPACK_COMPONENT_OTHER_DISPLAY_NAME "${DIST_NAME} Unspecified Content" ) 296 | set ( CPACK_COMPONENT_OTHER_DESCRIPTION 297 | "Other unspecified content. Installed into ${INSTALL_FOO}." ) 298 | macro ( install_foo ) 299 | parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} ) 300 | _complete_install_args() 301 | foreach ( _file ${_ARG_DEFAULT_ARGS} ) 302 | if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" ) 303 | install ( DIRECTORY ${_file} DESTINATION ${INSTALL_FOO}/${_ARG_INTO} 304 | COMPONENT Other ${_ARG_PATTERN} ${_ARG_REGEX} ) 305 | else () 306 | install ( FILES ${_file} DESTINATION ${INSTALL_FOO}/${_ARG_INTO} 307 | COMPONENT Other ) 308 | endif () 309 | endforeach() 310 | endmacro () 311 | 312 | ## CTest defaults 313 | 314 | ## CPack defaults 315 | set ( CPACK_GENERATOR "ZIP" ) 316 | set ( CPACK_STRIP_FILES TRUE ) 317 | set ( CPACK_PACKAGE_NAME "${DIST_NAME}" ) 318 | set ( CPACK_PACKAGE_VERSION "${DIST_VERSION}") 319 | set ( CPACK_PACKAGE_VENDOR "LuaDist" ) 320 | set ( CPACK_COMPONENTS_ALL Runtime Library Header Data Documentation Example Other ) 321 | include ( CPack ) 322 | -------------------------------------------------------------------------------- /cmake/lua.cmake: -------------------------------------------------------------------------------- 1 | # LuaDist CMake utility library for Lua. 2 | # 3 | # Copyright (C) 2007-2012 LuaDist. 4 | # by David Manura, Peter Drahos 5 | # Redistribution and use of this file is allowed according to the terms of the MIT license. 6 | # For details see the COPYRIGHT file distributed with LuaDist. 7 | # Please note that the package source code is licensed under its own license. 8 | 9 | set ( INSTALL_LMOD ${INSTALL_LIB}/lua 10 | CACHE PATH "Directory to install Lua modules." ) 11 | set ( INSTALL_CMOD ${INSTALL_LIB}/lua 12 | CACHE PATH "Directory to install Lua binary modules." ) 13 | 14 | option ( SKIP_LUA_WRAPPER 15 | "Do not build and install Lua executable wrappers." OFF) 16 | 17 | # List of (Lua module name, file path) pairs. 18 | # Used internally by add_lua_test. Built by add_lua_module. 19 | set ( _lua_modules ) 20 | 21 | # utility function: appends path `path` to path `basepath`, properly 22 | # handling cases when `path` may be relative or absolute. 23 | macro ( _append_path basepath path result ) 24 | if ( IS_ABSOLUTE "${path}" ) 25 | set ( ${result} "${path}" ) 26 | else () 27 | set ( ${result} "${basepath}/${path}" ) 28 | endif () 29 | endmacro () 30 | 31 | # install_lua_executable ( target source ) 32 | # Automatically generate a binary if srlua package is available 33 | # The application or its source will be placed into /bin 34 | # If the application source did not have .lua suffix then it will be added 35 | # USE: lua_executable ( sputnik src/sputnik.lua ) 36 | macro ( install_lua_executable _name _source ) 37 | get_filename_component ( _source_name ${_source} NAME_WE ) 38 | # Find srlua and glue 39 | find_program( SRLUA_EXECUTABLE NAMES srlua ) 40 | find_program( GLUE_EXECUTABLE NAMES glue ) 41 | # Executable output 42 | set ( _exe ${CMAKE_CURRENT_BINARY_DIR}/${_name}${CMAKE_EXECUTABLE_SUFFIX} ) 43 | if ( NOT SKIP_LUA_WRAPPER AND SRLUA_EXECUTABLE AND GLUE_EXECUTABLE ) 44 | # Generate binary gluing the lua code to srlua, this is a robuust approach for most systems 45 | add_custom_command( 46 | OUTPUT ${_exe} 47 | COMMAND ${GLUE_EXECUTABLE} 48 | ARGS ${SRLUA_EXECUTABLE} ${_source} ${_exe} 49 | DEPENDS ${_source} 50 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 51 | VERBATIM 52 | ) 53 | # Make sure we have a target associated with the binary 54 | add_custom_target(${_name} ALL 55 | DEPENDS ${_exe} 56 | ) 57 | # Install with run permissions 58 | install ( PROGRAMS ${_exe} DESTINATION ${INSTALL_BIN} COMPONENT Runtime) 59 | # Also install source as optional resurce 60 | install ( FILES ${_source} DESTINATION ${INSTALL_FOO} COMPONENT Other ) 61 | else() 62 | # Install into bin as is but without the lua suffix, we assume the executable uses UNIX shebang/hash-bang magic 63 | install ( PROGRAMS ${_source} DESTINATION ${INSTALL_BIN} 64 | RENAME ${_source_name} 65 | COMPONENT Runtime 66 | ) 67 | endif() 68 | endmacro () 69 | 70 | macro ( _lua_module_helper is_install _name ) 71 | parse_arguments ( _MODULE "LINK;ALL_IN_ONE" "" ${ARGN} ) 72 | # _target is CMake-compatible target name for module (e.g. socket_core). 73 | # _module is relative path of target (e.g. socket/core), 74 | # without extension (e.g. .lua/.so/.dll). 75 | # _MODULE_SRC is list of module source files (e.g. .lua and .c files). 76 | # _MODULE_NAMES is list of module names (e.g. socket.core). 77 | if ( _MODULE_ALL_IN_ONE ) 78 | string ( REGEX REPLACE "\\..*" "" _target "${_name}" ) 79 | string ( REGEX REPLACE "\\..*" "" _module "${_name}" ) 80 | set ( _target "${_target}_all_in_one") 81 | set ( _MODULE_SRC ${_MODULE_ALL_IN_ONE} ) 82 | set ( _MODULE_NAMES ${_name} ${_MODULE_DEFAULT_ARGS} ) 83 | else () 84 | string ( REPLACE "." "_" _target "${_name}" ) 85 | string ( REPLACE "." "/" _module "${_name}" ) 86 | set ( _MODULE_SRC ${_MODULE_DEFAULT_ARGS} ) 87 | set ( _MODULE_NAMES ${_name} ) 88 | endif () 89 | if ( NOT _MODULE_SRC ) 90 | message ( FATAL_ERROR "no module sources specified" ) 91 | endif () 92 | list ( GET _MODULE_SRC 0 _first_source ) 93 | 94 | get_filename_component ( _ext ${_first_source} EXT ) 95 | if ( _ext STREQUAL ".lua" ) # Lua source module 96 | list ( LENGTH _MODULE_SRC _len ) 97 | if ( _len GREATER 1 ) 98 | message ( FATAL_ERROR "more than one source file specified" ) 99 | endif () 100 | 101 | set ( _module "${_module}.lua" ) 102 | 103 | get_filename_component ( _module_dir ${_module} PATH ) 104 | get_filename_component ( _module_filename ${_module} NAME ) 105 | _append_path ( "${CMAKE_CURRENT_SOURCE_DIR}" "${_first_source}" _module_path ) 106 | list ( APPEND _lua_modules "${_name}" "${_module_path}" ) 107 | 108 | if ( ${is_install} ) 109 | install ( FILES ${_first_source} DESTINATION ${INSTALL_LMOD}/${_module_dir} 110 | RENAME ${_module_filename} 111 | COMPONENT Runtime 112 | ) 113 | endif () 114 | else () # Lua C binary module 115 | enable_language ( C ) 116 | find_package ( Lua REQUIRED ) 117 | include_directories ( ${LUA_INCLUDE_DIR} ) 118 | 119 | set ( _module "${_module}${CMAKE_SHARED_MODULE_SUFFIX}" ) 120 | 121 | get_filename_component ( _module_dir ${_module} PATH ) 122 | get_filename_component ( _module_filenamebase ${_module} NAME_WE ) 123 | foreach ( _thisname ${_MODULE_NAMES} ) 124 | list ( APPEND _lua_modules "${_thisname}" 125 | "${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_CFG_INTDIR}/${_module}" ) 126 | endforeach () 127 | 128 | add_library( ${_target} MODULE ${_MODULE_SRC}) 129 | target_link_libraries ( ${_target} ${LUA_LIBRARY} ${_MODULE_LINK} ) 130 | set_target_properties ( ${_target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY 131 | "${_module_dir}" PREFIX "" OUTPUT_NAME "${_module_filenamebase}" ) 132 | if ( ${is_install} ) 133 | install ( TARGETS ${_target} DESTINATION ${INSTALL_CMOD}/${_module_dir} COMPONENT Runtime) 134 | endif () 135 | endif () 136 | endmacro () 137 | 138 | # add_lua_module 139 | # Builds a Lua source module into a destination locatable by Lua 140 | # require syntax. 141 | # Binary modules are also supported where this function takes sources and 142 | # libraries to compile separated by LINK keyword. 143 | # USE: add_lua_module ( socket.http src/http.lua ) 144 | # USE2: add_lua_module ( mime.core src/mime.c ) 145 | # USE3: add_lua_module ( socket.core ${SRC_SOCKET} LINK ${LIB_SOCKET} ) 146 | # USE4: add_lua_module ( ssl.context ssl.core ALL_IN_ONE src/context.c src/ssl.c ) 147 | # This form builds an "all-in-one" module (e.g. ssl.so or ssl.dll containing 148 | # both modules ssl.context and ssl.core). The CMake target name will be 149 | # ssl_all_in_one. 150 | # Also sets variable _module_path (relative path where module typically 151 | # would be installed). 152 | macro ( add_lua_module ) 153 | _lua_module_helper ( 0 ${ARGN} ) 154 | endmacro () 155 | 156 | 157 | # install_lua_module 158 | # This is the same as `add_lua_module` but also installs the module. 159 | # USE: install_lua_module ( socket.http src/http.lua ) 160 | # USE2: install_lua_module ( mime.core src/mime.c ) 161 | # USE3: install_lua_module ( socket.core ${SRC_SOCKET} LINK ${LIB_SOCKET} ) 162 | macro ( install_lua_module ) 163 | _lua_module_helper ( 1 ${ARGN} ) 164 | endmacro () 165 | 166 | # Builds string representing Lua table mapping Lua modules names to file 167 | # paths. Used internally. 168 | macro ( _make_module_table _outvar ) 169 | set ( ${_outvar} ) 170 | list ( LENGTH _lua_modules _n ) 171 | if ( ${_n} GREATER 0 ) # avoids cmake complaint 172 | foreach ( _i RANGE 1 ${_n} 2 ) 173 | list ( GET _lua_modules ${_i} _path ) 174 | math ( EXPR _ii ${_i}-1 ) 175 | list ( GET _lua_modules ${_ii} _name ) 176 | set ( ${_outvar} "${_table} ['${_name}'] = '${_path}'\;\n") 177 | endforeach () 178 | endif () 179 | set ( ${_outvar} 180 | "local modules = { 181 | ${_table}}" ) 182 | endmacro () 183 | 184 | # add_lua_test ( _testfile [ WORKING_DIRECTORY _working_dir ] ) 185 | # Runs Lua script `_testfile` under CTest tester. 186 | # Optional named argument `WORKING_DIRECTORY` is current working directory to 187 | # run test under (defaults to ${CMAKE_CURRENT_BINARY_DIR}). 188 | # Both paths, if relative, are relative to ${CMAKE_CURRENT_SOURCE_DIR}. 189 | # Any modules previously defined with install_lua_module are automatically 190 | # preloaded (via package.preload) prior to running the test script. 191 | # Under LuaDist, set test=true in config.lua to enable testing. 192 | # USE: add_lua_test ( test/test1.lua [args...] [WORKING_DIRECTORY dir]) 193 | macro ( add_lua_test _testfile ) 194 | if ( NOT SKIP_TESTING ) 195 | parse_arguments ( _ARG "WORKING_DIRECTORY" "" ${ARGN} ) 196 | include ( CTest ) 197 | find_program ( LUA NAMES lua lua.bat ) 198 | get_filename_component ( TESTFILEABS ${_testfile} ABSOLUTE ) 199 | get_filename_component ( TESTFILENAME ${_testfile} NAME ) 200 | get_filename_component ( TESTFILEBASE ${_testfile} NAME_WE ) 201 | 202 | # Write wrapper script. 203 | # Note: One simple way to allow the script to find modules is 204 | # to just put them in package.preload. 205 | set ( TESTWRAPPER ${CMAKE_CURRENT_BINARY_DIR}/${TESTFILENAME} ) 206 | _make_module_table ( _table ) 207 | set ( TESTWRAPPERSOURCE 208 | "local CMAKE_CFG_INTDIR = ... or '.' 209 | ${_table} 210 | local function preload_modules(modules) 211 | for name, path in pairs(modules) do 212 | if path:match'%.lua' then 213 | package.preload[name] = assert(loadfile(path)) 214 | else 215 | local name = name:gsub('.*%-', '') -- remove any hyphen prefix 216 | local symbol = 'luaopen_' .. name:gsub('%.', '_') 217 | --improve: generalize to support all-in-one loader? 218 | local path = path:gsub('%$%{CMAKE_CFG_INTDIR%}', CMAKE_CFG_INTDIR) 219 | package.preload[name] = assert(package.loadlib(path, symbol)) 220 | end 221 | end 222 | end 223 | preload_modules(modules) 224 | arg[0] = '${TESTFILEABS}' 225 | table.remove(arg, 1) 226 | return assert(loadfile '${TESTFILEABS}')(unpack(arg)) 227 | " ) 228 | if ( _ARG_WORKING_DIRECTORY ) 229 | get_filename_component ( 230 | TESTCURRENTDIRABS ${_ARG_WORKING_DIRECTORY} ABSOLUTE ) 231 | # note: CMake 2.6 (unlike 2.8) lacks WORKING_DIRECTORY parameter. 232 | set ( _pre ${CMAKE_COMMAND} -E chdir "${TESTCURRENTDIRABS}" ) 233 | endif () 234 | file ( WRITE ${TESTWRAPPER} ${TESTWRAPPERSOURCE}) 235 | add_test ( NAME ${TESTFILEBASE} COMMAND ${_pre} ${LUA} 236 | ${TESTWRAPPER} "${CMAKE_CFG_INTDIR}" 237 | ${_ARG_DEFAULT_ARGS} ) 238 | endif () 239 | # see also http://gdcm.svn.sourceforge.net/viewvc/gdcm/Sandbox/CMakeModules/UsePythonTest.cmake 240 | # Note: ${CMAKE_CFG_INTDIR} is a command-line argument to allow proper 241 | # expansion by the native build tool. 242 | endmacro () 243 | 244 | 245 | # Converts Lua source file `_source` to binary string embedded in C source 246 | # file `_target`. Optionally compiles Lua source to byte code (not available 247 | # under LuaJIT2, which doesn't have a bytecode loader). Additionally, Lua 248 | # versions of bin2c [1] and luac [2] may be passed respectively as additional 249 | # arguments. 250 | # 251 | # [1] http://lua-users.org/wiki/BinToCee 252 | # [2] http://lua-users.org/wiki/LuaCompilerInLua 253 | function ( add_lua_bin2c _target _source ) 254 | find_program ( LUA NAMES lua lua.bat ) 255 | execute_process ( COMMAND ${LUA} -e "string.dump(function()end)" 256 | RESULT_VARIABLE _LUA_DUMP_RESULT ERROR_QUIET ) 257 | if ( NOT ${_LUA_DUMP_RESULT} ) 258 | SET ( HAVE_LUA_DUMP true ) 259 | endif () 260 | message ( "-- string.dump=${HAVE_LUA_DUMP}" ) 261 | 262 | if ( ARGV2 ) 263 | get_filename_component ( BIN2C ${ARGV2} ABSOLUTE ) 264 | set ( BIN2C ${LUA} ${BIN2C} ) 265 | else () 266 | find_program ( BIN2C NAMES bin2c bin2c.bat ) 267 | endif () 268 | if ( HAVE_LUA_DUMP ) 269 | if ( ARGV3 ) 270 | get_filename_component ( LUAC ${ARGV3} ABSOLUTE ) 271 | set ( LUAC ${LUA} ${LUAC} ) 272 | else () 273 | find_program ( LUAC NAMES luac luac.bat ) 274 | endif () 275 | endif ( HAVE_LUA_DUMP ) 276 | message ( "-- bin2c=${BIN2C}" ) 277 | message ( "-- luac=${LUAC}" ) 278 | 279 | get_filename_component ( SOURCEABS ${_source} ABSOLUTE ) 280 | if ( HAVE_LUA_DUMP ) 281 | get_filename_component ( SOURCEBASE ${_source} NAME_WE ) 282 | add_custom_command ( 283 | OUTPUT ${_target} DEPENDS ${_source} 284 | COMMAND ${LUAC} -o ${CMAKE_CURRENT_BINARY_DIR}/${SOURCEBASE}.lo 285 | ${SOURCEABS} 286 | COMMAND ${BIN2C} ${CMAKE_CURRENT_BINARY_DIR}/${SOURCEBASE}.lo 287 | ">${_target}" ) 288 | else () 289 | add_custom_command ( 290 | OUTPUT ${_target} DEPENDS ${SOURCEABS} 291 | COMMAND ${BIN2C} ${_source} ">${_target}" ) 292 | endif () 293 | endfunction() 294 | -------------------------------------------------------------------------------- /dist.info: -------------------------------------------------------------------------------- 1 | --- This dist file is part of LuaDist project 2 | 3 | name="luabitop" 4 | version="1.0.2" 5 | 6 | desc = "Lua Bit Operations Module by Mile Pall" 7 | author = "Mike Pall" 8 | url = "http://bitop.luajit.org/" 9 | license = "MIT/X license" 10 | maintainer = "Peter Drahoš" 11 | 12 | depends = { 13 | "lua >= 5.1" 14 | } 15 | -------------------------------------------------------------------------------- /doc/api.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | API Functions 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | Bit 15 |
16 | 19 | 34 |
35 |

36 | This list of API functions is not intended to replace a tutorial. 37 | If you are not familiar with the terms used, you may want to study the 38 | » Wikipedia 39 | article on bitwise operations first. 40 |

41 |

Loading the BitOp Module

42 |

43 | The suggested way to use the BitOp module is to add the following 44 | to the start of every Lua file that needs one of its functions: 45 |

46 |
 47 | local bit = require("bit")
 48 | 
49 |

50 | This makes the dependency explicit, limits the scope to the current file 51 | and provides faster access to the bit.* functions, too. 52 | It's good programming practice not to rely on the global variable 53 | bit being set (assuming some other part of your application 54 | has already loaded the module). The require function ensures 55 | the module is only loaded once, in any case. 56 |

57 |

Defining Shortcuts

58 |

59 | It's a common (but not a required) practice to cache often used module 60 | functions in locals. This serves as a shortcut to save some typing 61 | and also speeds up resolving them (only relevant if called hundreds of 62 | thousands of times). 63 |

64 |
 65 | local bnot = bit.bnot
 66 | local band, bor, bxor = bit.band, bit.bor, bit.bxor
 67 | local lshift, rshift, rol = bit.lshift, bit.rshift, bit.rol
 68 | -- etc...
 69 | 
 70 | -- Example use of the shortcuts:
 71 | local function tr_i(a, b, c, d, x, s)
 72 |   return rol(bxor(c, bor(b, bnot(d))) + a + x, s) + b
 73 | end
 74 | 
75 |

76 | Remember that and, or and not 77 | are reserved keywords in Lua. They cannot be used for variable names or 78 | literal field names. That's why the corresponding bitwise functions have 79 | been named band, bor, and bnot 80 | (and bxor for consistency). 81 |

82 | While we are at it: a common pitfall is to use bit as the 83 | name of a local temporary variable — well, don't! :-) 84 |

85 |

About the Examples

86 |

87 | The examples below show small Lua one-liners. Their expected output 88 | is shown after -->. This is interpreted as a comment marker 89 | by Lua so you can cut & paste the whole line to a Lua prompt 90 | and experiment with it. 91 |

92 |

93 | Note that all bit operations return signed 32 bit numbers 94 | (rationale). And these print 95 | as signed decimal numbers by default. 96 |

97 |

98 | For clarity the examples assume the definition of a helper function 99 | printx(). This prints its argument as an unsigned 100 | 32 bit hexadecimal number on all platforms: 101 |

102 |
103 | function printx(x)
104 |   print("0x"..bit.tohex(x))
105 | end
106 | 
107 | 108 |

Bit Operations

109 |

y = bit.tobit(x)

110 |

111 | Normalizes a number to the numeric range for bit operations and returns it. 112 | This function is usually not needed since all bit operations already 113 | normalize all of their input arguments. Check the 114 | operational semantics for details. 115 |

116 |
117 | print(0xffffffff)                --> 4294967295 (*)
118 | print(bit.tobit(0xffffffff))     --> -1
119 | printx(bit.tobit(0xffffffff))    --> 0xffffffff
120 | print(bit.tobit(0xffffffff + 1)) --> 0
121 | print(bit.tobit(2^40 + 1234))    --> 1234
122 | 
123 |

124 | (*) See the treatment of hex literals 125 | for an explanation why the printed numbers in the first two lines 126 | differ (if your Lua installation uses a double number type). 127 |

128 | 129 |

y = bit.tohex(x [,n])

130 |

131 | Converts its first argument to a hex string. The number of hex digits is 132 | given by the absolute value of the optional second argument. Positive 133 | numbers between 1 and 8 generate lowercase hex digits. Negative numbers 134 | generate uppercase hex digits. Only the least-significant 4*|n| bits are 135 | used. The default is to generate 8 lowercase hex digits. 136 |

137 |
138 | print(bit.tohex(1))              --> 00000001
139 | print(bit.tohex(-1))             --> ffffffff
140 | print(bit.tohex(0xffffffff))     --> ffffffff
141 | print(bit.tohex(-1, -8))         --> FFFFFFFF
142 | print(bit.tohex(0x21, 4))        --> 0021
143 | print(bit.tohex(0x87654321, 4))  --> 4321
144 | 
145 | 146 |

y = bit.bnot(x)

147 |

148 | Returns the bitwise not of its argument. 149 |

150 |
151 | print(bit.bnot(0))            --> -1
152 | printx(bit.bnot(0))           --> 0xffffffff
153 | print(bit.bnot(-1))           --> 0
154 | print(bit.bnot(0xffffffff))   --> 0
155 | printx(bit.bnot(0x12345678))  --> 0xedcba987
156 | 
157 | 158 |

y = bit.bor(x1 [,x2...])
159 | y = bit.band(x1 [,x2...])
160 | y = bit.bxor(x1 [,x2...])

161 |

162 | Returns either the bitwise or, bitwise and, 163 | or bitwise xor of all of its arguments. 164 | Note that more than two arguments are allowed. 165 |

166 |
167 | print(bit.bor(1, 2, 4, 8))                --> 15
168 | printx(bit.band(0x12345678, 0xff))        --> 0x00000078
169 | printx(bit.bxor(0xa5a5f0f0, 0xaa55ff00))  --> 0x0ff00ff0
170 | 
171 | 172 |

y = bit.lshift(x, n)
173 | y = bit.rshift(x, n)
174 | y = bit.arshift(x, n)

175 |

176 | Returns either the bitwise logical left-shift, 177 | bitwise logical right-shift, or bitwise arithmetic right-shift 178 | of its first argument by the number of bits given by the second argument. 179 |

180 |

181 | Logical shifts treat the first argument as an unsigned number and shift in 182 | 0-bits. Arithmetic right-shift treats the most-significant bit 183 | as a sign bit and replicates it.
184 | Only the lower 5 bits of the shift count are used 185 | (reduces to the range [0..31]). 186 |

187 |
188 | print(bit.lshift(1, 0))              --> 1
189 | print(bit.lshift(1, 8))              --> 256
190 | print(bit.lshift(1, 40))             --> 256
191 | print(bit.rshift(256, 8))            --> 1
192 | print(bit.rshift(-256, 8))           --> 16777215
193 | print(bit.arshift(256, 8))           --> 1
194 | print(bit.arshift(-256, 8))          --> -1
195 | printx(bit.lshift(0x87654321, 12))   --> 0x54321000
196 | printx(bit.rshift(0x87654321, 12))   --> 0x00087654
197 | printx(bit.arshift(0x87654321, 12))  --> 0xfff87654
198 | 
199 | 200 |

y = bit.rol(x, n)
201 | y = bit.ror(x, n)

202 |

203 | Returns either the bitwise left rotation, 204 | or bitwise right rotation of its first argument by the 205 | number of bits given by the second argument. 206 | Bits shifted out on one side are shifted back in on the other side.
207 | Only the lower 5 bits of the rotate count are used 208 | (reduces to the range [0..31]). 209 |

210 |
211 | printx(bit.rol(0x12345678, 12))   --> 0x45678123
212 | printx(bit.ror(0x12345678, 12))   --> 0x67812345
213 | 
214 | 215 |

y = bit.bswap(x)

216 |

217 | Swaps the bytes of its argument and returns it. This can be used 218 | to convert little-endian 32 bit numbers to big-endian 32 bit 219 | numbers or vice versa. 220 |

221 |
222 | printx(bit.bswap(0x12345678)) --> 0x78563412
223 | printx(bit.bswap(0x78563412)) --> 0x12345678
224 | 
225 | 226 |

Example Program

227 |

228 | This is an implementation of the (naïve) Sieve of Eratosthenes 229 | algorithm. It counts the number of primes up to some maximum number. 230 |

231 |

232 | A Lua table is used to hold a bit-vector. Every array index has 233 | 32 bits of the vector. Bitwise operations are used to access and 234 | modify them. Note that the shift counts don't need to be masked 235 | since this is already done by the BitOp shift and rotate functions. 236 |

237 |
238 | local bit = require("bit")
239 | local band, bxor = bit.band, bit.bxor
240 | local rshift, rol = bit.rshift, bit.rol
241 | 
242 | local m = tonumber(arg and arg[1]) or 100000
243 | if m < 2 then m = 2 end
244 | local count = 0
245 | local p = {}
246 | 
247 | for i=0,(m+31)/32 do p[i] = -1 end
248 | 
249 | for i=2,m do
250 |   if band(rshift(p[rshift(i, 5)], i), 1) ~= 0 then
251 |     count = count + 1
252 |     for j=i+i,m,i do
253 |       local jx = rshift(j, 5)
254 |       p[jx] = band(p[jx], rol(-2, j))
255 |     end
256 |   end
257 | end
258 | 
259 | io.write(string.format("Found %d primes up to %d\n", count, m))
260 | 
261 |

262 | Lua BitOp is quite fast. This program runs in less than 263 | 90 milliseconds on a 3 GHz CPU with a standard Lua installation, 264 | but performs more than a million calls to bitwise functions. 265 | If you're looking for even more speed, 266 | check out » LuaJIT. 267 |

268 | 269 |

Caveats

270 |

Signed Results

271 |

272 | Returning signed numbers from bitwise operations may be surprising to 273 | programmers coming from other programming languages which have both 274 | signed and unsigned types. But as long as you treat the results of 275 | bitwise operations uniformly everywhere, this shouldn't cause any problems. 276 |

277 |

278 | Preferably format results with bit.tohex if you want a 279 | reliable unsigned string representation. Avoid the "%x" or 280 | "%u" formats for string.format. They fail on some 281 | architectures for negative numbers and can return more than 8 hex digits 282 | on others. 283 |

284 |

285 | You may also want to avoid the default number to string coercion, 286 | since this is a signed conversion. 287 | The coercion is used for string concatenation and all standard library 288 | functions which accept string arguments (such as print() or 289 | io.write()). 290 |

291 |

Conditionals

292 |

293 | If you're transcribing some code from C/C++, watch out for 294 | bit operations in conditionals. In C/C++ any non-zero value 295 | is implicitly considered as "true". E.g. this C code:
296 |   if (x & 3) ...
297 | must not be turned into this Lua code:
298 |   if band(x, 3) then ... -- wrong! 299 |

300 |

301 | In Lua all objects except nil and false are 302 | considered "true". This includes all numbers. An explicit comparison 303 | against zero is required in this case:
304 |   if band(x, 3) ~= 0 then ... -- correct! 305 |

306 |

Comparing Against Hex Literals

307 |

308 | Comparing the results of bitwise operations (signed numbers) 309 | against hex literals (unsigned numbers) needs some additional care. 310 | The following conditional expression may or may not work right, 311 | depending on the platform you run it on:
312 |   bit.bor(x, 1) == 0xffffffff
313 | E.g. it's never true on a Lua installation with the default number type. 314 | Some simple solutions: 315 |

316 |
    317 |
  • Either never use hex literals larger than 0x7fffffff in comparisons:
    318 |   bit.bor(x, 1) == -1
  • 319 |
  • Or convert them with bit.tobit() before comparing:
    320 |   bit.bor(x, 1) == bit.tobit(0xffffffff)
  • 321 |
  • Or use a generic workaround with bit.bxor():
    322 |   bit.bxor(bit.bor(x, 1), 0xffffffff) == 0
  • 323 |
  • Or use a case-specific workaround:
    324 |   bit.rshift(x, 1) == 0x7fffffff
  • 325 |
326 |
327 |
328 | 336 | 337 | 338 | -------------------------------------------------------------------------------- /doc/bluequad-print.css: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2004-2012 Mike Pall. 2 | * 3 | * You are welcome to use the general ideas of this design for your own sites. 4 | * But please do not steal the stylesheet, the layout or the color scheme. 5 | */ 6 | body { 7 | font-family: serif; 8 | font-size: 11pt; 9 | margin: 0 3em; 10 | padding: 0; 11 | border: none; 12 | } 13 | a:link, a:visited, a:hover, a:active { 14 | text-decoration: none; 15 | background: transparent; 16 | color: #0000ff; 17 | } 18 | h1, h2, h3 { 19 | font-family: sans-serif; 20 | font-weight: bold; 21 | text-align: left; 22 | margin: 0.5em 0; 23 | padding: 0; 24 | } 25 | h1 { 26 | font-size: 200%; 27 | } 28 | h2 { 29 | font-size: 150%; 30 | } 31 | h3 { 32 | font-size: 125%; 33 | } 34 | p { 35 | margin: 0 0 0.5em 0; 36 | padding: 0; 37 | } 38 | ul, ol { 39 | margin: 0.5em 0; 40 | padding: 0 0 0 2em; 41 | } 42 | ul { 43 | list-style: outside square; 44 | } 45 | ol { 46 | list-style: outside decimal; 47 | } 48 | li { 49 | margin: 0; 50 | padding: 0; 51 | } 52 | dl { 53 | margin: 1em 0; 54 | padding: 1em; 55 | border: 1px solid black; 56 | } 57 | dt { 58 | font-weight: bold; 59 | margin: 0; 60 | padding: 0; 61 | } 62 | dt sup { 63 | float: right; 64 | margin-left: 1em; 65 | } 66 | dd { 67 | margin: 0.5em 0 0 2em; 68 | padding: 0; 69 | } 70 | table { 71 | table-layout: fixed; 72 | width: 100%; 73 | margin: 1em 0; 74 | padding: 0; 75 | border: 1px solid black; 76 | border-spacing: 0; 77 | border-collapse: collapse; 78 | } 79 | tr { 80 | margin: 0; 81 | padding: 0; 82 | border: none; 83 | } 84 | td { 85 | text-align: left; 86 | margin: 0; 87 | padding: 0.2em 0.5em; 88 | border-top: 1px solid black; 89 | border-bottom: 1px solid black; 90 | } 91 | tr.separate td { 92 | border-top: double; 93 | } 94 | tt, pre, code, kbd, samp { 95 | font-family: monospace; 96 | font-size: 75%; 97 | } 98 | kbd { 99 | font-weight: bolder; 100 | } 101 | blockquote, pre { 102 | margin: 1em 2em; 103 | padding: 0; 104 | } 105 | img { 106 | border: none; 107 | vertical-align: baseline; 108 | margin: 0; 109 | padding: 0; 110 | } 111 | img.left { 112 | float: left; 113 | margin: 0.5em 1em 0.5em 0; 114 | } 115 | img.right { 116 | float: right; 117 | margin: 0.5em 0 0.5em 1em; 118 | } 119 | .flush { 120 | clear: both; 121 | visibility: hidden; 122 | } 123 | .hide, .noprint, #nav { 124 | display: none !important; 125 | } 126 | .pagebreak { 127 | page-break-before: always; 128 | } 129 | #site { 130 | text-align: right; 131 | font-family: sans-serif; 132 | font-weight: bold; 133 | margin: 0 1em; 134 | border-bottom: 1pt solid black; 135 | } 136 | #site a { 137 | font-size: 1.2em; 138 | } 139 | #site a:link, #site a:visited { 140 | text-decoration: none; 141 | font-weight: bold; 142 | background: transparent; 143 | color: #ffffff; 144 | } 145 | #logo { 146 | color: #ff8000; 147 | } 148 | #head { 149 | clear: both; 150 | margin: 0 1em; 151 | } 152 | #main { 153 | line-height: 1.3; 154 | text-align: justify; 155 | margin: 1em; 156 | } 157 | #foot { 158 | clear: both; 159 | font-size: 80%; 160 | text-align: center; 161 | margin: 0 1.25em; 162 | padding: 0.5em 0 0 0; 163 | border-top: 1pt solid black; 164 | page-break-before: avoid; 165 | page-break-after: avoid; 166 | } 167 | -------------------------------------------------------------------------------- /doc/bluequad.css: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2004-2012 Mike Pall. 2 | * 3 | * You are welcome to use the general ideas of this design for your own sites. 4 | * But please do not steal the stylesheet, the layout or the color scheme. 5 | */ 6 | /* colorscheme: 7 | * 8 | * site | head #4162bf/white | #6078bf/#e6ecff 9 | * ------+------ ----------------+------------------- 10 | * nav | main #bfcfff | #e6ecff/black 11 | * 12 | * nav: hiback loback #c5d5ff #b9c9f9 13 | * hiborder loborder #e6ecff #97a7d7 14 | * link hover #2142bf #ff0000 15 | * 16 | * link: link visited hover #2142bf #8122bf #ff0000 17 | * 18 | * main: boxback boxborder #f0f4ff #bfcfff 19 | */ 20 | body { 21 | font-family: Verdana, Arial, Helvetica, sans-serif; 22 | font-size: 10pt; 23 | margin: 0; 24 | padding: 0; 25 | border: none; 26 | background: #e0e0e0; 27 | color: #000000; 28 | } 29 | a:link { 30 | text-decoration: none; 31 | background: transparent; 32 | color: #2142bf; 33 | } 34 | a:visited { 35 | text-decoration: none; 36 | background: transparent; 37 | color: #8122bf; 38 | } 39 | a:hover, a:active { 40 | text-decoration: underline; 41 | background: transparent; 42 | color: #ff0000; 43 | } 44 | h1, h2, h3 { 45 | font-weight: bold; 46 | text-align: left; 47 | margin: 0.5em 0; 48 | padding: 0; 49 | background: transparent; 50 | } 51 | h1 { 52 | font-size: 200%; 53 | line-height: 3em; /* really 6em relative to body, match #site span */ 54 | margin: 0; 55 | } 56 | h2 { 57 | font-size: 150%; 58 | color: #606060; 59 | } 60 | h3 { 61 | font-size: 125%; 62 | color: #404040; 63 | } 64 | p { 65 | max-width: 600px; 66 | margin: 0 0 0.5em 0; 67 | padding: 0; 68 | } 69 | ul, ol { 70 | max-width: 600px; 71 | margin: 0.5em 0; 72 | padding: 0 0 0 2em; 73 | } 74 | ul { 75 | list-style: outside square; 76 | } 77 | ol { 78 | list-style: outside decimal; 79 | } 80 | li { 81 | margin: 0; 82 | padding: 0; 83 | } 84 | dl { 85 | max-width: 600px; 86 | margin: 1em 0; 87 | padding: 1em; 88 | border: 1px solid #bfcfff; 89 | background: #f0f4ff; 90 | } 91 | dt { 92 | font-weight: bold; 93 | margin: 0; 94 | padding: 0; 95 | } 96 | dt sup { 97 | float: right; 98 | margin-left: 1em; 99 | color: #808080; 100 | } 101 | dt a:visited { 102 | text-decoration: none; 103 | color: #2142bf; 104 | } 105 | dt a:hover, dt a:active { 106 | text-decoration: none; 107 | color: #ff0000; 108 | } 109 | dd { 110 | margin: 0.5em 0 0 2em; 111 | padding: 0; 112 | } 113 | div.tablewrap { /* for IE *sigh* */ 114 | max-width: 600px; 115 | } 116 | table { 117 | table-layout: fixed; 118 | border-spacing: 0; 119 | border-collapse: collapse; 120 | max-width: 600px; 121 | width: 100%; 122 | margin: 1em 0; 123 | padding: 0; 124 | border: 1px solid #bfcfff; 125 | } 126 | tr { 127 | margin: 0; 128 | padding: 0; 129 | border: none; 130 | } 131 | tr.odd { 132 | background: #f0f4ff; 133 | } 134 | tr.separate td { 135 | border-top: 1px solid #bfcfff; 136 | } 137 | td { 138 | text-align: left; 139 | margin: 0; 140 | padding: 0.2em 0.5em; 141 | border: none; 142 | } 143 | tt, code, kbd, samp { 144 | font-family: Courier New, Courier, monospace; 145 | font-size: 110%; 146 | } 147 | kbd { 148 | font-weight: bolder; 149 | } 150 | blockquote, pre { 151 | max-width: 600px; 152 | margin: 1em 2em; 153 | padding: 0; 154 | } 155 | pre { 156 | line-height: 1.1; 157 | } 158 | pre.code { 159 | line-height: 1.4; 160 | margin: 0.5em 0 1em 0.5em; 161 | padding: 0.5em 1em; 162 | border: 1px solid #bfcfff; 163 | background: #f0f4ff; 164 | } 165 | img { 166 | border: none; 167 | vertical-align: baseline; 168 | margin: 0; 169 | padding: 0; 170 | } 171 | img.left { 172 | float: left; 173 | margin: 0.5em 1em 0.5em 0; 174 | } 175 | img.right { 176 | float: right; 177 | margin: 0.5em 0 0.5em 1em; 178 | } 179 | .indent { 180 | padding-left: 1em; 181 | } 182 | .flush { 183 | clear: both; 184 | visibility: hidden; 185 | } 186 | .hide, .noscreen { 187 | display: none !important; 188 | } 189 | .ext { 190 | color: #ff8000; 191 | } 192 | #site { 193 | clear: both; 194 | float: left; 195 | width: 13em; 196 | text-align: center; 197 | font-weight: bold; 198 | margin: 0; 199 | padding: 0; 200 | background: transparent; 201 | color: #ffffff; 202 | } 203 | #site a { 204 | font-size: 200%; 205 | } 206 | #site a:link, #site a:visited { 207 | text-decoration: none; 208 | font-weight: bold; 209 | background: transparent; 210 | color: #ffffff; 211 | } 212 | #site span { 213 | line-height: 3em; /* really 6em relative to body, match h1 */ 214 | } 215 | #logo { 216 | color: #ffb380; 217 | } 218 | #head { 219 | margin: 0; 220 | padding: 0 0 0 2em; 221 | border-left: solid 13em #4162bf; 222 | border-right: solid 3em #6078bf; 223 | background: #6078bf; 224 | color: #e6ecff; 225 | } 226 | #nav { 227 | clear: both; 228 | float: left; 229 | overflow: hidden; 230 | text-align: left; 231 | line-height: 1.5; 232 | width: 13em; 233 | padding-top: 1em; 234 | background: transparent; 235 | } 236 | #nav ul { 237 | list-style: none outside; 238 | margin: 0; 239 | padding: 0; 240 | } 241 | #nav li { 242 | margin: 0; 243 | padding: 0; 244 | } 245 | #nav a { 246 | display: block; 247 | text-decoration: none; 248 | font-weight: bold; 249 | margin: 0; 250 | padding: 2px 1em; 251 | border-top: 1px solid transparent; 252 | border-bottom: 1px solid transparent; 253 | background: transparent; 254 | color: #2142bf; 255 | } 256 | #nav a:hover, #nav a:active { 257 | text-decoration: none; 258 | border-top: 1px solid #97a7d7; 259 | border-bottom: 1px solid #e6ecff; 260 | background: #b9c9f9; 261 | color: #ff0000; 262 | } 263 | #nav a.current, #nav a.current:hover, #nav a.current:active { 264 | border-top: 1px solid #e6ecff; 265 | border-bottom: 1px solid #97a7d7; 266 | background: #c5d5ff; 267 | color: #2142bf; 268 | } 269 | #nav ul ul a { 270 | padding: 0 1em 0 2em; 271 | } 272 | #main { 273 | line-height: 1.5; 274 | text-align: left; 275 | margin: 0; 276 | padding: 1em 2em; 277 | border-left: solid 13em #bfcfff; 278 | border-right: solid 3em #e6ecff; 279 | background: #e6ecff; 280 | } 281 | #foot { 282 | clear: both; 283 | font-size: 80%; 284 | text-align: center; 285 | margin: 0; 286 | padding: 0.5em; 287 | background: #6078bf; 288 | color: #ffffff; 289 | } 290 | #foot a:link, #foot a:visited { 291 | text-decoration: underline; 292 | background: transparent; 293 | color: #ffffff; 294 | } 295 | #foot a:hover, #foot a:active { 296 | text-decoration: underline; 297 | background: transparent; 298 | color: #bfcfff; 299 | } 300 | -------------------------------------------------------------------------------- /doc/changes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Change History 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | Bit 15 |
16 | 19 | 34 |
35 |

36 | This is a list of changes between the released versions of Lua BitOp. 37 | The current release is Lua BitOp 1.0.2. 38 |

39 |

40 | Please check the 41 | » Online Change History 42 | to see whether newer versions are available. 43 |

44 | 45 |

Lua BitOp 1.0.2 — 2012-05-08

46 |
    47 |
  • Add Lua 5.2 compatibility.
  • 48 |
49 | 50 |

Lua BitOp 1.0.1 — 2009-01-06

51 |
    52 |
  • Add bit.tohex for portable conversion of results 53 | to hexadecimal strings.
  • 54 |
  • Add missing LUA_LIB define.
  • 55 |
  • Self-test checks for arithmetic right-shift semantics.
  • 56 |
57 | 58 |

Lua BitOp 1.0.0 — 2008-12-17

59 |
    60 |
  • Initial public release.
  • 61 |
62 |
63 |
64 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /doc/contact.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Contact 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | Bit 15 |
16 | 19 | 34 |
35 |

36 | Please send general questions to the 37 | » Lua mailing list. 38 | You can also send any questions you have directly to me: 39 |

40 | 41 | 51 | 55 | 59 | 60 |

Copyright

61 |

62 | All documentation is 63 | Copyright © 2005-2012 Mike Pall. 64 |

65 | 66 | 67 |
68 |
69 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /doc/img/contact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LuaDist/luabitop/81bb23b0e737805442033535de8e6d204d0e5381/doc/img/contact.png -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Lua Bit Operations Module 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | Bit 15 |
16 | 19 | 34 |
35 |

36 | Lua BitOp is a C extension module for Lua 5.1/5.2 37 | which adds bitwise operations on numbers. 38 |

39 |

40 | Lua BitOp is Copyright © 2008-2012 Mike Pall. 41 | Lua BitOp is free software, released under the 42 | » MIT license 43 | (same license as the Lua core). 44 |

45 |

Features

46 |
    47 |
  • Supported functions: 48 | bit.tobit, bit.tohex, bit.bnot, bit.band, bit.bor, bit.bxor, 49 | bit.lshift, bit.rshift, bit.arshift, bit.rol, bit.ror, bit.bswap
  • 50 |
  • Consistent semantics 51 | across 16, 32 and 64 bit platforms.
  • 52 |
  • Supports different lua_Number types: 53 | either IEEE 754 doubles, int32_t or int64_t.
  • 54 |
  • Runs on Linux, *BSD, Mac OS X, Windows and probably anything else 55 | you can find.
  • 56 |
  • Simple installation on all systems. 57 | No bulky configure scripts. Embedded-systems-friendly.
  • 58 |
  • Internal self-test on startup to detect miscompiles. 59 | Includes a comprehensive test and benchmark suite.
  • 60 |
  • Compatible with the built-in bitwise operations in 61 | » LuaJIT 2.0.
  • 62 |
  • It's as fast as you can get with the standard Lua/C API.
  • 63 |
64 | 65 |

More ...

66 |

67 | Please click on one of the links in the navigation bar to your left 68 | to learn more. 69 |

70 | 71 |

72 | Click on the Logo in the upper left corner to visit 73 | the Lua BitOp project page on the web. All other links to online 74 | resources are marked with a '»'. 75 |

76 |
77 |
78 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /doc/install.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Installation 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | Bit 15 |
16 | 19 | 34 |
35 |

36 | This page explains how to build Lua BitOp from source, against an 37 | existing Lua installation. If you've installed Lua using a package manager 38 | (e.g. as part of a Linux distribution), you're advised to check for 39 | a pre-built package of Lua BitOp and install this instead. 40 |

41 |

Prerequisites

42 |

43 | To compile Lua BitOp, your Lua 5.1/5.2 installation must include all development 44 | files (e.g. include files). If you've installed Lua from source, you 45 | already have them (e.g. in /usr/local/include on POSIX systems). 46 |

47 |

48 | If you've installed Lua using a package manager, you may need to install 49 | an extra Lua development package (e.g. liblua5.1-dev on 50 | Debian/Ubuntu). 51 |

52 |

53 | Probably any current C compiler which can compile Lua also works for 54 | Lua BitOp. The C99 <stdint.h> include file is mandatory, 55 | but the source contains a workaround for MSVC. 56 |

57 |

58 | Lua is by default configured to use double as its number type. 59 | Lua BitOp supports IEEE 754 doubles or alternative configurations 60 | with int32_t or int64_t (suitable for embedded systems without 61 | floating-point hardware). The float number type is not supported. 62 |

63 |

Configuration

64 |

65 | You may need to modify the build scripts and change the paths to 66 | the Lua development files or some compiler flags. Check the start of 67 | Makefile (POSIX), Makefile.mingw (MinGW on Windows) 68 | or msvcbuild.bat (MSVC on Windows) and follow the instructions 69 | in the comments. 70 |

71 |

72 | E.g. the Lua 5.1 include files are located in /usr/include/lua5.1, 73 | if you've installed the Debian/Ubuntu Lua development package. 74 |

75 |

Build & Install

76 |

77 | After » downloading Lua BitOp, 78 | unpack the distribution file, open a terminal/command window, 79 | change into the newly created directory and follow the instructions below. 80 |

81 |

Linux, *BSD, Mac OS X

82 |

83 | For Linux, *BSD and most other POSIX systems just run: 84 |

85 |
 86 | make
 87 | 
88 |

89 | For Mac OS X you need to run this instead: 90 |

91 |
 92 | make macosx
 93 | 
94 |

95 | You probably need to be the root user to install the resulting bit.so 96 | into the C module directory for your current Lua installation. 97 | Most systems provide sudo, so you can run: 98 |

99 |
100 | sudo make install
101 | 
102 |

MinGW on Windows

103 |

104 | Start a command prompt and make sure the MinGW tools are in your PATH. 105 | Then run: 106 |

107 |
108 | mingw32-make -f Makefile.mingw
109 | 
110 |

111 | If you've adjusted the path where C modules for Lua should be installed, 112 | you can run: 113 |

114 |
115 | mingw32-make -f Makefile.mingw install
116 | 
117 |

118 | Otherwise just copy the file bit.dll to the appropriate directory. 119 | By default this is the same directory where lua.exe resides. 120 |

121 |

MSVC on Windows

122 |

123 | Open a "Visual Studio .NET Command Prompt", change to the directory 124 | where msvcbuild.bat resides and run it: 125 |

126 |
127 | msvcbuild
128 | 
129 |

130 | If the file bit.dll has been successfully built, copy it 131 | to the directory where C modules for your Lua installation are installed. 132 | By default this is the same directory where lua.exe resides. 133 |

134 |

Embedding Lua BitOp

135 |

136 | If you're embedding Lua into your application, it's quite simple to 137 | add Lua BitOp as a static module: 138 |

139 |

140 | 1. Copy the file bit.c from the Lua BitOp distribution 141 | to your Lua source code directory. 142 |

143 |

144 | 2. Add this file to your build script (e.g. modify the Makefile) or 145 | import it as a build dependency in your IDE. 146 |

147 |

148 | 3. Edit lualib.h and add the following two lines: 149 |

150 |
151 | #define LUA_BITLIBNAME "bit"
152 | LUALIB_API int luaopen_bit(lua_State *L);
153 | 
154 |

155 | 4. Edit linit.c and add this immediately before the line 156 | with {NULL, NULL}: 157 |

158 |
159 |   {LUA_BITLIBNAME, luaopen_bit},
160 | 
161 |

162 | 5. Now recompile and you're done! 163 |

164 |

Testing

165 |

166 | You can optionally test whether the installation of Lua BitOp was successful. 167 | Keep the terminal/command window open and run one of the following commands: 168 |

169 |

170 | For Linux, *BSD and Mac OS X: 171 |

172 |
173 | make test
174 | 
175 |

176 | For MinGW on Windows: 177 |

178 |
179 | mingw32-make -f Makefile.mingw test
180 | 
181 |

182 | For MSVC on Windows: 183 |

184 |
185 | msvctest
186 | 
187 |

188 | If any of the tests fail, please check that you've properly set the 189 | paths in the build scripts, compiled with the same headers you've 190 | compiled your Lua installation (in particular if you've changed the 191 | number type in luaconf.h) and installed the C module into 192 | the directory which matches your Lua installation. Double check everything 193 | if you've installed multiple Lua interpreters (e.g. both in /usr/bin 194 | and in /usr/local/bin). 195 |

196 |

197 | If you get a warning or a failure about a broken tostring() function 198 | or about broken hex literals, then your Lua installation is defective. 199 | Check with your distributor, replace/upgrade a broken compiler or C library 200 | or re-install Lua yourself with the right configuration settings 201 | (in particular see LUA_NUMBER_* and luai_num* 202 | in luaconf.h). 203 |

204 |

Benchmarks

205 |

206 | The distribution contains several benchmarks: 207 |

208 |
    209 |
  • bitbench.lua tests the speed of basic bit operations. 210 | The benchmark is auto-scaling with a minimum runtime of 1 second 211 | for each part. 212 | The loop overhead is computed first and subtracted from the following 213 | measurements. The time to run a bit operation includes the overhead 214 | of setting up its parameters and calling the corresponding C function.
  • 215 |
  • nsievebits.lua is a simple benchmark adapted from the 216 | » Computer Language Benchmarks Game 217 | (formerly known as Great Computer Language Shootout). The scale factor 218 | is exponential, so run it with a small number between 2 and 10 and time it 219 | (e.g. time lua nsievebits.lua 6).
  • 220 |
  • md5test.lua when given the argument "bench" runs 221 | an auto-scaling benchmark and prints the time per character 222 | needed to compute the MD5 hash of a (medium-length) string. 223 | Please note that this implementation is mainly intended as a 224 | regression test. It's not suitable for cross-language comparisons 225 | against fully optimized MD5 implementations.
  • 226 |
227 |
228 |
229 | 237 | 238 | 239 | -------------------------------------------------------------------------------- /doc/semantics.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Operational Semantics and Rationale 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | Bit 15 |
16 | 19 | 34 |
35 |

36 | Lua uses only a single number type which can be redefined at compile-time. 37 | By default this is a double, i.e. a floating-point number with 38 | 53 bits of precision. Operations in the range of 32 bit numbers 39 | (and beyond) are exact. There is no loss of precision, 40 | so there is no need to add an extra integer number type. 41 | Modern desktop and server CPUs have fast floating-point hardware — 42 | FP arithmetic is nearly the same speed as integer arithmetic. Any 43 | differences vanish under the overhead of the Lua interpreter itself. 44 |

45 |

46 | Even today, many embedded systems lack support for fast FP operations. 47 | These systems benefit from compiling Lua with an integer number type 48 | (with 32 bits or more). 49 |

50 |

51 | The different possible number types and the use of FP numbers cause 52 | some problems when defining bitwise operations on Lua numbers. The 53 | following sections define the operational semantics and try to explain 54 | the rationale behind them. 55 |

56 |

Input and Output Ranges

57 |
    58 |
  • Bitwise operations cannot sensibly be applied to FP numbers 59 | (or their underlying bit patterns). They must be converted to integers 60 | before operating on them and then back to FP numbers.
  • 61 |
  • It's desirable to define semantics that work the same across 62 | all platforms. This dictates that all operations are based on 63 | the common denominator of 32 bit integers.
  • 64 |
  • The float type provides only 24 bits of precision. 65 | This makes it unsuitable for use in bitwise operations. 66 | Lua BitOp refuses to compile against a Lua installation with this 67 | number type.
  • 68 |
  • Bit operations only deal with the underlying bit patterns and 69 | generally ignore signedness (except for arithmetic right-shift). 70 | They are commonly displayed and treated like unsigned numbers, though.
  • 71 |
  • But the Lua number type must be signed and may be limited 72 | to 32 bits. Defining the result type as an unsigned number 73 | would not be cross-platform safe. All bit operations are thus defined to 74 | return results in the range of signed 32 bit numbers 75 | (converted to the Lua number type).
  • 76 |
  • Hexadecimal literals are treated as 77 | unsigned numbers by the Lua parser before converting them 78 | to the Lua number type. This means they can be out of the range of 79 | signed 32 bit integers if the Lua number type has a greater range. 80 | E.g. 0xffffffff has a value of 4294967295 in the default installation, 81 | but may be -1 on embedded systems.
  • 82 |
  • It's highly desirable that hex literals are treated uniformly across 83 | systems when used in bitwise operations. 84 | All bit operations accept arguments in the signed or 85 | the unsigned 32 bit range (and more, see below). 86 | Numbers with the same underlying bit pattern are treated the same by 87 | all operations.
  • 88 |
89 |

Modular Arithmetic

90 |

Arithmetic operations on n-bit integers are usually based on the rules of 91 | » modular arithmetic 92 | modulo 2n. Numbers wrap around when the mathematical result 93 | of operations is outside their defined range. This simplifies hardware 94 | implementations and some algorithms actually require this behavior 95 | (like many cryptographic functions). 96 |

97 |

98 | E.g. for 32 bit integers the following holds: 0xffffffff + 1 = 0 99 |

100 |

101 | Arithmetic modulo 232 is trivially available 102 | if the Lua number type is a 32 bit integer. Otherwise normalization 103 | steps must be inserted. Modular arithmetic should work the same 104 | across all platforms as far as possible: 105 |

106 |
    107 |
  • For the default number type of double, 108 | arguments can be in the range of ±251 109 | and still be safely normalized across all platforms by taking their 110 | least-significant 32 bits. The limit is derived from the way 111 | doubles are converted to integers.
  • 112 |
  • The function bit.tobit can be used to explicitly 113 | normalize numbers to implement modular addition or subtraction. 114 | E.g. bit.tobit(0xffffffff + 1) returns 0 on all platforms.
  • 115 |
  • The limit on the argument range implies that modular multiplication 116 | is usually restricted to multiplying already normalized numbers with 117 | small constants. FP numbers are limited to 53 bits of precision, 118 | anyway. E.g. (230+1)2 does not return an odd number 119 | when computed with doubles.
  • 120 |
121 |

122 | BTW: The tr_i function shown here 123 | is one of the non-linear functions of the (flawed) MD5 cryptographic hash and 124 | relies on modular arithmetic for correct operation. The result is 125 | fed back to other bitwise operations (not shown) and does not need 126 | to be normalized until the last step. 127 |

128 |

Restricted and Undefined Behavior

129 |

130 | The following rules are intended to give a precise and useful definition 131 | (for the programmer), yet give the implementation (interpreter and 132 | compiler) the maximum flexibility and the freedom to apply advanced 133 | optimizations. It's strongly advised not to rely on undefined or 134 | implementation-defined behavior. 135 |

136 |
    137 |
  • All kinds of floating-point numbers are acceptable to the bitwise 138 | operations. None of them cause an error, but some may invoke undefined 139 | behavior: 140 |
      141 |
    • -0 is treated the same as +0 on input and 142 | is never returned as a result.
    • 143 |
    • Passing ±Inf, NaN or numbers outside the range of 144 | ±251 as input yields an undefined result.
    • 145 |
    • Non-integral numbers may be rounded or truncated in an 146 | implementation-defined way. This means the result could differ between 147 | different BitOp versions, different Lua VMs, on different platforms or even 148 | between interpreted vs. compiled code 149 | (as in » LuaJIT).
      150 | Avoid passing fractional numbers to bitwise functions. Use 151 | math.floor() or math.ceil() to get defined behavior.
    • 152 |
  • 153 |
  • Lua provides auto-coercion of string arguments to numbers 154 | by default. This behavior is deprecated for bitwise operations.
  • 155 |
156 |
157 |
158 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /installpath.lua: -------------------------------------------------------------------------------- 1 | -- Script to find the install path for a C module. Public domain. 2 | 3 | if not arg or not arg[1] then 4 | io.write("Usage: lua installpath.lua modulename\n") 5 | os.exit(1) 6 | end 7 | for p in string.gmatch(package.cpath, "[^;]+") do 8 | if string.sub(p, 1, 1) ~= "." then 9 | local p2 = string.gsub(arg[1], "%.", string.sub(package.config, 1, 1)) 10 | io.write(string.gsub(p, "%?", p2), "\n") 11 | return 12 | end 13 | end 14 | error("no suitable installation path found") 15 | -------------------------------------------------------------------------------- /md5test.lua: -------------------------------------------------------------------------------- 1 | -- MD5 test and benchmark. Public domain. 2 | 3 | local bit = require("bit") 4 | local tobit, tohex, bnot = bit.tobit or bit.cast, bit.tohex, bit.bnot 5 | local bor, band, bxor = bit.bor, bit.band, bit.bxor 6 | local lshift, rshift, rol, bswap = bit.lshift, bit.rshift, bit.rol, bit.bswap 7 | local byte, char, sub, rep = string.byte, string.char, string.sub, string.rep 8 | 9 | if not rol then -- Replacement function if rotates are missing. 10 | local bor, shl, shr = bit.bor, bit.lshift, bit.rshift 11 | function rol(a, b) return bor(shl(a, b), shr(a, 32-b)) end 12 | end 13 | 14 | if not bswap then -- Replacement function if bswap is missing. 15 | local bor, band, shl, shr = bit.bor, bit.band, bit.lshift, bit.rshift 16 | function bswap(a) 17 | return bor(shr(a, 24), band(shr(a, 8), 0xff00), 18 | shl(band(a, 0xff00), 8), shl(a, 24)); 19 | end 20 | end 21 | 22 | if not tohex then -- (Unreliable) replacement function if tohex is missing. 23 | function tohex(a) 24 | return string.sub(string.format("%08x", a), -8) 25 | end 26 | end 27 | 28 | local function tr_f(a, b, c, d, x, s) 29 | return rol(bxor(d, band(b, bxor(c, d))) + a + x, s) + b 30 | end 31 | 32 | local function tr_g(a, b, c, d, x, s) 33 | return rol(bxor(c, band(d, bxor(b, c))) + a + x, s) + b 34 | end 35 | 36 | local function tr_h(a, b, c, d, x, s) 37 | return rol(bxor(b, c, d) + a + x, s) + b 38 | end 39 | 40 | local function tr_i(a, b, c, d, x, s) 41 | return rol(bxor(c, bor(b, bnot(d))) + a + x, s) + b 42 | end 43 | 44 | local function transform(x, a1, b1, c1, d1) 45 | local a, b, c, d = a1, b1, c1, d1 46 | 47 | a = tr_f(a, b, c, d, x[ 1] + 0xd76aa478, 7) 48 | d = tr_f(d, a, b, c, x[ 2] + 0xe8c7b756, 12) 49 | c = tr_f(c, d, a, b, x[ 3] + 0x242070db, 17) 50 | b = tr_f(b, c, d, a, x[ 4] + 0xc1bdceee, 22) 51 | a = tr_f(a, b, c, d, x[ 5] + 0xf57c0faf, 7) 52 | d = tr_f(d, a, b, c, x[ 6] + 0x4787c62a, 12) 53 | c = tr_f(c, d, a, b, x[ 7] + 0xa8304613, 17) 54 | b = tr_f(b, c, d, a, x[ 8] + 0xfd469501, 22) 55 | a = tr_f(a, b, c, d, x[ 9] + 0x698098d8, 7) 56 | d = tr_f(d, a, b, c, x[10] + 0x8b44f7af, 12) 57 | c = tr_f(c, d, a, b, x[11] + 0xffff5bb1, 17) 58 | b = tr_f(b, c, d, a, x[12] + 0x895cd7be, 22) 59 | a = tr_f(a, b, c, d, x[13] + 0x6b901122, 7) 60 | d = tr_f(d, a, b, c, x[14] + 0xfd987193, 12) 61 | c = tr_f(c, d, a, b, x[15] + 0xa679438e, 17) 62 | b = tr_f(b, c, d, a, x[16] + 0x49b40821, 22) 63 | 64 | a = tr_g(a, b, c, d, x[ 2] + 0xf61e2562, 5) 65 | d = tr_g(d, a, b, c, x[ 7] + 0xc040b340, 9) 66 | c = tr_g(c, d, a, b, x[12] + 0x265e5a51, 14) 67 | b = tr_g(b, c, d, a, x[ 1] + 0xe9b6c7aa, 20) 68 | a = tr_g(a, b, c, d, x[ 6] + 0xd62f105d, 5) 69 | d = tr_g(d, a, b, c, x[11] + 0x02441453, 9) 70 | c = tr_g(c, d, a, b, x[16] + 0xd8a1e681, 14) 71 | b = tr_g(b, c, d, a, x[ 5] + 0xe7d3fbc8, 20) 72 | a = tr_g(a, b, c, d, x[10] + 0x21e1cde6, 5) 73 | d = tr_g(d, a, b, c, x[15] + 0xc33707d6, 9) 74 | c = tr_g(c, d, a, b, x[ 4] + 0xf4d50d87, 14) 75 | b = tr_g(b, c, d, a, x[ 9] + 0x455a14ed, 20) 76 | a = tr_g(a, b, c, d, x[14] + 0xa9e3e905, 5) 77 | d = tr_g(d, a, b, c, x[ 3] + 0xfcefa3f8, 9) 78 | c = tr_g(c, d, a, b, x[ 8] + 0x676f02d9, 14) 79 | b = tr_g(b, c, d, a, x[13] + 0x8d2a4c8a, 20) 80 | 81 | a = tr_h(a, b, c, d, x[ 6] + 0xfffa3942, 4) 82 | d = tr_h(d, a, b, c, x[ 9] + 0x8771f681, 11) 83 | c = tr_h(c, d, a, b, x[12] + 0x6d9d6122, 16) 84 | b = tr_h(b, c, d, a, x[15] + 0xfde5380c, 23) 85 | a = tr_h(a, b, c, d, x[ 2] + 0xa4beea44, 4) 86 | d = tr_h(d, a, b, c, x[ 5] + 0x4bdecfa9, 11) 87 | c = tr_h(c, d, a, b, x[ 8] + 0xf6bb4b60, 16) 88 | b = tr_h(b, c, d, a, x[11] + 0xbebfbc70, 23) 89 | a = tr_h(a, b, c, d, x[14] + 0x289b7ec6, 4) 90 | d = tr_h(d, a, b, c, x[ 1] + 0xeaa127fa, 11) 91 | c = tr_h(c, d, a, b, x[ 4] + 0xd4ef3085, 16) 92 | b = tr_h(b, c, d, a, x[ 7] + 0x04881d05, 23) 93 | a = tr_h(a, b, c, d, x[10] + 0xd9d4d039, 4) 94 | d = tr_h(d, a, b, c, x[13] + 0xe6db99e5, 11) 95 | c = tr_h(c, d, a, b, x[16] + 0x1fa27cf8, 16) 96 | b = tr_h(b, c, d, a, x[ 3] + 0xc4ac5665, 23) 97 | 98 | a = tr_i(a, b, c, d, x[ 1] + 0xf4292244, 6) 99 | d = tr_i(d, a, b, c, x[ 8] + 0x432aff97, 10) 100 | c = tr_i(c, d, a, b, x[15] + 0xab9423a7, 15) 101 | b = tr_i(b, c, d, a, x[ 6] + 0xfc93a039, 21) 102 | a = tr_i(a, b, c, d, x[13] + 0x655b59c3, 6) 103 | d = tr_i(d, a, b, c, x[ 4] + 0x8f0ccc92, 10) 104 | c = tr_i(c, d, a, b, x[11] + 0xffeff47d, 15) 105 | b = tr_i(b, c, d, a, x[ 2] + 0x85845dd1, 21) 106 | a = tr_i(a, b, c, d, x[ 9] + 0x6fa87e4f, 6) 107 | d = tr_i(d, a, b, c, x[16] + 0xfe2ce6e0, 10) 108 | c = tr_i(c, d, a, b, x[ 7] + 0xa3014314, 15) 109 | b = tr_i(b, c, d, a, x[14] + 0x4e0811a1, 21) 110 | a = tr_i(a, b, c, d, x[ 5] + 0xf7537e82, 6) 111 | d = tr_i(d, a, b, c, x[12] + 0xbd3af235, 10) 112 | c = tr_i(c, d, a, b, x[ 3] + 0x2ad7d2bb, 15) 113 | b = tr_i(b, c, d, a, x[10] + 0xeb86d391, 21) 114 | 115 | return tobit(a+a1), tobit(b+b1), tobit(c+c1), tobit(d+d1) 116 | end 117 | 118 | -- Note: this is copying the original string and NOT particularly fast. 119 | -- A library for struct unpacking would make this task much easier. 120 | local function md5(msg) 121 | local len = #msg 122 | msg = msg.."\128"..rep("\0", 63 - band(len + 8, 63)) 123 | ..char(band(lshift(len, 3), 255), band(rshift(len, 5), 255), 124 | band(rshift(len, 13), 255), band(rshift(len, 21), 255)) 125 | .."\0\0\0\0" 126 | local a, b, c, d = 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 127 | local x, k = {}, 1 128 | for i=1,#msg,4 do 129 | local m0, m1, m2, m3 = byte(msg, i, i+3) 130 | x[k] = bor(m0, lshift(m1, 8), lshift(m2, 16), lshift(m3, 24)) 131 | if k == 16 then 132 | a, b, c, d = transform(x, a, b, c, d) 133 | k = 1 134 | else 135 | k = k + 1 136 | end 137 | end 138 | return tohex(bswap(a))..tohex(bswap(b))..tohex(bswap(c))..tohex(bswap(d)) 139 | end 140 | 141 | assert(md5('') == 'd41d8cd98f00b204e9800998ecf8427e') 142 | assert(md5('a') == '0cc175b9c0f1b6a831c399e269772661') 143 | assert(md5('abc') == '900150983cd24fb0d6963f7d28e17f72') 144 | assert(md5('message digest') == 'f96b697d7cb7938d525a2f31aaf161d0') 145 | assert(md5('abcdefghijklmnopqrstuvwxyz') == 'c3fcd3d76192e4007dfb496cca67e13b') 146 | assert(md5('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') == 147 | 'd174ab98d277d9f5a5611c2c9f419d9f') 148 | assert(md5('12345678901234567890123456789012345678901234567890123456789012345678901234567890') == 149 | '57edf4a22be3c955ac49da2e2107b67a') 150 | 151 | if arg and arg[1] == "bench" then 152 | -- Credits: William Shakespeare, Romeo and Juliet 153 | local txt = [[Rebellious subjects, enemies to peace, 154 | Profaners of this neighbour-stained steel,-- 155 | Will they not hear? What, ho! you men, you beasts, 156 | That quench the fire of your pernicious rage 157 | With purple fountains issuing from your veins, 158 | On pain of torture, from those bloody hands 159 | Throw your mistemper'd weapons to the ground, 160 | And hear the sentence of your moved prince. 161 | Three civil brawls, bred of an airy word, 162 | By thee, old Capulet, and Montague, 163 | Have thrice disturb'd the quiet of our streets, 164 | And made Verona's ancient citizens 165 | Cast by their grave beseeming ornaments, 166 | To wield old partisans, in hands as old, 167 | Canker'd with peace, to part your canker'd hate: 168 | If ever you disturb our streets again, 169 | Your lives shall pay the forfeit of the peace. 170 | For this time, all the rest depart away: 171 | You Capulet; shall go along with me: 172 | And, Montague, come you this afternoon, 173 | To know our further pleasure in this case, 174 | To old Free-town, our common judgment-place. 175 | Once more, on pain of death, all men depart.]] 176 | txt = txt..txt..txt..txt 177 | txt = txt..txt..txt..txt 178 | 179 | local function bench() 180 | local n = 80 181 | repeat 182 | local tm = os.clock() 183 | local res 184 | for i=1,n do 185 | res = md5(txt) 186 | end 187 | assert(res == 'a831e91e0f70eddcb70dc61c6f82f6cd') 188 | tm = os.clock() - tm 189 | if tm > 1 then return tm*(1000000000/(n*#txt)) end 190 | n = n + n 191 | until false 192 | end 193 | 194 | io.write(string.format("MD5 %7.1f ns/char\n", bench())) 195 | end 196 | 197 | -------------------------------------------------------------------------------- /msvcbuild.bat: -------------------------------------------------------------------------------- 1 | @rem Script to build Lua BitOp with MSVC. 2 | 3 | @rem First change the paths to your Lua installation below. 4 | @rem Then open a "Visual Studio .NET Command Prompt", cd to this directory 5 | @rem and run this script. Afterwards copy the resulting bit.dll to 6 | @rem the directory where lua.exe is installed. 7 | 8 | @if not defined INCLUDE goto :FAIL 9 | 10 | @setlocal 11 | @rem Path to the Lua includes and the library file for the Lua DLL: 12 | @set LUA_INC=-I .. 13 | @set LUA_LIB=..\lua51.lib 14 | 15 | @set MYCOMPILE=cl /nologo /MD /O2 /W3 /c %LUA_INC% 16 | @set MYLINK=link /nologo 17 | @set MYMT=mt /nologo 18 | 19 | %MYCOMPILE% bit.c 20 | %MYLINK% /DLL /export:luaopen_bit /out:bit.dll bit.obj %LUA_LIB% 21 | if exist bit.dll.manifest^ 22 | %MYMT% -manifest bit.dll.manifest -outputresource:bit.dll;2 23 | 24 | del *.obj *.exp *.manifest 25 | 26 | @goto :END 27 | :FAIL 28 | @echo You must open a "Visual Studio .NET Command Prompt" to run this script 29 | :END 30 | -------------------------------------------------------------------------------- /msvctest.bat: -------------------------------------------------------------------------------- 1 | @rem Script to test Lua BitOp. 2 | 3 | @setlocal 4 | @rem Path to the Lua executable: 5 | @set LUA=lua 6 | 7 | @echo off 8 | for %%t in (bittest.lua nsievebits.lua md5test.lua) do ( 9 | echo testing %%t 10 | %LUA% %%t 11 | if errorlevel 1^ 12 | goto :FAIL 13 | ) 14 | echo ****** ALL TESTS OK ****** 15 | goto :END 16 | 17 | :FAIL 18 | echo ****** TEST FAILED ****** 19 | :END 20 | -------------------------------------------------------------------------------- /nsievebits.lua: -------------------------------------------------------------------------------- 1 | -- This is the (naive) Sieve of Eratosthenes. Public domain. 2 | 3 | local bit = require("bit") 4 | local band, bxor, rshift, rol = bit.band, bit.bxor, bit.rshift, bit.rol 5 | 6 | local function nsieve(p, m) 7 | local count = 0 8 | for i=0,rshift(m, 5) do p[i] = -1 end 9 | for i=2,m do 10 | if band(rshift(p[rshift(i, 5)], i), 1) ~= 0 then 11 | count = count + 1 12 | for j=i+i,m,i do 13 | local jx = rshift(j, 5) 14 | p[jx] = band(p[jx], rol(-2, j)) 15 | end 16 | end 17 | end 18 | return count 19 | end 20 | 21 | if arg and arg[1] then 22 | local N = tonumber(arg[1]) or 1 23 | if N < 2 then N = 2 end 24 | local primes = {} 25 | 26 | for i=0,2 do 27 | local m = (2^(N-i))*10000 28 | io.write(string.format("Primes up to %8d %8d\n", m, nsieve(primes, m))) 29 | end 30 | else 31 | assert(nsieve({}, 10000) == 1229) 32 | end 33 | --------------------------------------------------------------------------------