3 Commits

Author SHA1 Message Date
579d671a77 Update rockspec 2024-02-23 13:07:02 -06:00
61ba76c5a3 Cleanup 2024-02-23 12:56:04 -06:00
8854c0edbe add build.bat 2024-02-22 23:23:07 -06:00
6 changed files with 295 additions and 279 deletions

View File

@@ -2,8 +2,8 @@ SRCDIR := .
CC := $(CROSS)gcc CC := $(CROSS)gcc
CFLAGS := -fPIC -O3 CFLAGS := -fPIC -O3
CXXFLAGS := -I$(SRCDIR)/kiwi -fno-rtti CXXFLAGS := -I$(SRCDIR)/kiwi -fno-rtti
F_LTO := -flto=auto #F_LTO := -flto=auto
CXXFLAGS_EXTRA := -std=c++14 -Wall $(F_LTO) CXXFLAGS_EXTRA := -std=c++14 -Wall $(F_LTO) -fstrict-flex-arrays=3
CFLAGS_EXTRA := -pedantic -std=c99 -Wall $(F_LTO) CFLAGS_EXTRA := -pedantic -std=c99 -Wall $(F_LTO)
LIBFLAG := -shared LIBFLAG := -shared
LIB_EXT := so LIB_EXT := so

2
build.bat Normal file
View File

@@ -0,0 +1,2 @@
cl /nologo /O2 /W4 /wd4200 /c /D_CRT_SECURE_NO_DEPRECATE /I "C:\Program Files\luarocks\include" /EHs /I kiwi luakiwi\luakiwi.cpp
link /DLL /out:ckiwi.dll /def:luakiwi.def /LIBPATH:"C:\Program Files\luarocks\lib" luakiwi.obj lua54.lib

View File

@@ -1,15 +1,15 @@
rockspec_format = "3.0" rockspec_format = "3.0"
package = "ljkiwi" package = "kiwi"
version = "scm-1" version = "scm-1"
source = { source = {
url = "git+https://github.com/jkl1337/ljkiwi", url = "git+https://github.com/jkl1337/ljkiwi",
} }
description = { description = {
summary = "A LuaJIT FFI binding for the Kiwi constraint solver.", summary = "LuaJIT FFI and Lua binding for the Kiwi constraint solver.",
detailed = [[ detailed = [[
ljkiwi is a LuaJIT FFI binding for the Kiwi constraint solver. Kiwi is a fast kiwi is a LuaJIT FFI and Lua binding for the Kiwi constraint solver. Kiwi is a fast
implementation of the Cassowary constraint solving algorithm. ljkiwi provides implementation of the Cassowary constraint solving algorithm. kiwi provides
reasonably efficient bindings using the LuaJIT FFI.]], reasonably efficient bindings using the LuaJIT FFI and convential Lua C bindings.]],
license = "MIT", license = "MIT",
issues_url = "https://github.com/jkl1337/ljkiwi/issues", issues_url = "https://github.com/jkl1337/ljkiwi/issues",
maintainer = "John Luebs", maintainer = "John Luebs",

View File

@@ -4,21 +4,24 @@
#include <kiwi/kiwi.h> #include <kiwi/kiwi.h>
#include <cstring> #include <cstring>
#include <new>
#include "luacompat.h" #include "luacompat.h"
#define ARR_COUNT(x) ((int)(sizeof(x) / sizeof((x)[0])))
#if defined(__GNUC__) && !defined(LKIWI_NO_BUILTIN) #if defined(__GNUC__) && !defined(LKIWI_NO_BUILTIN)
#define l_likely(x) (__builtin_expect(((x) != 0), 1)) #define lk_likely(x) (__builtin_expect(((x) != 0), 1))
#define l_unlikely(x) (__builtin_expect(((x) != 0), 0)) #define lk_unlikely(x) (__builtin_expect(((x) != 0), 0))
#else #else
#define l_likely(x) (x) #define lk_likely(x) (x)
#define l_unlikely(x) (x) #define lk_unlikely(x) (x)
#endif #endif
namespace {
using namespace kiwi;
// Lua 5.1 compatibility for missing lua_arith. // Lua 5.1 compatibility for missing lua_arith.
static void compat_arith_unm(lua_State* L) { inline void compat_arith_unm(lua_State* L) {
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
lua_Number n = lua_tonumber(L, -1); lua_Number n = lua_tonumber(L, -1);
if (n != 0 || lua_isnumber(L, -1)) { if (n != 0 || lua_isnumber(L, -1)) {
@@ -35,14 +38,13 @@ static void compat_arith_unm(lua_State* L) {
} }
// This version supports placeholders. // This version supports placeholders.
static void setfuncs(lua_State* L, const luaL_Reg* l, int nup) { inline void setfuncs(lua_State* L, const luaL_Reg* l, int nup) {
luaL_checkstack(L, nup, "too many upvalues"); luaL_checkstack(L, nup, "too many upvalues");
for (; l->name != NULL; l++) { /* fill the table with given functions */ for (; l->name != NULL; l++) { /* fill the table with given functions */
if (l->func == NULL) /* place holder? */ if (l->func == NULL) /* place holder? */
lua_pushboolean(L, 0); lua_pushboolean(L, 0);
else { else {
int i; for (int i = 0; i < nup; i++) /* copy upvalues to the top */
for (i = 0; i < nup; i++) /* copy upvalues to the top */
lua_pushvalue(L, -nup); lua_pushvalue(L, -nup);
lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
} }
@@ -51,11 +53,15 @@ static void setfuncs(lua_State* L, const luaL_Reg* l, int nup) {
lua_pop(L, nup); /* remove upvalues */ lua_pop(L, nup); /* remove upvalues */
} }
#define newlib(L, l) (lua_newtable((L)), setfuncs((L), (l), 0)) template<typename T, std::size_t N>
constexpr int array_count(T (&)[N]) {
return static_cast<int>(N);
}
namespace { void newlib(lua_State* L, const luaL_Reg* l) {
lua_newtable(L);
using namespace kiwi; setfuncs(L, l, 0);
}
enum KiwiErrKind { enum KiwiErrKind {
KiwiErrNone, KiwiErrNone,
@@ -80,20 +86,32 @@ struct KiwiExpression {
double constant; double constant;
int term_count; int term_count;
Constraint* owner; Constraint* owner;
// https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
// Although using one-element arrays this way is discouraged, GCC handles accesses to #if !defined(_MSC_VER) || _MSC_VER >= 1900
// trailing one-element array members analogously to zero-length arrays. KiwiTerm terms[];
// The only reason avoiding FAM here is to support older MSVC.
// Otherwise this is a non-issue. static constexpr std::size_t sz(int count) {
return sizeof(KiwiExpression) + sizeof(KiwiTerm) * (count > 0 ? count : 0);
}
#else
KiwiTerm terms[1]; KiwiTerm terms[1];
static constexpr std::size_t sz(int count) {
return sizeof(KiwiExpression) + sizeof(KiwiTerm) * (count > 1 ? count - 1 : 0);
}
#endif
KiwiExpression() = delete;
KiwiExpression(const KiwiExpression&) = delete;
KiwiExpression& operator=(const KiwiExpression&) = delete;
~KiwiExpression() = delete;
}; };
// This structure was initially designed for LuaJIT FFI. It works OK for C++ // This mechanism was initially designed for LuaJIT FFI.
// though it certainly isn't idiomatic.
struct KiwiErr { struct KiwiErr {
enum KiwiErrKind kind; enum KiwiErrKind kind;
const char* message; const char* message;
bool must_free; bool must_delete;
}; };
struct KiwiSolver { struct KiwiSolver {
@@ -101,28 +119,27 @@ struct KiwiSolver {
Solver solver; Solver solver;
}; };
const KiwiErr* new_error(const KiwiErr* base, const std::exception& ex) { inline const KiwiErr* new_error(const KiwiErr* base, const std::exception& ex) {
if (!std::strcmp(ex.what(), base->message)) if (!std::strcmp(ex.what(), base->message))
return base; return base;
const auto msg_n = std::strlen(ex.what()) + 1; const auto msg_n = std::strlen(ex.what()) + 1;
auto* mem = static_cast<char*>(std::malloc(sizeof(KiwiErr) + msg_n)); auto* mem = static_cast<char*>(::operator new(sizeof(KiwiErr) + msg_n, std::nothrow));
if (!mem) { if (!mem) {
return base; return base;
} }
auto* msg = mem + sizeof(KiwiErr);
const auto* err = new (mem) KiwiErr {base->kind, mem + sizeof(KiwiErr), true}; std::memcpy(msg, ex.what(), msg_n);
std::memcpy(const_cast<char*>(err->message), ex.what(), msg_n); return new (mem) KiwiErr {base->kind, msg, true};
return err;
} }
const constexpr KiwiErr kKiwiErrUnhandledCxxException {
KiwiErrUnknown,
"An unhandled C++ exception occurred."};
template<typename F> template<typename F>
inline const KiwiErr* wrap_err(F&& f) { inline const KiwiErr* wrap_err(F&& f) {
static const constexpr KiwiErr kKiwiErrUnhandledCxxException {
KiwiErrUnknown,
"An unhandled C++ exception occurred."};
try { try {
f(); f();
} catch (const UnsatisfiableConstraint&) { } catch (const UnsatisfiableConstraint&) {
@@ -198,12 +215,12 @@ inline Constraint* kiwi_constraint_retain(Constraint* c) {
return c; return c;
} }
inline void kiwi_constraint_new( inline Constraint* kiwi_constraint_new(
const KiwiExpression* lhs, const KiwiExpression* lhs,
const KiwiExpression* rhs, const KiwiExpression* rhs,
RelationalOperator op, RelationalOperator op,
double strength, double strength,
Constraint* mem void* mem
) { ) {
if (strength < 0.0) { if (strength < 0.0) {
strength = kiwi::strength::required; strength = kiwi::strength::required;
@@ -222,7 +239,7 @@ inline void kiwi_constraint_new(
terms.emplace_back(*t->var, -t->coefficient); terms.emplace_back(*t->var, -t->coefficient);
} }
} }
new (mem) Constraint( return new (mem) Constraint(
Expression(std::move(terms), (lhs ? lhs->constant : 0.0) - (rhs ? rhs->constant : 0.0)), Expression(std::move(terms), (lhs ? lhs->constant : 0.0) - (rhs ? rhs->constant : 0.0)),
static_cast<RelationalOperator>(op), static_cast<RelationalOperator>(op),
strength strength

File diff suppressed because it is too large Load Diff

12
t.lua
View File

@@ -8,14 +8,16 @@ do
local v3 = kiwi.Var("v3") local v3 = kiwi.Var("v3")
local v4 = kiwi.Var("v4") local v4 = kiwi.Var("v4")
local v5 = kiwi.Var("v5") local v5 = kiwi.Var("v5")
local c = (3 * v1 + 4 * v2 + 6 * v3):eq(0) local c1 = (3 * v1 + 4 * v2 + 6 * v3):eq(0)
local c2 = (6 * v4 + 4 * v5 + 2 * v1 + 1.4 * v1 / 0.3):le(1000)
local e = c:expression() local e = c1:expression()
print(e) local s = kiwi.Solver()
s:add_constraints({ c1, c2, c1 })
print(s:dumps())
end end
collectgarbage("collect")
collectgarbage("collect")
-- c = (3 * v1 + 4 * v2 + 6 * v3):eq(0) -- c = (3 * v1 + 4 * v2 + 6 * v3):eq(0)
-- local t = c:expression():terms() -- local t = c:expression():terms()