feat(lua/numerics): expose mpz and mpq numbers in the Lua bindings
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
88ebdbcfb6
commit
e2da8c1f4d
5 changed files with 157 additions and 1 deletions
|
@ -1 +1 @@
|
||||||
add_library(lua name.cpp)
|
add_library(lua name.cpp numerics.cpp)
|
||||||
|
|
129
src/bindings/lua/numerics.cpp
Normal file
129
src/bindings/lua/numerics.cpp
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||||
|
Released under Apache 2.0 license as described in the file LICENSE.
|
||||||
|
|
||||||
|
Author: Leonardo de Moura
|
||||||
|
*/
|
||||||
|
#ifdef LEAN_USE_LUA
|
||||||
|
#include <sstream>
|
||||||
|
#include <lua.hpp>
|
||||||
|
#include "util/debug.h"
|
||||||
|
#include "util/numerics/mpz.h"
|
||||||
|
#include "util/numerics/mpq.h"
|
||||||
|
|
||||||
|
namespace lean {
|
||||||
|
template<typename T, char const * N, char const * M>
|
||||||
|
class num_bindings {
|
||||||
|
public:
|
||||||
|
template<unsigned idx>
|
||||||
|
static T const & get_arg(lua_State * L) {
|
||||||
|
static thread_local T arg;
|
||||||
|
if (lua_isuserdata(L, idx)) {
|
||||||
|
return *static_cast<T*>(luaL_checkudata(L, idx, M));
|
||||||
|
} else if (lua_isstring(L, idx)) {
|
||||||
|
char const * str = luaL_checkstring(L, idx);
|
||||||
|
arg = T(str);
|
||||||
|
return arg;
|
||||||
|
} else {
|
||||||
|
arg = luaL_checkinteger(L, 1);
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push_result(lua_State * L, T const & val) {
|
||||||
|
void * mem = lua_newuserdata(L, sizeof(T));
|
||||||
|
new (mem) T(val);
|
||||||
|
luaL_getmetatable(L, M);
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gc(lua_State * L) {
|
||||||
|
T * n = static_cast<T*>(luaL_checkudata(L, 1, M));
|
||||||
|
n->~T();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tostring(lua_State * L) {
|
||||||
|
T * n = static_cast<T*>(luaL_checkudata(L, 1, M));
|
||||||
|
std::ostringstream out;
|
||||||
|
out << *n;
|
||||||
|
lua_pushfstring(L, out.str().c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int eq(lua_State * L) {
|
||||||
|
lua_pushboolean(L, get_arg<1>(L) == get_arg<2>(L));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lt(lua_State * L) {
|
||||||
|
lua_pushboolean(L, get_arg<1>(L) < get_arg<2>(L));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int add(lua_State * L) {
|
||||||
|
return push_result(L, get_arg<1>(L) + get_arg<2>(L));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sub(lua_State * L) {
|
||||||
|
return push_result(L, get_arg<1>(L) - get_arg<2>(L));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mul(lua_State * L) {
|
||||||
|
return push_result(L, get_arg<1>(L) * get_arg<2>(L));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int div(lua_State * L) {
|
||||||
|
T const & arg2 = get_arg<2>(L);
|
||||||
|
if (arg2 == 0) luaL_error(L, "division by zero");
|
||||||
|
return push_result(L, get_arg<1>(L) / arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int umn(lua_State * L) {
|
||||||
|
return push_result(L, 0 - get_arg<1>(L));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int power(lua_State * L) {
|
||||||
|
int k = luaL_checkinteger(L, 2);
|
||||||
|
if (k < 0) luaL_error(L, "argument #2 must be positive");
|
||||||
|
return push_result(L, pow(get_arg<1>(L), k));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct luaL_Reg m[];
|
||||||
|
|
||||||
|
static int mk(lua_State * L) {
|
||||||
|
T const & arg = get_arg<1>(L);
|
||||||
|
return push_result(L, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init(lua_State * L) {
|
||||||
|
luaL_newmetatable(L, M);
|
||||||
|
luaL_setfuncs(L, m, 0);
|
||||||
|
|
||||||
|
lua_pushcfunction(L, mk);
|
||||||
|
lua_setglobal(L, N);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, char const * N, char const * M>
|
||||||
|
const struct luaL_Reg num_bindings<T, N, M>::m[] = {
|
||||||
|
{"__gc", num_bindings<T, N, M>::gc}, {"__tostring", num_bindings<T, N, M>::tostring}, {"__eq", num_bindings<T, N, M>::eq},
|
||||||
|
{"__lt", num_bindings<T, N, M>::lt}, {"__add", num_bindings<T, N, M>::add}, {"__add", num_bindings<T, N, M>::sub},
|
||||||
|
{"__mul", num_bindings<T, N, M>::mul}, {"__div", num_bindings<T, N, M>::div}, {"__pow", num_bindings<T, N, M>::power},
|
||||||
|
{"__unm", num_bindings<T, N, M>::umn},
|
||||||
|
{0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr char const mpz_name[] = "mpz";
|
||||||
|
constexpr char const mpz_metatable[] = "mpz.mt";
|
||||||
|
void init_mpz(lua_State * L) {
|
||||||
|
num_bindings<mpz, mpz_name, mpz_metatable>::init(L);
|
||||||
|
}
|
||||||
|
constexpr char const mpq_name[] = "mpq";
|
||||||
|
constexpr char const mpq_metatable[] = "mpq.mt";
|
||||||
|
void init_mpq(lua_State * L) {
|
||||||
|
num_bindings<mpq, mpq_name, mpq_metatable>::init(L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
13
src/bindings/lua/numerics.h
Normal file
13
src/bindings/lua/numerics.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||||
|
Released under Apache 2.0 license as described in the file LICENSE.
|
||||||
|
|
||||||
|
Author: Leonardo de Moura
|
||||||
|
*/
|
||||||
|
#ifdef LEAN_USE_LUA
|
||||||
|
#include <lua.hpp>
|
||||||
|
namespace lean {
|
||||||
|
void init_mpz(lua_State * L);
|
||||||
|
void init_mpq(lua_State * L);
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -10,6 +10,7 @@ Author: Leonardo de Moura
|
||||||
#ifdef LEAN_USE_LUA
|
#ifdef LEAN_USE_LUA
|
||||||
#include <lua.hpp>
|
#include <lua.hpp>
|
||||||
#include "bindings/lua/name.h"
|
#include "bindings/lua/name.h"
|
||||||
|
#include "bindings/lua/numerics.h"
|
||||||
|
|
||||||
int main(int argc, char ** argv) {
|
int main(int argc, char ** argv) {
|
||||||
int status, result;
|
int status, result;
|
||||||
|
@ -18,6 +19,8 @@ int main(int argc, char ** argv) {
|
||||||
L = luaL_newstate();
|
L = luaL_newstate();
|
||||||
luaL_openlibs(L);
|
luaL_openlibs(L);
|
||||||
lean::init_name(L);
|
lean::init_name(L);
|
||||||
|
lean::init_mpz(L);
|
||||||
|
lean::init_mpq(L);
|
||||||
|
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
status = luaL_loadfile(L, argv[i]);
|
status = luaL_loadfile(L, argv[i]);
|
||||||
|
|
11
tests/lua/mpz1.lua
Normal file
11
tests/lua/mpz1.lua
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
a = mpz("1000000000000000000000000000")
|
||||||
|
b = mpz(10)
|
||||||
|
c = mpz(10)
|
||||||
|
print(a/3)
|
||||||
|
print(b == c)
|
||||||
|
print(a < b)
|
||||||
|
print(b < a)
|
||||||
|
print(10 < b)
|
||||||
|
print(10 <= b)
|
||||||
|
print(a)
|
||||||
|
print(b)
|
Loading…
Add table
Reference in a new issue