diff options
| author | christos <christos@NetBSD.org> | 2022-11-21 22:01:32 +0000 |
|---|---|---|
| committer | christos <christos@NetBSD.org> | 2022-11-21 22:01:32 +0000 |
| commit | aa8ee7f2ef496eff5f1f2b454405eafa4330a79e (patch) | |
| tree | 0220f4ad660d0fa9c1eb29825430faf1bae220bc /lib/lua/libm | |
| parent | 1a9fe3305d67bcec8f00f71582c2ea83fa493b53 (diff) | |
lua libm API from Phil Rulon
Diffstat (limited to 'lib/lua/libm')
| -rw-r--r-- | lib/lua/libm/Makefile | 7 | ||||
| -rw-r--r-- | lib/lua/libm/libm.c | 313 |
2 files changed, 320 insertions, 0 deletions
diff --git a/lib/lua/libm/Makefile b/lib/lua/libm/Makefile new file mode 100644 index 00000000000..00cfcd1d7dc --- /dev/null +++ b/lib/lua/libm/Makefile @@ -0,0 +1,7 @@ +# $NetBSD: Makefile,v 1.1 2022/11/21 22:01:33 christos Exp $ + +LUA_MODULES = libm +LUA_SRCS.libm = libm.c +LUA_DPLIBS += m /usr/lib + +.include <bsd.lua.mk> diff --git a/lib/lua/libm/libm.c b/lib/lua/libm/libm.c new file mode 100644 index 00000000000..999de6c597d --- /dev/null +++ b/lib/lua/libm/libm.c @@ -0,0 +1,313 @@ +/* $NetBSD: libm.c,v 1.1 2022/11/21 22:01:33 christos Exp $ */ + +/*- + * Copyright (c) 2022 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Phillip Rulon + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: libm.c,v 1.1 2022/11/21 22:01:33 christos Exp $"); + +#include <lua.h> +#include <lauxlib.h> +#include <math.h> + +const char badarg[] = "argument to libm function not a number"; + +/*- + * The majority of libm functions fall into a few forms: + * + * int func(double); + * double func(double); + * double func(double, double); + * and, + * double func(int, double); + * + * Accordingly, this lends itself to systematic declaration of the lua + * interface functions. These macros set this up. + */ +#define BFUNC_DBL(fname) \ +static int \ +libm_##fname(lua_State *L) \ +{ \ + if (!lua_isnumber(L, 1)) \ + return luaL_error(L, badarg); \ + \ + double x = lua_tonumber(L, 1); \ + lua_pushboolean(L, fname(x)); \ + return 1; \ +} + +#define DFUNC_DBL(fname) \ +static int \ +libm_##fname(lua_State *L) \ +{ \ + if (!lua_isnumber(L, 1)) \ + return luaL_error(L, badarg); \ + \ + double x = lua_tonumber(L, 1); \ + lua_pushnumber(L, fname(x)); \ + return 1; \ +} + +#define DFUNC_INT_DBL(fname) \ +static int \ +libm_##fname(lua_State *L) \ +{ \ + if (!lua_isinteger(L, 1) || \ + !lua_isnumber(L, 2)) \ + return luaL_error(L, badarg); \ + \ + int i = (int)lua_tointeger(L, 1); \ + double x = lua_tonumber(L, 2); \ + lua_pushnumber(L, fname(i, x)); \ + return 1; \ +} + +#define DFUNC_DBL_DBL(fname) \ +static int \ +libm_##fname(lua_State *L) \ +{ \ + if (!lua_isnumber(L, 1) || \ + !lua_isnumber(L, 2)) \ + return luaL_error(L, badarg); \ + double x[] = { \ + lua_tonumber(L, 1), \ + lua_tonumber(L,2) \ + }; \ + lua_pushnumber(L, fname(x[0], x[1])); \ + return 1; \ +} + +int luaopen_libm(lua_State *); + +DFUNC_DBL(acos) +DFUNC_DBL(acosh) +DFUNC_DBL(asin) +DFUNC_DBL(asinh) +DFUNC_DBL(atan) +DFUNC_DBL(atanh) +DFUNC_DBL_DBL(atan2) +DFUNC_DBL(cbrt) +DFUNC_DBL(ceil) +DFUNC_DBL_DBL(copysign) +DFUNC_DBL(cos) +DFUNC_DBL(cosh) +DFUNC_DBL(erf) +DFUNC_DBL(erfc) +DFUNC_DBL(exp) +DFUNC_DBL(exp2) +DFUNC_DBL(expm1) +DFUNC_DBL(fabs) +DFUNC_DBL_DBL(fdim) +BFUNC_DBL(finite) +DFUNC_DBL(floor) +DFUNC_DBL_DBL(fmax) +DFUNC_DBL_DBL(fmin) +DFUNC_DBL_DBL(fmod) +DFUNC_DBL(gamma) +DFUNC_DBL_DBL(hypot) +BFUNC_DBL(isfinite) +BFUNC_DBL(isnan) +BFUNC_DBL(isinf) +DFUNC_DBL(j0) +DFUNC_DBL(j1) +DFUNC_INT_DBL(jn) +DFUNC_DBL(lgamma) +DFUNC_DBL(log) +DFUNC_DBL(log10) +DFUNC_DBL(log1p) +DFUNC_DBL_DBL(nextafter) +DFUNC_DBL_DBL(pow) +DFUNC_DBL_DBL(remainder) +DFUNC_DBL(rint) +DFUNC_DBL(round) +DFUNC_DBL(sin) +DFUNC_DBL(sinh) +DFUNC_DBL(sqrt) +DFUNC_DBL(tan) +DFUNC_DBL(tanh) +DFUNC_DBL(trunc) +DFUNC_DBL(y0) +DFUNC_DBL(y1) +DFUNC_INT_DBL(yn) + +/* + * The following interface functions are special cases which do not lend + * themseleves to the systematic declaration scheme above. + */ +static int +libm_fma(lua_State *L) +{ + if (!lua_isnumber(L, 1) || + !lua_isnumber(L, 2) || + !lua_isnumber(L, 3)) + return luaL_error(L, badarg); + + double x[] = { + lua_tonumber(L, 1), + lua_tonumber(L, 2), + lua_tonumber(L, 3) + }; + lua_pushnumber(L, fma(x[0], x[1], x[2])); + return 1; +} + +static int +libm_nan(lua_State *L) +{ + if (!lua_isstring(L, 1)) + return luaL_error(L, badarg); + + const char *str = luaL_checkstring(L, 1); + lua_pushnumber(L, nan(str)); + return 1; +} + +static int +libm_scalbn(lua_State *L) +{ + if (!lua_isnumber(L, 1) || !lua_isinteger(L, 2)) + return luaL_error(L, badarg); + + double x = lua_tonumber(L, 1); + int i = (int)lua_tointeger(L, 2); + lua_pushnumber(L, scalbn(x, i)); + return 1; +} + +static int +libm_ilogb(lua_State *L) +{ + if (!lua_isnumber(L, 1)) + return luaL_error(L, badarg); + + double x = lua_tonumber(L, 1); + lua_pushinteger(L, ilogb(x)); + return 1; +} + +/* + * set up a table for the math.h constants + */ +#define LIBM_CONST(K) {#K, K} +struct kv { + const char *k; + double v; +}; + +static const struct kv libm_const[] = { + LIBM_CONST(M_E), + LIBM_CONST(M_LOG2E), + LIBM_CONST(M_LOG10E), + LIBM_CONST(M_LN2), + LIBM_CONST(M_LN10), + LIBM_CONST(M_PI), + LIBM_CONST(M_PI_2), + LIBM_CONST(M_PI_4), + LIBM_CONST(M_1_PI), + LIBM_CONST(M_2_PI), + LIBM_CONST(M_2_SQRTPI), + LIBM_CONST(M_SQRT2), + LIBM_CONST(M_SQRT1_2), + { NULL, 0 } +}; + + +static const struct luaL_Reg lualibm[] = { + { "acos", libm_acos }, + { "acosh", libm_acosh }, + { "asin", libm_asin }, + { "asinh", libm_asinh }, + { "atan", libm_atan }, + { "atanh", libm_atanh }, + { "atan2", libm_atan2 }, + { "cbrt", libm_cbrt }, + { "ceil", libm_ceil }, + { "copysign", libm_copysign }, + { "cos", libm_cos }, + { "cosh", libm_cosh }, + { "erf", libm_erf }, + { "erfc", libm_erfc }, + { "exp", libm_exp }, + { "exp2", libm_exp2 }, + { "expm1", libm_expm1 }, + { "fabs", libm_fabs }, + { "fdim", libm_fdim }, + { "finite", libm_finite }, + { "floor", libm_floor }, + { "fma", libm_fma }, + { "fmax", libm_fmax }, + { "fmin", libm_fmin }, + { "fmod", libm_fmod }, + { "gamma", libm_gamma }, + { "hypot", libm_hypot }, + { "ilogb", libm_ilogb }, + { "isfinite", libm_isfinite }, + { "isinf", libm_isinf }, + { "isnan", libm_isnan }, + { "j0", libm_j0 }, + { "j1", libm_j1 }, + { "jn", libm_jn }, + { "lgamma", libm_lgamma }, + { "log", libm_log }, + { "log10", libm_log10 }, + { "log1p", libm_log1p }, + { "nan", libm_nan }, + { "nextafter", libm_nextafter }, + { "pow", libm_pow }, + { "remainder", libm_remainder }, + { "rint", libm_rint }, + { "round", libm_round }, + { "scalbn", libm_scalbn }, + { "sin", libm_sin }, + { "sinh", libm_sinh }, + { "sqrt", libm_sqrt }, + { "tan", libm_tan }, + { "tanh", libm_tanh }, + { "trunc", libm_trunc }, + { "y0", libm_y0 }, + { "y1", libm_y1 }, + { "yn", libm_yn }, + { NULL, NULL } +}; + +int +luaopen_libm(lua_State *L) +{ + const struct kv *kvp = libm_const; + + luaL_newlib(L, lualibm); + + /* integrate the math.h constants */ + while (kvp->k) { + lua_pushnumber(L, kvp->v); + lua_setfield(L, -2, kvp->k); + kvp++; + } + + return 1; +} |
