#include "tf.h"
#include "a/tf.h"
int liba_tf_die(lua_State *L)
{
a_tf *const ctx = (a_tf *)lua_touserdata(L, 1);
if (ctx)
{
lua_alloc(L, ctx->num_p, 0);
ctx->num_p = 0;
ctx->num_n = 0;
ctx->input = 0;
lua_alloc(L, ctx->den_p, 0);
ctx->den_p = 0;
ctx->den_n = 0;
ctx->output = 0;
}
return 0;
}
int liba_tf_new(lua_State *L)
{
if (lua_gettop(L) > 1)
{
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checktype(L, 2, LUA_TTABLE);
unsigned int const num_n = (unsigned int)lua_rawlen(L, 1);
a_float *const num_p = (a_float *)lua_alloc(L, NULL, sizeof(a_float) * num_n * 2);
lua_array_num_get(L, 1, num_p, num_n);
unsigned int const den_n = (unsigned int)lua_rawlen(L, 2);
a_float *const den_p = (a_float *)lua_alloc(L, NULL, sizeof(a_float) * den_n * 2);
lua_array_num_get(L, 2, den_p, den_n);
a_tf *const ctx = lua_newclass(L, a_tf);
lua_registry_get(L, liba_tf_new);
lua_setmetatable(L, -2);
a_tf_init(ctx, num_n, num_p, num_p + num_n, den_n, den_p, den_p + den_n);
return 1;
}
return 0;
}
int liba_tf_init(lua_State *L)
{
if (lua_gettop(L) > 2)
{
luaL_checktype(L, 1, LUA_TUSERDATA);
luaL_checktype(L, 2, LUA_TTABLE);
luaL_checktype(L, 3, LUA_TTABLE);
a_tf *const ctx = (a_tf *)lua_touserdata(L, 1);
unsigned int const num_n = (unsigned int)lua_rawlen(L, 2);
a_float *const num_p = (a_float *)lua_alloc(L, ctx->num_p, sizeof(a_float) * num_n * 2);
lua_array_num_get(L, 2, num_p, num_n);
unsigned int const den_n = (unsigned int)lua_rawlen(L, 3);
a_float *const den_p = (a_float *)lua_alloc(L, ctx->den_p, sizeof(a_float) * den_n * 2);
lua_array_num_get(L, 3, den_p, den_n);
a_tf_init(ctx, num_n, num_p, num_p + num_n, den_n, den_p, den_p + den_n);
lua_pushvalue(L, 1);
return 1;
}
return 0;
}
int liba_tf_iter(lua_State *L)
{
a_tf *const ctx = (a_tf *)lua_touserdata(L, 1);
if (ctx)
{
a_float x = (a_float)luaL_checknumber(L, 2);
lua_pushnumber(L, (lua_Number)a_tf_iter(ctx, x));
return 1;
}
return 0;
}
int liba_tf_zero(lua_State *L)
{
a_tf *const ctx = (a_tf *)lua_touserdata(L, 1);
if (ctx)
{
a_tf_zero(ctx);
return 1;
}
return 0;
}
static int liba_tf_set(lua_State *L)
{
a_tf *const ctx = (a_tf *)lua_touserdata(L, 1);
switch (a_hash_bkdr(lua_tostring(L, 2), 0))
{
case 0x001D0A2A: {
luaL_checktype(L, 3, LUA_TTABLE);
unsigned int const num_n = (unsigned int)lua_rawlen(L, 3);
a_float *const num_p = (a_float *)lua_alloc(L, ctx->num_p, sizeof(a_float) * num_n * 2);
lua_array_num_get(L, 3, num_p, num_n);
a_tf_set_num(ctx, num_n, num_p, num_p + num_n);
break;
}
case 0x001A63A1: {
luaL_checktype(L, 3, LUA_TTABLE);
unsigned int const den_n = (unsigned int)lua_rawlen(L, 3);
a_float *const den_p = (a_float *)lua_alloc(L, ctx->den_p, sizeof(a_float) * den_n * 2);
lua_array_num_get(L, 3, den_p, den_n);
a_tf_set_den(ctx, den_n, den_p, den_p + den_n);
break;
}
case 0xE8859EEB: case 0xE70C48C6: case 0xA65758B2: case 0xAEB551C6: break;
default:
lua_getmetatable(L, 1);
lua_replace(L, 1);
lua_rawset(L, 1);
}
return 0;
}
static int liba_tf_get(lua_State *L)
{
a_tf const *const ctx = (a_tf const *)lua_touserdata(L, 1);
switch (a_hash_bkdr(lua_tostring(L, 2), 0))
{
case 0x001D0A2A: lua_array_num_new(L, ctx->num_p, ctx->num_n);
break;
case 0x001A63A1: lua_array_num_new(L, ctx->den_p, ctx->den_n);
break;
case 0x41FAB016: lua_array_num_new(L, ctx->input, ctx->num_n);
break;
case 0x23C9C461: lua_array_num_new(L, ctx->output, ctx->den_n);
break;
case 0xA65758B2: lua_registry_get(L, liba_tf_new);
lua_pushstring(L, "num");
lua_array_num_new(L, ctx->num_p, ctx->num_n);
lua_rawset(L, -3);
lua_pushstring(L, "den");
lua_array_num_new(L, ctx->den_p, ctx->den_n);
lua_rawset(L, -3);
lua_pushstring(L, "input");
lua_array_num_new(L, ctx->input, ctx->num_n);
lua_rawset(L, -3);
lua_pushstring(L, "output");
lua_array_num_new(L, ctx->output, ctx->den_n);
lua_rawset(L, -3);
break;
default:
lua_getmetatable(L, 1);
lua_replace(L, 1);
lua_rawget(L, 1);
}
return 1;
}
static int liba_tf_(lua_State *L)
{
lua_pushcfunction(L, liba_tf_new);
lua_replace(L, 1);
lua_call(L, lua_gettop(L) - 1, 1);
return 1;
}
int luaopen_liba_tf(lua_State *L)
{
static lua_fun const funcs[] = {
{"init", liba_tf_init},
{"iter", liba_tf_iter},
{"zero", liba_tf_zero},
{"new", liba_tf_new},
{"die", liba_tf_die},
};
lua_createtable(L, 0, A_LEN(funcs));
lua_fun_reg(L, -1, funcs, A_LEN(funcs));
lua_createtable(L, 0, 1);
lua_fun_set(L, -1, "__call", liba_tf_);
lua_setmetatable(L, -2);
static lua_fun const metas[] = {
{"__newindex", liba_tf_set},
{"__index", liba_tf_get},
#if defined(LUA_VERSION_NUM) && (LUA_VERSION_NUM > 503)
{"__close", liba_tf_die},
#endif
{"__call", liba_tf_iter},
{"__gc", liba_tf_die},
};
lua_createtable(L, 0, A_LEN(metas) + A_LEN(funcs) + 1);
lua_fun_reg(L, -1, metas, A_LEN(metas));
lua_fun_reg(L, -1, funcs, A_LEN(funcs));
lua_str_set(L, -1, "__name", "a.tf");
lua_registry_set(L, liba_tf_new);
return 1;
}