diff options
author | Determinant <ted.sybil@gmail.com> | 2015-06-22 19:01:29 +0800 |
---|---|---|
committer | Determinant <ted.sybil@gmail.com> | 2015-06-22 19:01:29 +0800 |
commit | 2497fd9e7a0fae5ee4887890d7a312e0e08a93b8 (patch) | |
tree | 382f97575bd2df9ee6abb1662b11b279fc22d72b /nerv/matrix/generic/mmatrix.c | |
parent | 196e9b48a3541caccdffc5743001cced70667091 (diff) |
major change: use luarocks to manage project
Diffstat (limited to 'nerv/matrix/generic/mmatrix.c')
-rw-r--r-- | nerv/matrix/generic/mmatrix.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/nerv/matrix/generic/mmatrix.c b/nerv/matrix/generic/mmatrix.c new file mode 100644 index 0000000..b0f0791 --- /dev/null +++ b/nerv/matrix/generic/mmatrix.c @@ -0,0 +1,122 @@ +#ifdef NERV_GENERIC_MMATRIX +#include "matrix.h" +#include "elem_type.h" +#define MATRIX_DATA_FREE(L, ptr) free(ptr) +#define MATRIX_DATA_ALLOC(L, dptr, stride, width, height) \ + host_matrix_(alloc)(L, dptr, stride, width, height) +#define MATRIX_DATA_WRITE(L, data, idx, val) (data[idx] = val) +#define MATRIX_DATA_READ(L, data, idx) (data[idx]) +#define MATRIX_INIT(L) host_matrix_(init)(L) +#define MATRIX_BASE_TNAME nerv_matrix_host_tname +#define NERV_GENERIC_MATRIX +#include "../../common.h" +#include "../../io/chunk_file.h" +#include "string.h" + +static void host_matrix_(alloc)(lua_State *L, + MATRIX_ELEM **dptr, size_t *stride, + long width, long height) { + if ((*dptr = (MATRIX_ELEM *)malloc(width * height)) == NULL) + nerv_error(L, "mmatrix insufficient memory"); + *stride = width; +} + +int nerv_matrix_(get_elem)(lua_State *L) { + Matrix *self = luaT_checkudata(L, 1, nerv_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, MATRIX_ELEM_PTR(self)[idx]); + return 1; +} + +int nerv_matrix_(set_elem)(lua_State *L) { + Matrix *self = luaT_checkudata(L, 1, nerv_matrix_(tname)); + int idx = luaL_checkinteger(L, 2); + MATRIX_ELEM v = luaL_checknumber(L, 3); + if (idx < 0 || idx >= self->nmax) + nerv_error(L, "index must be within range [0, %d)", self->nmax); + MATRIX_ELEM_PTR(self)[idx] = v; + return 0; +} + +static const luaL_Reg nerv_matrix_(extra_methods)[]; +static void host_matrix_(init)(lua_State *L) { + luaN_append_methods(L, nerv_matrix_(extra_methods)); +#ifdef MMATRIX_INIT + MMATRIX_INIT(L); +#endif +} + +#include "matrix.c" + +int nerv_matrix_(load)(lua_State *L) { + ChunkData *chunk = luaT_checkudata(L, 1, nerv_chunk_data_tname); + Matrix *self; + int i, j; + long nrow, ncol; + FILE *fp = chunk->fp; + if (fscanf(fp, "%ld %ld", &nrow, &ncol) != 2) + return 0; + self = nerv_matrix_(new_)(L, nrow, ncol); + for (i = 0; i < nrow; i++) + { + MATRIX_ELEM *row = MATRIX_ROW_PTR(self, i); + for (j = 0; j < ncol; j++) + if (fscanf(fp, MATRIX_ELEM_FMT, row + j) != 1) + { + free(self); + return 0; + } + } + luaT_pushudata(L, self, nerv_matrix_(tname)); + return 1; +} + +int nerv_matrix_(save)(lua_State *L) { + ChunkFileHandle *chunk = luaT_checkudata(L, 2, + nerv_chunk_file_handle_tname); + Matrix *self = luaT_checkudata(L, 1, nerv_matrix_(tname)); + int i, j; + long nrow = self->nrow, ncol = self->ncol; + FILE *fp = chunk->fp; + if (fprintf(fp, "%ld %ld\n", nrow, ncol) < 0) + return 0; + for (i = 0; i < nrow; i++) + { + MATRIX_ELEM *row = MATRIX_ROW_PTR(self, i); + for (j = 0; j < ncol; j++) + if (fprintf(fp, MATRIX_ELEM_WRITE_FMT " ", row[j]) < 0) + return 0; + if (fprintf(fp, "\n") < 0) + return 0; + } + return 0; +} + +static int nerv_matrix_(copy_from)(lua_State *L) { + Matrix *a = luaT_checkudata(L, 1, nerv_matrix_(tname)); + Matrix *b = luaT_checkudata(L, 2, nerv_matrix_(tname)); + int nargs = lua_gettop(L); + int b_begin = nargs > 2 ? luaL_checkinteger(L, 3) : 0; + int b_end = nargs > 3 ? luaL_checkinteger(L, 4) : b->nrow; + int a_begin = nargs > 4 ? luaL_checkinteger(L, 5) : 0; + if (!(0 <= b_begin && b_begin < b_end && b_end <= b->nrow && + a_begin + b_end - b_begin <= a->nrow)) + nerv_error(L, "invalid copy interval"); + if (a->ncol != b->ncol) + nerv_error(L, "matrices should be of the same dimension"); + memmove(MATRIX_ROW_PTR(a, a_begin), + MATRIX_ROW_PTR(b, b_begin), + sizeof(MATRIX_ELEM) * b->ncol * (b_end - b_begin)); + return 0; +} + +static const luaL_Reg nerv_matrix_(extra_methods)[] = { + {"load", nerv_matrix_(load)}, + {"save", nerv_matrix_(save)}, + {"copy_from", nerv_matrix_(copy_from)}, + {NULL, NULL} +}; + +#endif |