Compare commits

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
CFLAGS := -fPIC -O3
CXXFLAGS := -I$(SRCDIR)/kiwi -fno-rtti
F_LTO := -flto=auto
CXXFLAGS_EXTRA := -std=c++14 -Wall $(F_LTO)
#F_LTO := -flto=auto
CXXFLAGS_EXTRA := -std=c++14 -Wall $(F_LTO) -fstrict-flex-arrays=3
CFLAGS_EXTRA := -pedantic -std=c99 -Wall $(F_LTO)
LIBFLAG := -shared
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"
package = "ljkiwi"
package = "kiwi"
version = "scm-1"
source = {
url = "git+https://github.com/jkl1337/ljkiwi",
}
description = {
summary = "A LuaJIT FFI binding for the Kiwi constraint solver.",
summary = "LuaJIT FFI and Lua binding for the Kiwi constraint solver.",
detailed = [[
ljkiwi is a LuaJIT FFI binding for the Kiwi constraint solver. Kiwi is a fast
implementation of the Cassowary constraint solving algorithm. ljkiwi provides
reasonably efficient bindings using the LuaJIT FFI.]],
kiwi is a LuaJIT FFI and Lua binding for the Kiwi constraint solver. Kiwi is a fast
implementation of the Cassowary constraint solving algorithm. kiwi provides
reasonably efficient bindings using the LuaJIT FFI and convential Lua C bindings.]],
license = "MIT",
issues_url = "https://github.com/jkl1337/ljkiwi/issues",
maintainer = "John Luebs",

View File

@@ -4,21 +4,24 @@
#include <kiwi/kiwi.h>
#include <cstring>
#include <new>
#include "luacompat.h"
#define ARR_COUNT(x) ((int)(sizeof(x) / sizeof((x)[0])))
#if defined(__GNUC__) && !defined(LKIWI_NO_BUILTIN)
#define l_likely(x) (__builtin_expect(((x) != 0), 1))
#define l_unlikely(x) (__builtin_expect(((x) != 0), 0))
#define lk_likely(x) (__builtin_expect(((x) != 0), 1))
#define lk_unlikely(x) (__builtin_expect(((x) != 0), 0))
#else
#define l_likely(x) (x)
#define l_unlikely(x) (x)
#define lk_likely(x) (x)
#define lk_unlikely(x) (x)
#endif
namespace {
using namespace kiwi;
// 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
lua_Number n = lua_tonumber(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.
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");
for (; l->name != NULL; l++) { /* fill the table with given functions */
if (l->func == NULL) /* place holder? */
lua_pushboolean(L, 0);
else {
int i;
for (i = 0; i < nup; i++) /* copy upvalues to the top */
for (int i = 0; i < nup; i++) /* copy upvalues to the top */
lua_pushvalue(L, -nup);
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 */
}
#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 {
using namespace kiwi;
void newlib(lua_State* L, const luaL_Reg* l) {
lua_newtable(L);
setfuncs(L, l, 0);
}
enum KiwiErrKind {
KiwiErrNone,
@@ -80,20 +86,32 @@ struct KiwiExpression {
double constant;
int term_count;
Constraint* owner;
// https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
// Although using one-element arrays this way is discouraged, GCC handles accesses to
// trailing one-element array members analogously to zero-length arrays.
// The only reason avoiding FAM here is to support older MSVC.
// Otherwise this is a non-issue.
#if !defined(_MSC_VER) || _MSC_VER >= 1900
KiwiTerm terms[];
static constexpr std::size_t sz(int count) {
return sizeof(KiwiExpression) + sizeof(KiwiTerm) * (count > 0 ? count : 0);
}
#else
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++
// though it certainly isn't idiomatic.
// This mechanism was initially designed for LuaJIT FFI.
struct KiwiErr {
enum KiwiErrKind kind;
const char* message;
bool must_free;
bool must_delete;
};
struct KiwiSolver {
@@ -101,28 +119,27 @@ struct KiwiSolver {
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))
return base;
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) {
return base;
}
const auto* err = new (mem) KiwiErr {base->kind, mem + sizeof(KiwiErr), true};
std::memcpy(const_cast<char*>(err->message), ex.what(), msg_n);
return err;
auto* msg = mem + sizeof(KiwiErr);
std::memcpy(msg, ex.what(), msg_n);
return new (mem) KiwiErr {base->kind, msg, true};
}
const constexpr KiwiErr kKiwiErrUnhandledCxxException {
KiwiErrUnknown,
"An unhandled C++ exception occurred."};
template<typename F>
inline const KiwiErr* wrap_err(F&& f) {
static const constexpr KiwiErr kKiwiErrUnhandledCxxException {
KiwiErrUnknown,
"An unhandled C++ exception occurred."};
try {
f();
} catch (const UnsatisfiableConstraint&) {
@@ -198,12 +215,12 @@ inline Constraint* kiwi_constraint_retain(Constraint* c) {
return c;
}
inline void kiwi_constraint_new(
inline Constraint* kiwi_constraint_new(
const KiwiExpression* lhs,
const KiwiExpression* rhs,
RelationalOperator op,
double strength,
Constraint* mem
void* mem
) {
if (strength < 0.0) {
strength = kiwi::strength::required;
@@ -222,7 +239,7 @@ inline void kiwi_constraint_new(
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)),
static_cast<RelationalOperator>(op),
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 v4 = kiwi.Var("v4")
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()
print(e)
local e = c1:expression()
local s = kiwi.Solver()
s:add_constraints({ c1, c2, c1 })
print(s:dumps())
end
collectgarbage("collect")
collectgarbage("collect")
-- c = (3 * v1 + 4 * v2 + 6 * v3):eq(0)
-- local t = c:expression():terms()