lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I have just needed to do bitwise operations in Lua. I wrote a library to
do them, then remembered that something similar had been posted to the
mailing list, so I went and found it, by John Passaniti. Below, I post the
a merge of his and my efforts, which I think is better than either.

What's nice? Well, I allow the type used for integer ops to be defined.
long long seems handy, as this lets you use the full range of the double
mantissa (53 bits on my machine) rather than just the typical 32 bits of
long.

Apart from that, I think some of my results are better than his
(especially right shifting negative numbers gives more sensible results),
owing to careful casting. I like John's use of macros, which could be
adopted to good effect in lmathlib.c. I provide signed and unsigned right
shifts (assuming a sensible compiler that does signed shifts on signed
quantities; this is optional for ANSI C, but mandatory for ISO C).

Something like this should be available from the Lua libraries
page; indeed, since this library is really just exposing features of
standard C in the same way as lmathlib (modulo my use of long long), I
think it should be in the standard system.

#include "lauxlib.h"
#include "lua.h"

typedef long long Integer;
typedef unsigned long long UInteger;

#define luaL_check_bit(L,n) ((Integer)luaL_check_number(L, n))
#define luaL_check_ubit(L,n) ((UInteger)luaL_check_bit(L, n))

#define TDYADIC(name, op, t1, t2) \
  static int name(lua_State* L) { \
    lua_pushnumber(L, \
      luaL_check_ ## t1 ## bit(L, 1) op luaL_check_ ## t2 ## bit(L, 2)); \
    return 1; \
  }

#define DYADIC(name, op)  TDYADIC(name, op, , )

#define MONADIC(name, op) \
  static int name(lua_State* L) { \
    lua_pushnumber(L, op luaL_check_bit(L, 1)); \
    return 1; \
  }

MONADIC(int_not,      ~)
DYADIC(int_mod,       %)
DYADIC(int_and,       &)
DYADIC(int_or,        |)
DYADIC(int_xor,       ^)
TDYADIC(int_lshift,  <<, , u)
TDYADIC(int_rshift,  >>, u, u)
TDYADIC(int_arshift, >>, , u)

static const struct luaL_reg bitlib[] = {
{"bnot",    int_not},
{"imod",    int_mod},  /* "mod" already in Lua math library */
{"band",    int_and},
{"bor",     int_or},
{"bxor",    int_xor},
{"lshift",  int_lshift},
{"rshift",  int_rshift},
{"arshift", int_arshift},
};

extern void lua_bitlibopen (lua_State *L) {
    luaL_openl(L, bitlib);
}

-- 
http://sc3d.org/rrt/ | plagiarism, n.  the mind burgles