diff options
Diffstat (limited to 'source/luametatex/source/luarest/lmtposit.c')
-rw-r--r-- | source/luametatex/source/luarest/lmtposit.c | 654 |
1 files changed, 654 insertions, 0 deletions
diff --git a/source/luametatex/source/luarest/lmtposit.c b/source/luametatex/source/luarest/lmtposit.c new file mode 100644 index 000000000..e7f12b7d2 --- /dev/null +++ b/source/luametatex/source/luarest/lmtposit.c @@ -0,0 +1,654 @@ +/* + See license.txt in the root of this project. +*/ + +/*tex + This is an experiment using the posit (unum) implementation from https://gitlab.com/cerlane/SoftPosit#known, which is + afaiks the standard. At some point it migh tbe interesting to have this as MetaPost number plugin too, but first I need + to figure out some helpers (sin, cos, pow etc). + + Watch out: this is just a playground for me and a few others. There are \CONTEXT\ interfaces but these are also quite + experimental. For instance we might move to 64 bit posits. And how about quires. It all depends on developments in + this area. + + The standard is at: + + https://posithub.org/docs/posit_standard-2.pdf + + The reference code can be found here: + + https://gitlab.com/cerlane/SoftPosit + + However, the implementation lags behind the standard: no posit64 and no functions except from a few that add, subtract, + multiply, divide etc. But I will keep an eye in it. + + Todo: check if we used the right functions (also in auxposit). + +*/ + +# include <luametatex.h> + +# define POSIT_METATABLE "posit number" + +inline static posit_t *positlib_push(lua_State *L) +{ + posit p = lua_newuserdatauv(L, sizeof(posit_t), 0); + luaL_setmetatable(L, POSIT_METATABLE); + return p; +} + +inline static int positlib_new(lua_State *L) +{ + posit p = positlib_push(L); + switch (lua_type(L, 1)) { + case LUA_TSTRING: + *p = double_to_posit(lua_tonumber(L, 1)); + break; + case LUA_TNUMBER: + if (lua_isinteger(L, 1)) { + *p = i64_to_posit(lua_tointeger(L, 1)); + } else { + *p = double_to_posit(lua_tonumber(L, 1)); + } + break; + default: + p->v = 0; + break; + } + return 1; +} + +inline static int positlib_toposit(lua_State *L) +{ + if (lua_type(L, 1) == LUA_TNUMBER) { + posit_t p = double_to_posit(lua_tonumber(L, 1)); + lua_pushinteger(L, p.v); + } else { + lua_pushinteger(L, 0); + } + return 1; +} + +inline static int positlib_fromposit(lua_State *L) +{ + if (lua_type(L, 1) == LUA_TNUMBER) { + posit_t p = { .v = lmt_roundnumber(L, 1) }; + lua_pushnumber(L, posit_to_double(p)); + } else { + lua_pushinteger(L, 0); + } + return 1; +} + +/* + This is nicer for the user. Beware, we create a userdata object on the stack so we need to + replace the original non userdata. +*/ + +static posit_t *positlib_get(lua_State *L, int i) +{ + switch (lua_type(L, i)) { + case LUA_TUSERDATA: + return (posit) luaL_checkudata(L, i, POSIT_METATABLE); + case LUA_TSTRING: + { + posit p = positlib_push(L); + *p = double_to_posit(lua_tonumber(L, i)); + lua_replace(L, i); + return p; + } + case LUA_TNUMBER: + { + posit p = positlib_push(L); + if (lua_isinteger(L, i)) { + *p = i64_to_posit(lua_tointeger(L, 1)); + } else { + *p = double_to_posit(lua_tonumber(L, i)); + } + lua_replace(L, i); + return p; + } + default: + { + posit p = positlib_push(L); + lua_replace(L, i); + return p; + } + } +} + +static int positlib_tostring(lua_State *L) +{ + posit p = positlib_get(L, 1); + double d = posit_to_double(*p); + lua_pushnumber(L, d); + lua_tostring(L, -1); + return 1; +} + + +static int positlib_tonumber(lua_State *L) +{ + posit p = positlib_get(L, 1); + double d = posit_to_double(*p); + lua_pushnumber(L, d); + return 1; +} + +static int positlib_copy(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = *a; + return 1; +} + +static int positlib_eq(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit b = positlib_get(L, 2); + lua_pushboolean(L, posit_eq(*a, *b)); + return 1; +} + +static int positlib_le(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit b = positlib_get(L, 2); + lua_pushboolean(L, posit_le(*a, *b)); + return 1; +} + +static int positlib_lt(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit b = positlib_get(L, 2); + lua_pushboolean(L, posit_lt(*a, *b)); + return 1; +} + +static int positlib_add(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit b = positlib_get(L, 2); + posit p = positlib_push(L); + *p = posit_add(*a, *b); + return 1; +} + +static int positlib_sub(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit b = positlib_get(L, 2); + posit p = positlib_push(L); + *p = posit_sub(*a, *b); + return 1; +} + +static int positlib_mul(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit b = positlib_get(L, 2); + posit p = positlib_push(L); + *p = posit_mul(*a, *b); + return 1; +} + +static int positlib_div(lua_State *L) { + posit a = positlib_get(L, 1); + posit b = positlib_get(L, 2); + posit p = positlib_push(L); + *p = posit_div(*a, *b); + return 1; +} + +static int positlib_round(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = posit_round_to_integer(*a); + return 1; +} + +static int positlib_rounded(lua_State *L) +{ + posit a = positlib_get(L, 1); + lua_pushinteger(L, posit_to_integer(*a)); + return 1; +} + +static int positlib_integer(lua_State *L) +{ + posit p = positlib_get(L, 1); + lua_pushinteger(L, (lua_Integer) posit_to_i64(*p)); + return 1; +} + +static int positlib_NaN(lua_State *L) +{ + posit p = positlib_get(L, 1); + lua_pushboolean(L, p->v == (uint32_t) 0x80000000); + return 1; +} + +static int positlib_NaR(lua_State *L) +{ + posit p = positlib_get(L, 1); + lua_pushboolean(L, posit_is_NaR(p->v)); + return 1; +} + +// static int positlib_idiv(lua_State *L) { +// return 0; +// } + +// static int positlib_mod(lua_State *L) { +// return 0; +// } + +static int positlib_neg(lua_State* L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = posit_neg(*a); + return 1; +} + +static int positlib_min(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit b = positlib_get(L, 2); + posit p = positlib_push(L); + *p = posit_lt(*a, *b) ? *a : *b; + return 1; +} + +static int positlib_max(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit b = positlib_get(L, 2); + posit p = positlib_push(L); + *p = posit_lt(*a, *b) ? *b : *a; + return 1; +} + +static int positlib_pow(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit b = positlib_get(L, 1); + posit p = positlib_push(L); + *p = double_to_posit(pow(posit_to_double(*a),posit_to_double(*b))); + return 1; +} + +static int positlib_abs(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = posit_abs(*a); + return 1; +} + +static int positlib_sqrt(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = posit_sqrt(*a); + return 1; +} + +// static int positlib_ln(lua_State *L) +// { +// posit a = positlib_get(L, 1); +// posit p = positlib_push(L); +// *p = double_to_posit(ln(posit_to_double(*a))); +// return 1; +// } + +static int positlib_log10(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = double_to_posit(log10(posit_to_double(*a))); + return 1; +} + +static int positlib_log1p(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = double_to_posit(log1p(posit_to_double(*a))); + return 1; +} + +static int positlib_log2(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = double_to_posit(log2(posit_to_double(*a))); + return 1; +} + +static int positlib_logb(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = double_to_posit(logb(posit_to_double(*a))); + return 1; +} + +static int positlib_log(lua_State *L) +{ + if (lua_gettop(L) == 1) { + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = double_to_posit(log(posit_to_double(*a))); + } else { + posit a = positlib_get(L, 1); + posit b = positlib_get(L, 2); + posit p = positlib_push(L); + double d = posit_to_double(*a); + double n = posit_to_double(*b); + if (n == 10.0) { + n = (lua_Number) log10(d); + } else if (n == 2.0) { + n = (lua_Number) log2(d); + } else { + n = (lua_Number) log(d) / (lua_Number) log(n); + } + *p = double_to_posit(n); + } + return 1; +} + +static int positlib_exp(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = double_to_posit(exp(posit_to_double(*a))); + return 1; +} + +static int positlib_exp2(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = double_to_posit(exp2(posit_to_double(*a))); + return 1; +} + +static int positlib_ceil(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = double_to_posit(ceil(posit_to_double(*a))); + return 1; +} + +static int positlib_floor(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = double_to_posit(floor(posit_to_double(*a))); + return 1; +} + +static int positlib_modf(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + posit q = positlib_push(L); + double d; + *q = double_to_posit(modf(posit_to_double(*a),&d)); + *p = double_to_posit(d); + return 2; +} + +static int positlib_sin(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = double_to_posit(sin(posit_to_double(*a))); + return 1; +} + +static int positlib_cos(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = double_to_posit(cos(posit_to_double(*a))); + return 1; +} + +static int positlib_tan(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = double_to_posit(tan(posit_to_double(*a))); + return 1; +} + +static int positlib_asin(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = double_to_posit(asin(posit_to_double(*a))); + return 1; +} + +static int positlib_acos(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = double_to_posit(acos(posit_to_double(*a))); + return 1; +} + +static int positlib_atan(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit p = positlib_push(L); + *p = double_to_posit(atan(posit_to_double(*a))); + return 1; +} + +static int positlib_rotate(lua_State *L) +{ + posit a = positlib_get(L, 1); + lua_Integer n = luaL_optinteger(L, 2, 1); + posit p = positlib_push(L); + if (n > 0) { + p->v = (a->v >> n) | (a->v << (posit_bits - n)); + } else if (n < 0) { + p->v = (a->v << n) | (a->v >> (posit_bits - n)); + } else { + p->v = a->v; + } + return 1; +} + +static int positlib_shift(lua_State *L) +{ + posit a = positlib_get(L, 1); + lua_Integer shift = luaL_optinteger(L, 2, 1); + posit p = positlib_push(L); + if (shift > 0) { + p->v = (a->v >> shift) & 0xFFFFFFFF; + } else if (shift < 0) { + p->v = (a->v << -shift) & 0xFFFFFFFF; + } else { + p->v = a->v; + } + return 1; +} + +static int positlib_left(lua_State *L) +{ + posit a = positlib_get(L, 1); + lua_Integer shift = luaL_optinteger(L, 2, 1); + posit p = positlib_push(L); + p->v = (a->v << shift) & 0xFFFFFFFF; + return 1; +} + +static int positlib_right(lua_State *L) +{ + posit_t *a = positlib_get(L, 1); + lua_Integer shift = - luaL_optinteger(L, 2, 1); + posit_t *p = positlib_push(L); + p->v = (a->v >> shift) & 0xFFFFFFFF; + return 1; +} + +static int positlib_and(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit b = positlib_get(L, 2); + posit p = positlib_push(L); + p->v = (a->v) & (b->v); + return 1; +} + +static int positlib_or(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit b = positlib_get(L, 2); + posit p = positlib_push(L); + p->v = (a->v) | (b->v); + return 1; +} + +static int positlib_xor(lua_State *L) +{ + posit a = positlib_get(L, 1); + posit b = positlib_get(L, 2); + posit p = positlib_push(L); + p->v = (a->v) ^ (b->v); + return 1; +} + +static const luaL_Reg positlib_function_list[] = +{ + /* management */ + { "new", positlib_new }, + { "copy", positlib_copy }, + { "tostring", positlib_tostring }, + { "tonumber", positlib_tonumber }, + { "integer", positlib_integer }, + { "rounded", positlib_rounded }, + { "toposit", positlib_toposit }, + { "fromposit", positlib_fromposit }, + /* operators */ + { "__add", positlib_add }, + // { "__idiv", positlib_idiv }, + { "__div", positlib_div }, + // { "__mod", positlib_mod }, + { "__eq", positlib_eq }, + { "__le", positlib_le }, + { "__lt", positlib_lt }, + { "__mul", positlib_mul }, + { "__sub", positlib_sub }, + { "__unm", positlib_neg }, + { "__pow", positlib_pow }, + { "__bor", positlib_or }, + { "__bxor", positlib_xor }, + { "__band", positlib_and }, + { "__shl", positlib_left }, + { "__shr", positlib_right }, + /* */ + { "NaN", positlib_NaN }, + { "NaN", positlib_NaR }, + /* */ + { "bor", positlib_or }, + { "bxor", positlib_xor }, + { "band", positlib_and }, + { "shift", positlib_shift }, + { "rotate", positlib_rotate }, + /* */ + { "min", positlib_min }, + { "max", positlib_max }, + { "abs", positlib_abs }, + { "conj", positlib_neg }, + { "modf", positlib_modf }, + /* */ + { "acos", positlib_acos }, + // { "acosh", positlib_acosh }, + { "asin", positlib_asin }, + // { "asinh", positlib_asinh }, + { "atan", positlib_atan }, + // { "atan2", positlib_atan2 }, + // { "atanh", positlib_atanh }, + // { "cbrt", positlib_cbrt }, + { "ceil", positlib_ceil }, + // { "copysign", positlib_copysign }, + { "cos", positlib_cos }, + // { "cosh", positlib_cosh }, + // { "deg", positlib_deg }, + // { "erf", positlib_erf }, + // { "erfc", positlib_erfc }, + { "exp", positlib_exp }, + { "exp2", positlib_exp2 }, + // { "expm1", positlib_expm1 }, + // { "fabs", positlib_fabs }, + // { "fdim", positlib_fdim }, + { "floor", positlib_floor }, + // { "fma", positlib_fma }, + // { "fmax", positlib_fmax }, + // { "fmin", positlib_fmin }, + // { "fmod", positlib_fmod }, + // { "frexp", positlib_frexp }, + // { "gamma", positlib_gamma }, + // { "hypot", positlib_hypot }, + // { "isfinite", positlib_isfinite }, + // { "isinf", positlib_isinf }, + // { "isnan", positlib_isnan }, + // { "isnormal", positlib_isnormal }, + // { "j0", positlib_j0 }, + // { "j1", positlib_j1 }, + // { "jn", positlib_jn }, + // { "ldexp", positlib_ldexp }, + // { "lgamma", positlib_lgamma }, + { "log", positlib_log }, + { "log10", positlib_log10 }, + { "log1p", positlib_log1p }, + { "log2", positlib_log2 }, + { "logb", positlib_logb }, + // { "modf", positlib_modf }, + // { "nearbyint", positlib_nearbyint }, + // { "nextafter", positlib_nextafter }, + { "pow", positlib_pow }, + // { "rad", positlib_rad }, + // { "remainder", positlib_remainder }, + // { "remquo", positlib_fremquo }, + { "round", positlib_round }, + // { "scalbn", positlib_scalbn }, + { "sin", positlib_sin }, + // { "sinh", positlib_sinh }, + { "sqrt", positlib_sqrt }, + { "tan", positlib_tan }, + // { "tanh", positlib_tanh }, + // { "tgamma", positlib_tgamma }, + // { "trunc", positlib_trunc }, + // { "y0", positlib_y0 }, + // { "y1", positlib_y1 }, + // { "yn", positlib_yn }, + /* */ + { NULL, NULL }, +}; + +int luaopen_posit(lua_State *L) +{ + luaL_newmetatable(L, POSIT_METATABLE); + luaL_setfuncs(L, positlib_function_list, 0); + lua_pushliteral(L, "__index"); + lua_pushvalue(L, -2); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushliteral(L, "tostring"); + lua_gettable(L, -3); + lua_settable(L, -3); + lua_pushliteral(L, "__name"); + lua_pushliteral(L, "posit"); + lua_settable(L, -3); + return 1; +} |