From efb786d716363dde8f90ef0672f479790befc79c Mon Sep 17 00:00:00 2001 From: Determinant Date: Fri, 15 May 2015 02:36:55 +0800 Subject: use C macro to implement matrix template --- Makefile | 8 ++- matrix.c | 172 ------------------------------------------------ matrix.lua | 15 ----- matrix/generic/matrix.c | 132 +++++++++++++++++++++++++++++++++++++ matrix/generic/matrix.h | 9 +++ matrix/init.c | 19 ++++++ matrix/matrix.c | 26 ++++++++ matrix/matrix.lua | 15 +++++ 8 files changed, 207 insertions(+), 189 deletions(-) delete mode 100644 matrix.c delete mode 100644 matrix.lua create mode 100644 matrix/generic/matrix.c create mode 100644 matrix/generic/matrix.h create mode 100644 matrix/init.c create mode 100644 matrix/matrix.c create mode 100644 matrix/matrix.lua diff --git a/Makefile b/Makefile index 55510a7..75e1317 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ .PHONY: all clean luajit -OBJS := oop_example.o nerv.o luaT.o common.o matrix.o +OBJS := oop_example.o nerv.o luaT.o common.o matrix/matrix.o matrix/init.o LIBS := libnerv.so -LUA_LIBS := matrix.lua +LUA_LIBS := matrix/matrix.lua INCLUDE := -I build/luajit-2.0/include/luajit-2.0/ -DLUA_USE_APICHECK LDFLAGS := -L luajit-2.0/build/lib/ -llua -lm CFLAGS := @@ -17,10 +17,14 @@ luajit: ./build_luajit.sh $(OBJ_DIR): -mkdir -p $(OBJ_DIR) + -mkdir -p $(OBJ_DIR)/matrix + -mkdir -p $(LUA_DIR)/matrix $(LUA_DIR): -mkdir -p $(LUA_DIR) $(OBJ_DIR)/%.o: %.c gcc -c -o $@ $< $(INCLUDE) -fPIC $(CFLAGS) +$(OBJ_DIR)/matrix/%.o: matrix/%.c + gcc -c -o $@ $< $(INCLUDE) -fPIC $(CFLAGS) $(LUA_DIR)/%.lua: %.lua cp $< $@ $(OBJ_DIR)/luaT.o: diff --git a/matrix.c b/matrix.c deleted file mode 100644 index a58377f..0000000 --- a/matrix.c +++ /dev/null @@ -1,172 +0,0 @@ -#include "common.h" - -typedef struct Matrix { - long stride; /* size of a row */ - long ncol, nrow, nmax; /* dimension of the matrix */ - union { - float *f; - double *d; - } data; /* pointer to actual storage */ - long *data_ref; -} Matrix; - -const char *float_matrix_tname = "nerv.FloatMatrix"; -const char *matrix_tname = "nerv.Matrix"; - -void float_matrix_data_free(Matrix *self) { - if (--(*self->data_ref) == 0) - free(self->data.f); -} - -void float_matrix_data_retain(Matrix *self) { - (*self->data_ref)++; -} - -int float_matrix_new(lua_State *L) { - Matrix *self = (Matrix *)malloc(sizeof(Matrix)); - self->nrow = luaL_checkinteger(L, 1); - self->ncol = luaL_checkinteger(L, 2); - self->nmax = self->nrow * self->ncol; - self->stride = sizeof(float) * self->ncol; - self->data.f = (float *)malloc(self->stride * self->nrow); - self->data_ref = (long *)malloc(sizeof(long)); - *self->data_ref = 0; - float_matrix_data_retain(self); - luaT_pushudata(L, self, float_matrix_tname); - return 1; -} - -int float_matrix_destroy(lua_State *L) { - Matrix *self = luaT_checkudata(L, 1, float_matrix_tname); - float_matrix_data_free(self); - return 0; -} - -int nerv_float_matrix_get_elem(lua_State *L) { - Matrix *self = luaT_checkudata(L, 1, float_matrix_tname); - int idx = luaL_checkinteger(L, 2); - if (idx < 0 || idx >= self->nmax) - nerv_error(L, "index must be within range [0, %d)", self->nmax); - lua_pushnumber(L, self->data.f[idx]); - return 1; -} - -int nerv_float_matrix_set_elem(lua_State *L) { - Matrix *self = luaT_checkudata(L, 1, float_matrix_tname); - int idx = luaL_checkinteger(L, 2); - float v = luaL_checknumber(L, 3); - long upper = self->nrow * self->ncol; - if (idx < 0 || idx >= self->nmax) - nerv_error(L, "index must be within range [0, %d)", self->nmax); - self->data.f[idx] = v; - return 0; -} - -static Matrix *nerv_float_matrix_getrow(Matrix *self, int row) { - Matrix *prow = (Matrix *)malloc(sizeof(Matrix)); - prow->ncol = self->ncol; - prow->nrow = 1; - prow->stride = self->stride; - prow->nmax = prow->ncol; - prow->data.f = (float *)((char *)self->data.f + row * self->stride); - prow->data_ref = self->data_ref; - float_matrix_data_retain(self); - return prow; -} - -static int nerv_float_matrix_newindex(lua_State *L) { - Matrix *self = luaT_checkudata(L, 1, float_matrix_tname); - if (lua_isnumber(L, 2)) - { - int idx = luaL_checkinteger(L, 2); - if (self->nrow == 1) - { - if (idx < 0 || idx >= self->ncol) - nerv_error(L, "index must be within range [0, %d)", self->ncol); - self->data.f[idx] = luaL_checknumber(L, 3); - } - else - nerv_error(L, "cannot assign a scalar to row vector"); - lua_pushboolean(L, 1); - return 2; - } - else - { - lua_pushboolean(L, 0); - return 1; - } -} - - -static int nerv_float_matrix_index(lua_State *L) { - Matrix *self = luaT_checkudata(L, 1, float_matrix_tname); - if (lua_isnumber(L, 2)) - { - int idx = luaL_checkinteger(L, 2); - if (self->nrow == 1) - { - if (idx < 0 || idx >= self->ncol) - nerv_error(L, "index must be within range [0, %d)", self->ncol); - lua_pushnumber(L, self->data.f[idx]); - } - else - { - if (idx < 0 || idx >= self->nrow) - nerv_error(L, "index must be within range [0, %d)", self->nrow); - luaT_pushudata(L, nerv_float_matrix_getrow(self, idx), float_matrix_tname); - } - lua_pushboolean(L, 1); - return 2; - } - else - { - lua_pushboolean(L, 0); - return 1; - } -} - -static int nerv_float_matrix_ncol(lua_State *L) { - Matrix *self = luaT_checkudata(L, 1, float_matrix_tname); - lua_pushinteger(L, self->ncol); - return 1; -} - -static int nerv_float_matrix_nrow(lua_State *L) { - Matrix *self = luaT_checkudata(L, 1, float_matrix_tname); - lua_pushinteger(L, self->nrow); - return 1; -} - - -static const luaL_Reg float_matrix_methods[] = { - {"get_elem", nerv_float_matrix_get_elem}, - {"set_elem", nerv_float_matrix_set_elem}, - {"ncol", nerv_float_matrix_ncol}, - {"nrow", nerv_float_matrix_nrow}, - {"__index__", nerv_float_matrix_index}, - {"__newindex__", nerv_float_matrix_newindex}, - {NULL, NULL} -}; - -void nerv_float_matrix_init(lua_State *L) { - luaT_newmetatable(L, float_matrix_tname, matrix_tname, - float_matrix_new, float_matrix_destroy, NULL); - luaL_register(L, NULL, float_matrix_methods); - lua_pop(L, 1); -} - -static const luaL_Reg matrix_methods[] = { - {"__tostring__", nerv_error_method_not_implemented }, - {"__add__", nerv_error_method_not_implemented }, - {"__sub__", nerv_error_method_not_implemented }, - {"__mul__", nerv_error_method_not_implemented }, - {NULL, NULL} -}; - -void nerv_matrix_init(lua_State *L) { - /* abstract class */ - luaT_newmetatable(L, matrix_tname, NULL, NULL, NULL, NULL); - luaL_register(L, NULL, matrix_methods); - lua_pop(L, 1); - nerv_float_matrix_init(L); -} diff --git a/matrix.lua b/matrix.lua deleted file mode 100644 index 7aa1f12..0000000 --- a/matrix.lua +++ /dev/null @@ -1,15 +0,0 @@ -function nerv.FloatMatrix:__tostring__() - local ncol = self:ncol() - local nrow = self:nrow() - local i = 0 - local strt = {} - for row = 0, nrow - 1 do - for col = 0, ncol - 1 do - table.insert(strt, string.format("%f ", self:get_elem(i))) - i = i + 1 - end - table.insert(strt, "\n") - end - table.insert(strt, string.format("[Float Matrix %d x %d]", nrow, ncol)) - return table.concat(strt) -end diff --git a/matrix/generic/matrix.c b/matrix/generic/matrix.c new file mode 100644 index 0000000..3bb12ef --- /dev/null +++ b/matrix/generic/matrix.c @@ -0,0 +1,132 @@ +#ifdef MATRIX_GENERIC +#include "../../common.h" +#include "matrix.h" + +extern const char *nerv_matrix_tname; +const char *nerv_float_matrix_tname = "nerv.FloatMatrix"; + +void nerv_float_matrix_(data_free)(Matrix *self) { + if (--(*self->data_ref) == 0) + MATRIX_DATA_FREE(self->data.f); +} + +void nerv_float_matrix_(data_retain)(Matrix *self) { + (*self->data_ref)++; +} + +int nerv_float_matrix_(new)(lua_State *L) { + Matrix *self = (Matrix *)malloc(sizeof(Matrix)); + self->nrow = luaL_checkinteger(L, 1); + self->ncol = luaL_checkinteger(L, 2); + self->nmax = self->nrow * self->ncol; + self->stride = MATRIX_DATA_STRIDE(self->ncol); + self->data.f = MATRIX_DATA_ALLOC(self->stride * self->nrow); + self->data_ref = (long *)malloc(sizeof(long)); + *self->data_ref = 0; + nerv_float_matrix_(data_retain)(self); + luaT_pushudata(L, self, nerv_float_matrix_tname); + return 1; +} + +int nerv_float_matrix_(destroy)(lua_State *L) { + Matrix *self = luaT_checkudata(L, 1, nerv_float_matrix_tname); + nerv_float_matrix_(data_free)(self); + return 0; +} + +int nerv_float_matrix_(get_elem)(lua_State *L); +int nerv_float_matrix_(set_elem)(lua_State *L); + +static Matrix *nerv_float_matrix_(getrow)(Matrix *self, int row) { + Matrix *prow = (Matrix *)malloc(sizeof(Matrix)); + prow->ncol = self->ncol; + prow->nrow = 1; + prow->stride = self->stride; + prow->nmax = prow->ncol; + prow->data.f = (float *)((char *)self->data.f + row * self->stride); + prow->data_ref = self->data_ref; + nerv_float_matrix_(data_retain)(self); + return prow; +} + +static int nerv_float_matrix_(newindex)(lua_State *L) { + Matrix *self = luaT_checkudata(L, 1, nerv_float_matrix_tname); + if (lua_isnumber(L, 2)) + { + int idx = luaL_checkinteger(L, 2); + if (self->nrow == 1) + { + if (idx < 0 || idx >= self->ncol) + nerv_error(L, "index must be within range [0, %d)", self->ncol); + self->data.f[idx] = luaL_checknumber(L, 3); + } + else + nerv_error(L, "cannot assign a scalar to row vector"); + lua_pushboolean(L, 1); + return 2; + } + else + { + lua_pushboolean(L, 0); + return 1; + } +} + + +static int nerv_float_matrix_(index)(lua_State *L) { + Matrix *self = luaT_checkudata(L, 1, nerv_float_matrix_tname); + if (lua_isnumber(L, 2)) + { + int idx = luaL_checkinteger(L, 2); + if (self->nrow == 1) + { + if (idx < 0 || idx >= self->ncol) + nerv_error(L, "index must be within range [0, %d)", self->ncol); + lua_pushnumber(L, self->data.f[idx]); + } + else + { + if (idx < 0 || idx >= self->nrow) + nerv_error(L, "index must be within range [0, %d)", self->nrow); + luaT_pushudata(L, nerv_float_matrix_(getrow)(self, idx), nerv_float_matrix_tname); + } + lua_pushboolean(L, 1); + return 2; + } + else + { + lua_pushboolean(L, 0); + return 1; + } +} + +static int nerv_float_matrix_(ncol)(lua_State *L) { + Matrix *self = luaT_checkudata(L, 1, nerv_float_matrix_tname); + lua_pushinteger(L, self->ncol); + return 1; +} + +static int nerv_float_matrix_(nrow)(lua_State *L) { + Matrix *self = luaT_checkudata(L, 1, nerv_float_matrix_tname); + lua_pushinteger(L, self->nrow); + return 1; +} + + +static const luaL_Reg nerv_float_matrix_(methods)[] = { + {"get_elem", nerv_float_matrix_(get_elem)}, + {"set_elem", nerv_float_matrix_(set_elem)}, + {"ncol", nerv_float_matrix_(ncol)}, + {"nrow", nerv_float_matrix_(nrow)}, + {"__index__", nerv_float_matrix_(index)}, + {"__newindex__", nerv_float_matrix_(newindex)}, + {NULL, NULL} +}; + +void nerv_float_matrix_(init)(lua_State *L) { + luaT_newmetatable(L, nerv_float_matrix_tname, nerv_matrix_tname, + nerv_float_matrix_(new), nerv_float_matrix_(destroy), NULL); + luaL_register(L, NULL, nerv_float_matrix_(methods)); + lua_pop(L, 1); +} +#endif diff --git a/matrix/generic/matrix.h b/matrix/generic/matrix.h new file mode 100644 index 0000000..d02b56e --- /dev/null +++ b/matrix/generic/matrix.h @@ -0,0 +1,9 @@ +typedef struct Matrix { + long stride; /* size of a row */ + long ncol, nrow, nmax; /* dimension of the matrix */ + union { + float *f; + double *d; + } data; /* pointer to actual storage */ + long *data_ref; +} Matrix; diff --git a/matrix/init.c b/matrix/init.c new file mode 100644 index 0000000..e251628 --- /dev/null +++ b/matrix/init.c @@ -0,0 +1,19 @@ +#include "../common.h" +#include "generic/matrix.h" + +const char *nerv_matrix_tname = "nerv.Matrix"; +static const luaL_Reg matrix_methods[] = { + {"__tostring__", nerv_error_method_not_implemented }, + {"__add__", nerv_error_method_not_implemented }, + {"__sub__", nerv_error_method_not_implemented }, + {"__mul__", nerv_error_method_not_implemented }, + {NULL, NULL} +}; + +void nerv_matrix_init(lua_State *L) { + /* abstract class */ + luaT_newmetatable(L, nerv_matrix_tname, NULL, NULL, NULL, NULL); + luaL_register(L, NULL, matrix_methods); + lua_pop(L, 1); + nerv_float_matrix_host_init(L); +} diff --git a/matrix/matrix.c b/matrix/matrix.c new file mode 100644 index 0000000..3a593e5 --- /dev/null +++ b/matrix/matrix.c @@ -0,0 +1,26 @@ +#define MATRIX_DATA_FREE(ptr) free(ptr) +#define MATRIX_DATA_ALLOC(size) malloc(size) +#define MATRIX_DATA_STRIDE(ncol) (sizeof(float) * (ncol)) +#define MATRIX_GENERIC +#define nerv_float_matrix_(NAME) nerv_float_matrix_host_ ## NAME +#include "generic/matrix.c" + +int nerv_float_matrix_(get_elem)(lua_State *L) { + Matrix *self = luaT_checkudata(L, 1, nerv_float_matrix_tname); + int idx = luaL_checkinteger(L, 2); + if (idx < 0 || idx >= self->nmax) + nerv_error(L, "index must be within range [0, %d)", self->nmax); + lua_pushnumber(L, self->data.f[idx]); + return 1; +} + +int nerv_float_matrix_(set_elem)(lua_State *L) { + Matrix *self = luaT_checkudata(L, 1, nerv_float_matrix_tname); + int idx = luaL_checkinteger(L, 2); + float v = luaL_checknumber(L, 3); + long upper = self->nrow * self->ncol; + if (idx < 0 || idx >= self->nmax) + nerv_error(L, "index must be within range [0, %d)", self->nmax); + self->data.f[idx] = v; + return 0; +} diff --git a/matrix/matrix.lua b/matrix/matrix.lua new file mode 100644 index 0000000..7aa1f12 --- /dev/null +++ b/matrix/matrix.lua @@ -0,0 +1,15 @@ +function nerv.FloatMatrix:__tostring__() + local ncol = self:ncol() + local nrow = self:nrow() + local i = 0 + local strt = {} + for row = 0, nrow - 1 do + for col = 0, ncol - 1 do + table.insert(strt, string.format("%f ", self:get_elem(i))) + i = i + 1 + end + table.insert(strt, "\n") + end + table.insert(strt, string.format("[Float Matrix %d x %d]", nrow, ncol)) + return table.concat(strt) +end -- cgit v1.2.3-70-g09d2