huge
This commit is contained in:
@@ -65,7 +65,7 @@ PointerAlignment: Left
|
|||||||
ReferenceAlignment: Left # New in v13. int &name ==> int& name
|
ReferenceAlignment: Left # New in v13. int &name ==> int& name
|
||||||
ReflowComments: false
|
ReflowComments: false
|
||||||
SeparateDefinitionBlocks: Always # New in v14.
|
SeparateDefinitionBlocks: Always # New in v14.
|
||||||
SortIncludes: true
|
SortIncludes: false
|
||||||
SortUsingDeclarations: true
|
SortUsingDeclarations: true
|
||||||
SpaceAfterCStyleCast: false
|
SpaceAfterCStyleCast: false
|
||||||
SpaceAfterLogicalNot: false
|
SpaceAfterLogicalNot: false
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,6 +2,8 @@
|
|||||||
/lua
|
/lua
|
||||||
/lua_modules
|
/lua_modules
|
||||||
/.luarocks
|
/.luarocks
|
||||||
|
*.pch
|
||||||
|
*.gch
|
||||||
*.so
|
*.so
|
||||||
*.o
|
*.o
|
||||||
.cache/
|
.cache/
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json",
|
"$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json",
|
||||||
"runtime.version": "Lua 5.4",
|
"runtime.version": "LuaJIT",
|
||||||
"runtime.path": [
|
"runtime.path": [
|
||||||
"./?/init.lua",
|
"./?/init.lua",
|
||||||
"./?.lua",
|
"./?.lua",
|
||||||
|
|||||||
93
Makefile
93
Makefile
@@ -1,56 +1,85 @@
|
|||||||
SRCDIR := .
|
|
||||||
CC := $(CROSS)gcc
|
CC := $(CROSS)gcc
|
||||||
CFLAGS := -fPIC -O3
|
CP := cp
|
||||||
CXXFLAGS := -I$(SRCDIR)/kiwi -fno-rtti
|
RM := rm
|
||||||
#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
|
LIBFLAG := -shared
|
||||||
LIB_EXT := so
|
LIB_EXT := so
|
||||||
LUA_INCDIR := /usr/include
|
LUA_INCDIR := /usr/include
|
||||||
|
|
||||||
ifeq ($(findstring gcc,$(CC)),gcc)
|
SRCDIR := .
|
||||||
CXX := $(subst gcc,g++,$(CC))
|
|
||||||
CXXFLAGS += -std=c++14
|
OPTFLAG := -O2
|
||||||
ifneq ($(SANITIZE),)
|
CCFLAGS += $(OPTFLAG) -fPIC -Wall -fstrict-flex-arrays -fvisibility=hidden -Wformat=2 -Wconversion -Wimplicit-fallthrough
|
||||||
CFLAGS += -fsanitize=undefined -fsanitize=address
|
|
||||||
endif
|
SANITIZE_FLAGS := -fsanitize=undefined -fsanitize=address
|
||||||
|
LTO_FLAGS := -flto=auto
|
||||||
|
|
||||||
|
ifdef SANITIZE
|
||||||
|
CCFLAGS += $(SANITIZE_FLAGS)
|
||||||
|
endif
|
||||||
|
ifdef LTO
|
||||||
|
CCFLAGS += $(LTO_FLAGS)
|
||||||
|
endif
|
||||||
|
|
||||||
|
override CPPFLAGS += -I$(SRCDIR) -I$(SRCDIR)/kiwi -I$(LUA_INCDIR)
|
||||||
|
override CXXFLAGS += -std=c++14 -fno-rtti $(CCFLAGS)
|
||||||
|
override CFLAGS += -std=c99 $(CCFLAGS)
|
||||||
|
|
||||||
|
ifneq ($(filter %gcc,$(CC)),)
|
||||||
|
CXX := $(patsubst %gcc,%g++,$(CC))
|
||||||
|
PCH := ljkiwi.hpp.gch
|
||||||
else
|
else
|
||||||
ifeq ($(CC),clang)
|
ifneq ($(filter %clang,$(CC)),)
|
||||||
CXX := clang++
|
CXX := $(patsubst %clang,%clang++,$(CC))
|
||||||
CXXFLAGS += -std=c++14
|
override CXXFLAGS += -pedantic -Wno-c99-extensions
|
||||||
ifneq ($(SANITIZE),)
|
PCH := ljkiwi.hpp.pch
|
||||||
CFLAGS += -fsanitize=undefined -fsanitize=address
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
CXX := $(CC)
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
OBJS := ckiwi.o luakiwi.o
|
ifdef LUA
|
||||||
|
LUA_VERSION ?= $(lastword $(shell $(LUA) -e "print(_VERSION)"))
|
||||||
|
endif
|
||||||
|
|
||||||
VPATH = $(SRCDIR)/ckiwi $(SRCDIR)/luakiwi
|
ifndef LUA_VERSION
|
||||||
|
LJKIWI_CKIWI := 1
|
||||||
|
else
|
||||||
|
ifneq ($(LUA_VERSION),5.1)
|
||||||
|
LJKIWI_CKIWI :=
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
all: ckiwi.$(LIB_EXT)
|
OBJS := luakiwi.o
|
||||||
|
ifdef LJKIWI_CKIWI
|
||||||
|
OBJS += ckiwi.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
vpath %.cpp $(SRCDIR)/ckiwi $(SRCDIR)/luakiwi
|
||||||
|
vpath %.h $(SRCDIR)/ckiwi $(SRCDIR)/luakiwi
|
||||||
|
|
||||||
|
all: ljkiwi.$(LIB_EXT)
|
||||||
|
|
||||||
install:
|
install:
|
||||||
cp -f ckiwi.$(LIB_EXT) $(INST_LIBDIR)/ckiwi.$(LIB_EXT)
|
$(CP) -f ljkiwi.$(LIB_EXT) $(INST_LIBDIR)/ljkiwi.$(LIB_EXT)
|
||||||
cp -f kiwi.lua $(INST_LUADIR)/kiwi.lua
|
$(CP) -f kiwi.lua $(INST_LUADIR)/kiwi.lua
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f ckiwi.$(LIB_EXT) $(OBJS)
|
$(RM) -f ljkiwi.$(LIB_EXT) $(OBJS) $(PCH)
|
||||||
|
|
||||||
|
ckiwi.o: $(PCH) ckiwi.cpp ckiwi.h
|
||||||
|
luakiwi.o: $(PCH) luakiwi-int.h luacompat.h
|
||||||
|
|
||||||
ckiwi.$(LIB_EXT): $(OBJS)
|
ljkiwi.$(LIB_EXT): $(OBJS)
|
||||||
$(CXX) $(CXXFLAGS) $(CFLAGS) $(CFLAGS_EXTRA) -I$(SRCDIR)/kiwi $(LIBFLAG) -o $@ $^
|
$(CXX) $(CCFLAGS) $(LIBFLAG) -o $@ $(OBJS)
|
||||||
|
|
||||||
ckiwi.o: ckiwi.h
|
%.hpp.gch: %.hpp
|
||||||
luakiwi.o: ckiwi.h luakiwi-int.h luacompat.h
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -x c++-header -o $@ $<
|
||||||
|
|
||||||
|
%.hpp.pch: %.hpp
|
||||||
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -x c++-header -o $@ $<
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) -I$(LUA_INCDIR) $(CFLAGS) $(CFLAGS_EXTRA) -c -o $@ $<
|
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
%.o: %.cpp
|
%.o: %.cpp
|
||||||
$(CXX) -I$(LUA_INCDIR) $(CXXFLAGS) $(CFLAGS) $(CXXFLAGS_EXTRA) -c -o $@ $<
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
.PHONY: all install clean
|
.PHONY: all install clean
|
||||||
|
|||||||
416
ckiwi/ckiwi.cpp
416
ckiwi/ckiwi.cpp
@@ -1,3 +1,4 @@
|
|||||||
|
#include "ljkiwi.hpp"
|
||||||
#include "ckiwi.h"
|
#include "ckiwi.h"
|
||||||
|
|
||||||
#include <kiwi/kiwi.h>
|
#include <kiwi/kiwi.h>
|
||||||
@@ -5,99 +6,17 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
using namespace kiwi;
|
#if defined(__GNUC__) && !defined(LJKIWI_NO_BUILTIN)
|
||||||
|
#define lk_likely(x) (__builtin_expect(((x) != 0), 1))
|
||||||
|
#define lk_unlikely(x) (__builtin_expect(((x) != 0), 0))
|
||||||
|
#else
|
||||||
|
#define lk_likely(x) (x)
|
||||||
|
#define lk_unlikely(x) (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template<typename T, typename R, typename... Args>
|
using namespace kiwi;
|
||||||
inline R make_cref(Args&&... args) {
|
|
||||||
static_assert(
|
|
||||||
sizeof(R) >= sizeof(T), //NOLINT(bugprone-sizeof-expression)
|
|
||||||
"to_cref: R too small for T"
|
|
||||||
);
|
|
||||||
static_assert(alignof(R) >= alignof(T), "to_cref: R alignment too small for T");
|
|
||||||
|
|
||||||
R cref;
|
|
||||||
new (&cref) T(std::forward<Args>(args)...);
|
|
||||||
return cref;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
inline decltype(auto) make_var_cref(Args&&... args) {
|
|
||||||
return make_cref<Variable, KiwiVarRef>(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
inline decltype(auto) make_constraint_cref(Args&&... args) {
|
|
||||||
return make_cref<Constraint, KiwiConstraintRef>(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T, class R>
|
|
||||||
class SharedRef {
|
|
||||||
private:
|
|
||||||
R& cref_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit SharedRef<T, R>(R& cref) : cref_(cref) {}
|
|
||||||
|
|
||||||
static_assert(
|
|
||||||
sizeof(R) >= sizeof(T), //NOLINT(bugprone-sizeof-expression)
|
|
||||||
"SharedRef<T,CS> CS too small for T"
|
|
||||||
);
|
|
||||||
|
|
||||||
R clone() const {
|
|
||||||
return make_cref<T, R>(cref());
|
|
||||||
}
|
|
||||||
|
|
||||||
void release() {
|
|
||||||
if (cref_) {
|
|
||||||
ptr()->~T();
|
|
||||||
cref_ = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
T* ptr() {
|
|
||||||
T* p;
|
|
||||||
void* s = &cref_;
|
|
||||||
std::memcpy(&p, &s, sizeof p); //NOLINT(bugprone-sizeof-expression)
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
const T* const_ptr() const {
|
|
||||||
const T* p;
|
|
||||||
const void* s = &cref_;
|
|
||||||
std::memcpy(&p, &s, sizeof p); //NOLINT(bugprone-sizeof-expression)
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
const T& cref() const {
|
|
||||||
return *const_ptr();
|
|
||||||
}
|
|
||||||
|
|
||||||
T* operator&() const {
|
|
||||||
return ptr();
|
|
||||||
}
|
|
||||||
|
|
||||||
T* operator->() {
|
|
||||||
return ptr();
|
|
||||||
}
|
|
||||||
|
|
||||||
const T* operator->() const {
|
|
||||||
return const_ptr();
|
|
||||||
}
|
|
||||||
|
|
||||||
operator const T&() const {
|
|
||||||
return cref();
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator bool() const {
|
|
||||||
return cref_;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using ConstraintRef = SharedRef<Constraint, KiwiConstraintRef>;
|
|
||||||
using VariableRef = SharedRef<Variable, KiwiVarRef>;
|
|
||||||
using ConstVariableRef = const SharedRef<const Variable, const KiwiVarRef>;
|
|
||||||
|
|
||||||
const KiwiErr* new_error(const KiwiErr* base, const std::exception& ex) {
|
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))
|
||||||
@@ -117,18 +36,15 @@ const KiwiErr* new_error(const KiwiErr* base, const std::exception& ex) {
|
|||||||
|
|
||||||
static const constexpr KiwiErr kKiwiErrUnhandledCxxException {
|
static const constexpr KiwiErr kKiwiErrUnhandledCxxException {
|
||||||
KiwiErrUnknown,
|
KiwiErrUnknown,
|
||||||
"An unhandled C++ exception occurred."
|
"An unhandled C++ exception occurred."};
|
||||||
};
|
|
||||||
|
|
||||||
static const constexpr KiwiErr kKiwiErrNullObjectArg0 {
|
static const constexpr KiwiErr kKiwiErrNullObjectArg0 {
|
||||||
KiwiErrNullObject,
|
KiwiErrNullObject,
|
||||||
"null object passed as argument #0 (self)"
|
"null object passed as argument #0 (self)"};
|
||||||
};
|
|
||||||
|
|
||||||
static const constexpr KiwiErr kKiwiErrNullObjectArg1 {
|
static const constexpr KiwiErr kKiwiErrNullObjectArg1 {
|
||||||
KiwiErrNullObject,
|
KiwiErrNullObject,
|
||||||
"null object passed as argument #1"
|
"null object passed as argument #1"};
|
||||||
};
|
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
inline const KiwiErr* wrap_err(F&& f) {
|
inline const KiwiErr* wrap_err(F&& f) {
|
||||||
@@ -137,49 +53,42 @@ inline const KiwiErr* wrap_err(F&& f) {
|
|||||||
} catch (const UnsatisfiableConstraint& ex) {
|
} catch (const UnsatisfiableConstraint& ex) {
|
||||||
static const constexpr KiwiErr err {
|
static const constexpr KiwiErr err {
|
||||||
KiwiErrUnsatisfiableConstraint,
|
KiwiErrUnsatisfiableConstraint,
|
||||||
"The constraint cannot be satisfied."
|
"The constraint cannot be satisfied."};
|
||||||
};
|
|
||||||
return &err;
|
return &err;
|
||||||
} catch (const UnknownConstraint& ex) {
|
} catch (const UnknownConstraint& ex) {
|
||||||
static const constexpr KiwiErr err {
|
static const constexpr KiwiErr err {
|
||||||
KiwiErrUnknownConstraint,
|
KiwiErrUnknownConstraint,
|
||||||
"The constraint has not been added to the solver."
|
"The constraint has not been added to the solver."};
|
||||||
};
|
|
||||||
return &err;
|
return &err;
|
||||||
|
|
||||||
} catch (const DuplicateConstraint& ex) {
|
} catch (const DuplicateConstraint& ex) {
|
||||||
static const constexpr KiwiErr err {
|
static const constexpr KiwiErr err {
|
||||||
KiwiErrDuplicateConstraint,
|
KiwiErrDuplicateConstraint,
|
||||||
"The constraint has already been added to the solver."
|
"The constraint has already been added to the solver."};
|
||||||
};
|
|
||||||
return &err;
|
return &err;
|
||||||
|
|
||||||
} catch (const UnknownEditVariable& ex) {
|
} catch (const UnknownEditVariable& ex) {
|
||||||
static const constexpr KiwiErr err {
|
static const constexpr KiwiErr err {
|
||||||
KiwiErrUnknownEditVariable,
|
KiwiErrUnknownEditVariable,
|
||||||
"The edit variable has not been added to the solver."
|
"The edit variable has not been added to the solver."};
|
||||||
};
|
|
||||||
return &err;
|
return &err;
|
||||||
|
|
||||||
} catch (const DuplicateEditVariable& ex) {
|
} catch (const DuplicateEditVariable& ex) {
|
||||||
static const constexpr KiwiErr err {
|
static const constexpr KiwiErr err {
|
||||||
KiwiErrDuplicateEditVariable,
|
KiwiErrDuplicateEditVariable,
|
||||||
"The edit variable has already been added to the solver."
|
"The edit variable has already been added to the solver."};
|
||||||
};
|
|
||||||
return &err;
|
return &err;
|
||||||
|
|
||||||
} catch (const BadRequiredStrength& ex) {
|
} catch (const BadRequiredStrength& ex) {
|
||||||
static const constexpr KiwiErr err {
|
static const constexpr KiwiErr err {
|
||||||
KiwiErrBadRequiredStrength,
|
KiwiErrBadRequiredStrength,
|
||||||
"A required strength cannot be used in this context."
|
"A required strength cannot be used in this context."};
|
||||||
};
|
|
||||||
return &err;
|
return &err;
|
||||||
|
|
||||||
} catch (const InternalSolverError& ex) {
|
} catch (const InternalSolverError& ex) {
|
||||||
static const constexpr KiwiErr base {
|
static const constexpr KiwiErr base {
|
||||||
KiwiErrInternalSolverError,
|
KiwiErrInternalSolverError,
|
||||||
"An internal solver error occurred."
|
"An internal solver error occurred."};
|
||||||
};
|
|
||||||
return new_error(&base, ex);
|
return new_error(&base, ex);
|
||||||
} catch (std::bad_alloc&) {
|
} catch (std::bad_alloc&) {
|
||||||
static const constexpr KiwiErr err {KiwiErrAlloc, "A memory allocation failed."};
|
static const constexpr KiwiErr err {KiwiErrAlloc, "A memory allocation failed."};
|
||||||
@@ -193,82 +102,96 @@ inline const KiwiErr* wrap_err(F&& f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename P, typename R, typename F>
|
template<typename P, typename R, typename F>
|
||||||
inline const KiwiErr* wrap_err(P ptr, F&& f) {
|
inline const KiwiErr* wrap_err(P self, F&& f) {
|
||||||
if (!ptr) {
|
if (lk_unlikely(!self)) {
|
||||||
return &kKiwiErrNullObjectArg0;
|
return &kKiwiErrNullObjectArg0;
|
||||||
}
|
}
|
||||||
return wrap_err([&]() { f(ptr); });
|
return wrap_err([&]() { f(self->solver); });
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename P, typename R, typename F>
|
template<typename P, typename R, typename F>
|
||||||
inline const KiwiErr* wrap_err(P ptr, R ref, F&& f) {
|
inline const KiwiErr* wrap_err(P self, R item, F&& f) {
|
||||||
if (!ptr) {
|
if (lk_unlikely(!self)) {
|
||||||
return &kKiwiErrNullObjectArg0;
|
return &kKiwiErrNullObjectArg0;
|
||||||
} else if (!ref) {
|
} else if (lk_unlikely(!item)) {
|
||||||
return &kKiwiErrNullObjectArg1;
|
return &kKiwiErrNullObjectArg1;
|
||||||
}
|
}
|
||||||
return wrap_err([&]() { f(ptr, ref); });
|
return wrap_err([&]() { f(self->solver, *item); });
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
KiwiVarRef kiwi_var_new(const char* name) {
|
KiwiTypeInfo kiwi_ti_KiwiVar = {sizeof(KiwiVar), alignof(KiwiVar)};
|
||||||
return make_var_cref(name ? name : "");
|
KiwiTypeInfo kiwi_ti_KiwiConstraint = {sizeof(KiwiConstraint), alignof(KiwiConstraint)};
|
||||||
|
|
||||||
|
void kiwi_var_construct(const char* name, void* mem) {
|
||||||
|
new (mem) KiwiVar {lk_likely(name) ? name : ""};
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiwi_var_del(KiwiVarRef var) {
|
void kiwi_var_release(KiwiVar* var) {
|
||||||
VariableRef(var).release();
|
if (lk_likely(var))
|
||||||
|
var->~KiwiVar();
|
||||||
}
|
}
|
||||||
|
|
||||||
KiwiVarRef kiwi_var_clone(KiwiVarRef var) {
|
void kiwi_var_retain(KiwiVar* var) {
|
||||||
return VariableRef(var).clone();
|
if (lk_likely(var)) {
|
||||||
}
|
alignas(KiwiVar) unsigned char buf[sizeof(KiwiVar)];
|
||||||
|
new (buf) KiwiVar(*var);
|
||||||
const char* kiwi_var_name(KiwiVarRef var) {
|
|
||||||
const VariableRef self(var);
|
|
||||||
return self ? self->name().c_str() : "(<null>)";
|
|
||||||
}
|
|
||||||
|
|
||||||
void kiwi_var_set_name(KiwiVarRef var, const char* name) {
|
|
||||||
VariableRef self(var);
|
|
||||||
if (self)
|
|
||||||
self->setName(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
double kiwi_var_value(KiwiVarRef var) {
|
|
||||||
const VariableRef self(var);
|
|
||||||
return self ? self->value() : std::numeric_limits<double>::quiet_NaN();
|
|
||||||
}
|
|
||||||
|
|
||||||
void kiwi_var_set_value(KiwiVarRef var, double value) {
|
|
||||||
VariableRef self(var);
|
|
||||||
if (self)
|
|
||||||
self->setValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool kiwi_var_eq(KiwiVarRef var, KiwiVarRef other) {
|
|
||||||
ConstVariableRef self(var); // const defect in upstream
|
|
||||||
const VariableRef other_ref(other);
|
|
||||||
|
|
||||||
return self && other_ref && self->equals(other_ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
void kiwi_expression_del_vars(KiwiExpression* expr) {
|
|
||||||
if (!expr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (auto* t = expr->terms; t != expr->terms + expr->term_count; ++t) {
|
|
||||||
VariableRef(t->var).release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KiwiConstraintRef kiwi_constraint_new(
|
const char* kiwi_var_name(const KiwiVar* var) {
|
||||||
|
return lk_likely(var) ? var->name().c_str() : "(<null>)";
|
||||||
|
}
|
||||||
|
|
||||||
|
void kiwi_var_set_name(KiwiVar* var, const char* name) {
|
||||||
|
if (lk_likely(var))
|
||||||
|
var->setName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
double kiwi_var_value(const KiwiVar* var) {
|
||||||
|
return lk_likely(var) ? var->value() : std::numeric_limits<double>::quiet_NaN();
|
||||||
|
}
|
||||||
|
|
||||||
|
void kiwi_var_set_value(KiwiVar* var, double value) {
|
||||||
|
if (lk_likely(var))
|
||||||
|
var->setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool kiwi_var_eq(const KiwiVar* var, const KiwiVar* other) {
|
||||||
|
return lk_likely(var && other) && var->equals(*other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kiwi_expression_retain(KiwiExpression* expr) {
|
||||||
|
if (lk_unlikely(!expr))
|
||||||
|
return;
|
||||||
|
alignas(KiwiVar) unsigned char buf[sizeof(KiwiVar)];
|
||||||
|
for (auto* t = expr->terms_; t != expr->terms_ + expr->term_count; ++t) {
|
||||||
|
new (buf) KiwiVar(*t->var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kiwi_expression_destroy(KiwiExpression* expr) {
|
||||||
|
if (lk_unlikely(!expr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (expr->owner) {
|
||||||
|
expr->owner->~KiwiConstraint();
|
||||||
|
} else {
|
||||||
|
for (auto* t = expr->terms_; t != expr->terms_ + expr->term_count; ++t) {
|
||||||
|
t->var->~KiwiVar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kiwi_constraint_construct(
|
||||||
const KiwiExpression* lhs,
|
const KiwiExpression* lhs,
|
||||||
const KiwiExpression* rhs,
|
const KiwiExpression* rhs,
|
||||||
enum KiwiRelOp op,
|
enum KiwiRelOp op,
|
||||||
double strength
|
double strength,
|
||||||
|
void* mem
|
||||||
) {
|
) {
|
||||||
if (strength < 0.0) {
|
if (strength < 0.0) {
|
||||||
strength = kiwi::strength::required;
|
strength = kiwi::strength::required;
|
||||||
@@ -278,69 +201,69 @@ KiwiConstraintRef kiwi_constraint_new(
|
|||||||
terms.reserve((lhs ? lhs->term_count : 0) + (rhs ? rhs->term_count : 0));
|
terms.reserve((lhs ? lhs->term_count : 0) + (rhs ? rhs->term_count : 0));
|
||||||
|
|
||||||
if (lhs) {
|
if (lhs) {
|
||||||
for (auto* t = lhs->terms; t != lhs->terms + lhs->term_count; ++t) {
|
for (auto* t = lhs->terms_; t != lhs->terms_ + lhs->term_count; ++t) {
|
||||||
ConstVariableRef var(t->var);
|
if (t->var)
|
||||||
if (var)
|
terms.emplace_back(*t->var, t->coefficient);
|
||||||
terms.emplace_back(var.cref(), t->coefficient);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rhs) {
|
if (rhs) {
|
||||||
for (auto* t = rhs->terms; t != rhs->terms + rhs->term_count; ++t) {
|
for (auto* t = rhs->terms_; t != rhs->terms_ + rhs->term_count; ++t) {
|
||||||
ConstVariableRef var(t->var);
|
if (t->var)
|
||||||
if (var)
|
terms.emplace_back(*t->var, -t->coefficient);
|
||||||
terms.emplace_back(var.cref(), -t->coefficient);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return make_constraint_cref(
|
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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiwi_constraint_del(KiwiConstraintRef constraint) {
|
void kiwi_constraint_release(KiwiConstraint* c) {
|
||||||
ConstraintRef(constraint).release();
|
if (lk_likely(c))
|
||||||
|
c->~KiwiConstraint();
|
||||||
}
|
}
|
||||||
|
|
||||||
KiwiConstraintRef kiwi_constraint_clone(KiwiConstraintRef constraint) {
|
void kiwi_constraint_retain(KiwiConstraint* c) {
|
||||||
return ConstraintRef(constraint).clone();
|
if (lk_likely(c)) {
|
||||||
}
|
alignas(KiwiConstraint) unsigned char buf[sizeof(KiwiConstraint)];
|
||||||
|
new (buf) KiwiConstraint(*c);
|
||||||
double kiwi_constraint_strength(KiwiConstraintRef constraint) {
|
|
||||||
const ConstraintRef self(constraint);
|
|
||||||
return self ? self->strength() : std::numeric_limits<double>::quiet_NaN();
|
|
||||||
}
|
|
||||||
|
|
||||||
enum KiwiRelOp kiwi_constraint_op(KiwiConstraintRef constraint) {
|
|
||||||
const ConstraintRef self(constraint);
|
|
||||||
return self ? static_cast<KiwiRelOp>(self->op()) : KiwiRelOp::KIWI_OP_EQ;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool kiwi_constraint_violated(KiwiConstraintRef constraint) {
|
|
||||||
const ConstraintRef self(constraint);
|
|
||||||
return self ? self->violated() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int kiwi_constraint_expression(KiwiConstraintRef constraint, KiwiExpression* out, int out_size) {
|
|
||||||
const ConstraintRef self(constraint);
|
|
||||||
if (!self)
|
|
||||||
return 0;
|
|
||||||
const auto& expr = self->expression();
|
|
||||||
const auto& terms = expr.terms();
|
|
||||||
const int n_terms = terms.size();
|
|
||||||
if (!out || out_size < n_terms)
|
|
||||||
return n_terms;
|
|
||||||
|
|
||||||
auto* p = out->terms;
|
|
||||||
for (const auto& t : terms) {
|
|
||||||
*p = KiwiTerm {make_var_cref(t.variable()), t.coefficient()};
|
|
||||||
++p;
|
|
||||||
}
|
}
|
||||||
out->term_count = p - out->terms;
|
}
|
||||||
out->constant = expr.constant();
|
|
||||||
|
|
||||||
return n_terms;
|
double kiwi_constraint_strength(const KiwiConstraint* c) {
|
||||||
|
return lk_likely(c) ? c->strength() : std::numeric_limits<double>::quiet_NaN();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum KiwiRelOp kiwi_constraint_op(const KiwiConstraint* c) {
|
||||||
|
return lk_likely(c) ? static_cast<KiwiRelOp>(c->op()) : KiwiRelOp::KIWI_OP_EQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool kiwi_constraint_violated(const KiwiConstraint* c) {
|
||||||
|
return lk_likely(c) ? c->violated() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int kiwi_constraint_expression(KiwiConstraint* c, KiwiExpression* out, int out_size) {
|
||||||
|
if (lk_unlikely(!c))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const auto& expr = c->expression();
|
||||||
|
const auto& terms = expr.terms();
|
||||||
|
const auto term_count = static_cast<int>(terms.size());
|
||||||
|
if (!out || out_size < term_count)
|
||||||
|
return term_count;
|
||||||
|
|
||||||
|
for (int i = 0; i < term_count; ++i) {
|
||||||
|
out->terms_[i].var = const_cast<KiwiVar*>(&terms[i].variable());
|
||||||
|
out->terms_[i].coefficient = terms[i].coefficient();
|
||||||
|
}
|
||||||
|
out->constant = expr.constant();
|
||||||
|
out->term_count = term_count;
|
||||||
|
out->owner = c;
|
||||||
|
kiwi_constraint_retain(c);
|
||||||
|
|
||||||
|
return term_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct KiwiSolver {
|
struct KiwiSolver {
|
||||||
@@ -348,79 +271,80 @@ struct KiwiSolver {
|
|||||||
Solver solver;
|
Solver solver;
|
||||||
};
|
};
|
||||||
|
|
||||||
KiwiSolver* kiwi_solver_new(unsigned error_mask) {
|
KiwiTypeInfo kiwi_ti_KiwiSolver = {sizeof(KiwiSolver), alignof(KiwiSolver)};
|
||||||
return new KiwiSolver {error_mask};
|
|
||||||
|
void kiwi_solver_construct(unsigned error_mask, void* mem) {
|
||||||
|
new (mem) KiwiSolver {error_mask};
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiwi_solver_del(KiwiSolver* s) {
|
void kiwi_solver_destroy(KiwiSolver* s) {
|
||||||
if (s)
|
if (lk_likely(s))
|
||||||
delete s;
|
s->~KiwiSolver();
|
||||||
}
|
}
|
||||||
|
|
||||||
const KiwiErr* kiwi_solver_add_constraint(KiwiSolver* s, KiwiConstraintRef constraint) {
|
unsigned kiwi_solver_get_error_mask(const KiwiSolver* s) {
|
||||||
return wrap_err(s, ConstraintRef(constraint), [](auto* s, const auto c) {
|
return lk_likely(s) ? s->error_mask : 0;
|
||||||
s->solver.addConstraint(c);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const KiwiErr* kiwi_solver_remove_constraint(KiwiSolver* s, KiwiConstraintRef constraint) {
|
void kiwi_solver_set_error_mask(KiwiSolver* s, unsigned mask) {
|
||||||
return wrap_err(s, ConstraintRef(constraint), [](auto* s, const auto c) {
|
if (lk_likely(s))
|
||||||
s->solver.removeConstraint(c);
|
s->error_mask = mask;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool kiwi_solver_has_constraint(const KiwiSolver* s, KiwiConstraintRef constraint) {
|
const KiwiErr* kiwi_solver_add_constraint(KiwiSolver* s, const KiwiConstraint* constraint) {
|
||||||
ConstraintRef c(constraint);
|
return wrap_err(s, constraint, [](auto& s, const auto& c) { s.addConstraint(c); });
|
||||||
if (!s || !c)
|
}
|
||||||
|
|
||||||
|
const KiwiErr* kiwi_solver_remove_constraint(KiwiSolver* s, const KiwiConstraint* constraint) {
|
||||||
|
return wrap_err(s, constraint, [](auto& s, const auto& c) { s.removeConstraint(c); });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool kiwi_solver_has_constraint(const KiwiSolver* s, const KiwiConstraint* constraint) {
|
||||||
|
if (lk_unlikely(!s || !constraint))
|
||||||
return 0;
|
return 0;
|
||||||
return s->solver.hasConstraint(c);
|
return s->solver.hasConstraint(*constraint);
|
||||||
}
|
}
|
||||||
|
|
||||||
const KiwiErr* kiwi_solver_add_edit_var(KiwiSolver* s, KiwiVarRef var, double strength) {
|
const KiwiErr* kiwi_solver_add_edit_var(KiwiSolver* s, const KiwiVar* var, double strength) {
|
||||||
return wrap_err(s, VariableRef(var), [strength](auto* s, const auto v) {
|
return wrap_err(s, var, [strength](auto& s, const auto& v) {
|
||||||
s->solver.addEditVariable(v, strength);
|
s.addEditVariable(v, strength);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const KiwiErr* kiwi_solver_remove_edit_var(KiwiSolver* s, KiwiVarRef var) {
|
const KiwiErr* kiwi_solver_remove_edit_var(KiwiSolver* s, const KiwiVar* var) {
|
||||||
return wrap_err(s, VariableRef(var), [](auto* s, const auto v) {
|
return wrap_err(s, var, [](auto& s, const auto& v) { s.removeEditVariable(v); });
|
||||||
s->solver.removeEditVariable(v);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool kiwi_solver_has_edit_var(const KiwiSolver* s, KiwiVarRef var) {
|
bool kiwi_solver_has_edit_var(const KiwiSolver* s, const KiwiVar* var) {
|
||||||
VariableRef v(var);
|
if (lk_unlikely(!s || !var))
|
||||||
if (!s || !v)
|
|
||||||
return 0;
|
return 0;
|
||||||
return s->solver.hasEditVariable(v);
|
return s->solver.hasEditVariable(*var);
|
||||||
}
|
}
|
||||||
|
|
||||||
const KiwiErr* kiwi_solver_suggest_value(KiwiSolver* s, KiwiVarRef var, double value) {
|
const KiwiErr* kiwi_solver_suggest_value(KiwiSolver* s, const KiwiVar* var, double value) {
|
||||||
return wrap_err(s, VariableRef(var), [value](auto* s, const auto v) {
|
return wrap_err(s, var, [value](auto& s, const auto& v) { s.suggestValue(v, value); });
|
||||||
s->solver.suggestValue(v, value);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiwi_solver_update_vars(KiwiSolver* s) {
|
void kiwi_solver_update_vars(KiwiSolver* s) {
|
||||||
if (s)
|
if (lk_likely(s))
|
||||||
s->solver.updateVariables();
|
s->solver.updateVariables();
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiwi_solver_reset(KiwiSolver* s) {
|
void kiwi_solver_reset(KiwiSolver* s) {
|
||||||
if (s)
|
if (lk_likely(s))
|
||||||
s->solver.reset();
|
s->solver.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiwi_solver_dump(const KiwiSolver* s) {
|
void kiwi_solver_dump(const KiwiSolver* s) {
|
||||||
if (s)
|
if (lk_likely(s))
|
||||||
s->solver.dump();
|
s->solver.dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
char* kiwi_solver_dumps(const KiwiSolver* s) {
|
char* kiwi_solver_dumps(const KiwiSolver* s) {
|
||||||
if (!s)
|
if (lk_unlikely(!s))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
const auto str = s->solver.dumps(); // upstream library defect
|
const auto& str = s->solver.dumps();
|
||||||
const auto buf_size = str.size() + 1;
|
const auto buf_size = str.size() + 1;
|
||||||
auto* buf = static_cast<char*>(std::malloc(buf_size));
|
auto* buf = static_cast<char*>(std::malloc(buf_size));
|
||||||
if (!buf)
|
if (!buf)
|
||||||
|
|||||||
122
ckiwi/ckiwi.h
122
ckiwi/ckiwi.h
@@ -1,13 +1,38 @@
|
|||||||
#ifndef KIWI_CKIWI_H_
|
#ifndef LJKIWI_CKIWI_H_
|
||||||
#define KIWI_CKIWI_H_
|
#define LJKIWI_CKIWI_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||||
extern "C" {
|
#undef LJKIWI_USE_FAM_1
|
||||||
#else
|
#else
|
||||||
#include <stdbool.h>
|
#define LJKIWI_USE_FAM_1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define KIWI_REF_ISNULL(ref) ((ref).impl_ == NULL)
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
namespace kiwi {
|
||||||
|
class Variable;
|
||||||
|
class Constraint;
|
||||||
|
} // namespace kiwi
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
typedef kiwi::Variable KiwiVar;
|
||||||
|
typedef kiwi::Constraint KiwiConstraint;
|
||||||
|
#else
|
||||||
|
typedef struct KiwiVar KiwiVar;
|
||||||
|
typedef struct KiwiConstraint KiwiConstraint;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct KiwiTypeInfo {
|
||||||
|
unsigned size;
|
||||||
|
unsigned align;
|
||||||
|
} KiwiTypeInfo;
|
||||||
|
|
||||||
|
#if __GNUC__
|
||||||
|
#pragma GCC visibility push(default)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern KiwiTypeInfo kiwi_ti_KiwiVar, kiwi_ti_KiwiConstraint, kiwi_ti_KiwiSolver;
|
||||||
|
|
||||||
// LuaJIT start
|
// LuaJIT start
|
||||||
enum KiwiErrKind {
|
enum KiwiErrKind {
|
||||||
@@ -26,18 +51,24 @@ enum KiwiErrKind {
|
|||||||
|
|
||||||
enum KiwiRelOp { KIWI_OP_LE, KIWI_OP_GE, KIWI_OP_EQ };
|
enum KiwiRelOp { KIWI_OP_LE, KIWI_OP_GE, KIWI_OP_EQ };
|
||||||
|
|
||||||
typedef struct KiwiVarRefType* KiwiVarRef;
|
|
||||||
typedef struct KiwiConstraintRefType* KiwiConstraintRef;
|
|
||||||
|
|
||||||
typedef struct KiwiTerm {
|
typedef struct KiwiTerm {
|
||||||
KiwiVarRef var;
|
KiwiVar* var;
|
||||||
double coefficient;
|
double coefficient;
|
||||||
} KiwiTerm;
|
} KiwiTerm;
|
||||||
|
|
||||||
typedef struct KiwiExpression {
|
typedef struct KiwiExpression {
|
||||||
double constant;
|
double constant;
|
||||||
int term_count;
|
int term_count;
|
||||||
KiwiTerm terms[1]; // LuaJIT: struct KiwiTerm terms_[?];
|
KiwiConstraint* owner;
|
||||||
|
|
||||||
|
#if defined(LJKIWI_LUAJIT_DEF)
|
||||||
|
KiwiTerm terms_[?];
|
||||||
|
#elif defined(LJKIWI_USE_FAM_1)
|
||||||
|
KiwiTerm terms_[1]; // LuaJIT: struct KiwiTerm terms_[?];
|
||||||
|
#else
|
||||||
|
KiwiTerm terms_[];
|
||||||
|
#endif
|
||||||
|
|
||||||
} KiwiExpression;
|
} KiwiExpression;
|
||||||
|
|
||||||
typedef struct KiwiErr {
|
typedef struct KiwiErr {
|
||||||
@@ -46,56 +77,63 @@ typedef struct KiwiErr {
|
|||||||
bool must_free;
|
bool must_free;
|
||||||
} KiwiErr;
|
} KiwiErr;
|
||||||
|
|
||||||
typedef struct KiwiSolver
|
struct KiwiSolver;
|
||||||
KiwiSolver; // LuaJIT: typedef struct { unsigned error_mask; } KiwiSolver;
|
|
||||||
KiwiVarRef kiwi_var_new(const char* name);
|
|
||||||
void kiwi_var_del(KiwiVarRef var);
|
|
||||||
KiwiVarRef kiwi_var_clone(KiwiVarRef var);
|
|
||||||
|
|
||||||
const char* kiwi_var_name(KiwiVarRef var);
|
void kiwi_var_construct(const char* name, void* mem);
|
||||||
void kiwi_var_set_name(KiwiVarRef var, const char* name);
|
void kiwi_var_release(KiwiVar* var);
|
||||||
double kiwi_var_value(KiwiVarRef var);
|
void kiwi_var_retain(KiwiVar* var);
|
||||||
void kiwi_var_set_value(KiwiVarRef var, double value);
|
|
||||||
bool kiwi_var_eq(KiwiVarRef var, KiwiVarRef other);
|
|
||||||
|
|
||||||
void kiwi_expression_del_vars(KiwiExpression* expr);
|
const char* kiwi_var_name(const KiwiVar* var);
|
||||||
|
void kiwi_var_set_name(KiwiVar* var, const char* name);
|
||||||
|
double kiwi_var_value(const KiwiVar* var);
|
||||||
|
void kiwi_var_set_value(KiwiVar* var, double value);
|
||||||
|
bool kiwi_var_eq(const KiwiVar* var, const KiwiVar* other);
|
||||||
|
|
||||||
KiwiConstraintRef kiwi_constraint_new(
|
void kiwi_expression_retain(KiwiExpression* expr);
|
||||||
|
void kiwi_expression_destroy(KiwiExpression* expr);
|
||||||
|
|
||||||
|
void kiwi_constraint_construct(
|
||||||
const KiwiExpression* lhs,
|
const KiwiExpression* lhs,
|
||||||
const KiwiExpression* rhs,
|
const KiwiExpression* rhs,
|
||||||
enum KiwiRelOp op,
|
enum KiwiRelOp op,
|
||||||
double strength
|
double strength,
|
||||||
|
void* mem
|
||||||
);
|
);
|
||||||
void kiwi_constraint_del(KiwiConstraintRef constraint);
|
void kiwi_constraint_release(KiwiConstraint* c);
|
||||||
KiwiConstraintRef kiwi_constraint_clone(KiwiConstraintRef constraint);
|
void kiwi_constraint_retain(KiwiConstraint* c);
|
||||||
|
|
||||||
double kiwi_constraint_strength(KiwiConstraintRef constraint);
|
double kiwi_constraint_strength(const KiwiConstraint* c);
|
||||||
enum KiwiRelOp kiwi_constraint_op(KiwiConstraintRef constraint);
|
enum KiwiRelOp kiwi_constraint_op(const KiwiConstraint* c);
|
||||||
bool kiwi_constraint_violated(KiwiConstraintRef constraint);
|
bool kiwi_constraint_violated(const KiwiConstraint* c);
|
||||||
int kiwi_constraint_expression(KiwiConstraintRef constraint, KiwiExpression* out, int out_size);
|
int kiwi_constraint_expression(KiwiConstraint* c, KiwiExpression* out, int out_size);
|
||||||
|
|
||||||
KiwiSolver* kiwi_solver_new(unsigned error_mask);
|
void kiwi_solver_construct(unsigned error_mask, void* mem);
|
||||||
void kiwi_solver_del(KiwiSolver* s);
|
void kiwi_solver_destroy(KiwiSolver* s);
|
||||||
|
unsigned kiwi_solver_get_error_mask(const KiwiSolver* s);
|
||||||
|
void kiwi_solver_set_error_mask(KiwiSolver* s, unsigned mask);
|
||||||
|
|
||||||
const KiwiErr* kiwi_solver_add_constraint(KiwiSolver* sp, KiwiConstraintRef constraint);
|
const KiwiErr* kiwi_solver_add_constraint(KiwiSolver* s, const KiwiConstraint* constraint);
|
||||||
const KiwiErr* kiwi_solver_remove_constraint(KiwiSolver* sp, KiwiConstraintRef constraint);
|
const KiwiErr* kiwi_solver_remove_constraint(KiwiSolver* s, const KiwiConstraint* constraint);
|
||||||
bool kiwi_solver_has_constraint(const KiwiSolver* sp, KiwiConstraintRef constraint);
|
bool kiwi_solver_has_constraint(const KiwiSolver* s, const KiwiConstraint* constraint);
|
||||||
const KiwiErr* kiwi_solver_add_edit_var(KiwiSolver* sp, KiwiVarRef var, double strength);
|
const KiwiErr* kiwi_solver_add_edit_var(KiwiSolver* s, const KiwiVar* var, double strength);
|
||||||
const KiwiErr* kiwi_solver_remove_edit_var(KiwiSolver* sp, KiwiVarRef var);
|
const KiwiErr* kiwi_solver_remove_edit_var(KiwiSolver* s, const KiwiVar* var);
|
||||||
bool kiwi_solver_has_edit_var(const KiwiSolver* sp, KiwiVarRef var);
|
bool kiwi_solver_has_edit_var(const KiwiSolver* s, const KiwiVar* var);
|
||||||
const KiwiErr* kiwi_solver_suggest_value(KiwiSolver* sp, KiwiVarRef var, double value);
|
const KiwiErr* kiwi_solver_suggest_value(KiwiSolver* s, const KiwiVar* var, double value);
|
||||||
void kiwi_solver_update_vars(KiwiSolver* sp);
|
void kiwi_solver_update_vars(KiwiSolver* sp);
|
||||||
void kiwi_solver_reset(KiwiSolver* sp);
|
void kiwi_solver_reset(KiwiSolver* sp);
|
||||||
void kiwi_solver_dump(const KiwiSolver* sp);
|
void kiwi_solver_dump(const KiwiSolver* sp);
|
||||||
char* kiwi_solver_dumps(const KiwiSolver* sp);
|
char* kiwi_solver_dumps(const KiwiSolver* sp);
|
||||||
|
|
||||||
// LuaJIT end
|
// LuaJIT end
|
||||||
|
|
||||||
|
#if __GNUC__
|
||||||
|
#pragma GCC visibility pop
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
// mode: c++
|
// mode: c++
|
||||||
// End:
|
// End:
|
||||||
#endif // KIWI_CKIWI_H_
|
#endif // LJKIWI_CKIWI_H_
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ dependencies = {
|
|||||||
build = {
|
build = {
|
||||||
type = "make",
|
type = "make",
|
||||||
build_variables = {
|
build_variables = {
|
||||||
|
LUA = "$(LUA)",
|
||||||
CFLAGS = "$(CFLAGS)",
|
CFLAGS = "$(CFLAGS)",
|
||||||
LUA_INCDIR = "$(LUA_INCDIR)",
|
LUA_INCDIR = "$(LUA_INCDIR)",
|
||||||
LIBFLAG = "$(LIBFLAG)",
|
LIBFLAG = "$(LIBFLAG)",
|
||||||
|
|||||||
264
kiwi.lua
264
kiwi.lua
@@ -4,20 +4,48 @@ local ffi
|
|||||||
do
|
do
|
||||||
local ffi_loader = package.preload["ffi"]
|
local ffi_loader = package.preload["ffi"]
|
||||||
if ffi_loader == nil then
|
if ffi_loader == nil then
|
||||||
return require("ckiwi")
|
return require("ljkiwi")
|
||||||
end
|
end
|
||||||
ffi = ffi_loader() --[[@as ffilib]]
|
ffi = ffi_loader() --[[@as ffilib]]
|
||||||
end
|
end
|
||||||
|
|
||||||
local kiwi = {}
|
local kiwi = {}
|
||||||
|
|
||||||
local ckiwi
|
local ljkiwi
|
||||||
do
|
do
|
||||||
local cpath, err = package.searchpath("ckiwi", package.cpath)
|
local cpath, err = package.searchpath("ljkiwi", package.cpath)
|
||||||
if cpath == nil then
|
if cpath == nil then
|
||||||
error("kiwi dynamic library 'ckiwi' not found\n" .. err)
|
error("kiwi dynamic library 'ljkiwi' not found\n" .. err)
|
||||||
end
|
end
|
||||||
ckiwi = ffi.load(cpath)
|
ljkiwi = ffi.load(cpath)
|
||||||
|
end
|
||||||
|
kiwi.ljkiwi = ljkiwi
|
||||||
|
|
||||||
|
ffi.cdef([[
|
||||||
|
void free(void *);
|
||||||
|
|
||||||
|
typedef struct KiwiTypeInfo {
|
||||||
|
unsigned size;
|
||||||
|
unsigned align;
|
||||||
|
} KiwiTypeInfo;
|
||||||
|
|
||||||
|
extern KiwiTypeInfo kiwi_ti_KiwiVar, kiwi_ti_KiwiConstraint, kiwi_ti_KiwiSolver;
|
||||||
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
for _, t in ipairs({ "KiwiVar", "KiwiConstraint", "KiwiSolver" }) do
|
||||||
|
local tinfo = ljkiwi[("kiwi_ti_%s"):format(t)] --[[@as any]]
|
||||||
|
ffi.cdef(
|
||||||
|
[[
|
||||||
|
typedef struct $ {
|
||||||
|
unsigned char b_[$];
|
||||||
|
} __attribute__((aligned($))) $;
|
||||||
|
]],
|
||||||
|
t,
|
||||||
|
tinfo.size,
|
||||||
|
tinfo.align,
|
||||||
|
t
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
ffi.cdef([[
|
ffi.cdef([[
|
||||||
@@ -37,17 +65,15 @@ enum KiwiErrKind {
|
|||||||
|
|
||||||
enum KiwiRelOp { LE, GE, EQ };
|
enum KiwiRelOp { LE, GE, EQ };
|
||||||
|
|
||||||
typedef struct KiwiVarRefType* KiwiVarRef;
|
|
||||||
typedef struct KiwiConstraintRefType* KiwiConstraintRef;
|
|
||||||
|
|
||||||
typedef struct KiwiTerm {
|
typedef struct KiwiTerm {
|
||||||
KiwiVarRef var;
|
KiwiVar* var;
|
||||||
double coefficient;
|
double coefficient;
|
||||||
} KiwiTerm;
|
} KiwiTerm;
|
||||||
|
|
||||||
typedef struct KiwiExpression {
|
typedef struct KiwiExpression {
|
||||||
double constant;
|
double constant;
|
||||||
int term_count;
|
int term_count;
|
||||||
|
KiwiConstraint* owner;
|
||||||
KiwiTerm terms_[?];
|
KiwiTerm terms_[?];
|
||||||
} KiwiExpression;
|
} KiwiExpression;
|
||||||
|
|
||||||
@@ -57,49 +83,52 @@ typedef struct KiwiErr {
|
|||||||
bool must_free;
|
bool must_free;
|
||||||
} KiwiErr;
|
} KiwiErr;
|
||||||
|
|
||||||
typedef struct KiwiSolver { unsigned error_mask_; } KiwiSolver;
|
struct KiwiSolver;
|
||||||
|
|
||||||
KiwiVarRef kiwi_var_new(const char* name);
|
void kiwi_var_construct(const char* name, void* mem);
|
||||||
void kiwi_var_del(KiwiVarRef var);
|
void kiwi_var_release(KiwiVar* var);
|
||||||
KiwiVarRef kiwi_var_clone(KiwiVarRef var);
|
void kiwi_var_retain(KiwiVar* var);
|
||||||
|
|
||||||
const char* kiwi_var_name(KiwiVarRef var);
|
const char* kiwi_var_name(const KiwiVar* var);
|
||||||
void kiwi_var_set_name(KiwiVarRef var, const char* name);
|
void kiwi_var_set_name(KiwiVar* var, const char* name);
|
||||||
double kiwi_var_value(KiwiVarRef var);
|
double kiwi_var_value(const KiwiVar* var);
|
||||||
void kiwi_var_set_value(KiwiVarRef var, double value);
|
void kiwi_var_set_value(KiwiVar* var, double value);
|
||||||
bool kiwi_var_eq(KiwiVarRef var, KiwiVarRef other);
|
bool kiwi_var_eq(const KiwiVar* var, const KiwiVar* other);
|
||||||
|
|
||||||
void kiwi_expression_del_vars(KiwiExpression* expr);
|
void kiwi_expression_retain(KiwiExpression* expr);
|
||||||
|
void kiwi_expression_destroy(KiwiExpression* expr);
|
||||||
|
|
||||||
KiwiConstraintRef kiwi_constraint_new(
|
void kiwi_constraint_construct(
|
||||||
const KiwiExpression* lhs,
|
const KiwiExpression* lhs,
|
||||||
const KiwiExpression* rhs,
|
const KiwiExpression* rhs,
|
||||||
enum KiwiRelOp op,
|
enum KiwiRelOp op,
|
||||||
double strength
|
double strength,
|
||||||
|
void* mem
|
||||||
);
|
);
|
||||||
void kiwi_constraint_del(KiwiConstraintRef constraint);
|
void kiwi_constraint_release(KiwiConstraint* c);
|
||||||
|
void kiwi_constraint_retain(KiwiConstraint* c);
|
||||||
|
|
||||||
double kiwi_constraint_strength(KiwiConstraintRef constraint);
|
double kiwi_constraint_strength(const KiwiConstraint* c);
|
||||||
enum KiwiRelOp kiwi_constraint_op(KiwiConstraintRef constraint);
|
enum KiwiRelOp kiwi_constraint_op(const KiwiConstraint* c);
|
||||||
bool kiwi_constraint_violated(KiwiConstraintRef constraint);
|
bool kiwi_constraint_violated(const KiwiConstraint* c);
|
||||||
int kiwi_constraint_expression(KiwiConstraintRef constraint, KiwiExpression* out, int out_size);
|
int kiwi_constraint_expression(KiwiConstraint* c, KiwiExpression* out, int out_size);
|
||||||
|
|
||||||
KiwiSolver* kiwi_solver_new(unsigned error_mask);
|
void kiwi_solver_construct(unsigned error_mask, void* mem);
|
||||||
void kiwi_solver_del(KiwiSolver* s);
|
void kiwi_solver_destroy(KiwiSolver* s);
|
||||||
|
unsigned kiwi_solver_get_error_mask(const KiwiSolver* s);
|
||||||
|
void kiwi_solver_set_error_mask(KiwiSolver* s, unsigned mask);
|
||||||
|
|
||||||
const KiwiErr* kiwi_solver_add_constraint(KiwiSolver* sp, KiwiConstraintRef constraint);
|
const KiwiErr* kiwi_solver_add_constraint(KiwiSolver* s, const KiwiConstraint* constraint);
|
||||||
const KiwiErr* kiwi_solver_remove_constraint(KiwiSolver* sp, KiwiConstraintRef constraint);
|
const KiwiErr* kiwi_solver_remove_constraint(KiwiSolver* s, const KiwiConstraint* constraint);
|
||||||
bool kiwi_solver_has_constraint(const KiwiSolver* sp, KiwiConstraintRef constraint);
|
bool kiwi_solver_has_constraint(const KiwiSolver* s, const KiwiConstraint* constraint);
|
||||||
const KiwiErr* kiwi_solver_add_edit_var(KiwiSolver* sp, KiwiVarRef var, double strength);
|
const KiwiErr* kiwi_solver_add_edit_var(KiwiSolver* s, const KiwiVar* var, double strength);
|
||||||
const KiwiErr* kiwi_solver_remove_edit_var(KiwiSolver* sp, KiwiVarRef var);
|
const KiwiErr* kiwi_solver_remove_edit_var(KiwiSolver* s, const KiwiVar* var);
|
||||||
bool kiwi_solver_has_edit_var(const KiwiSolver* sp, KiwiVarRef var);
|
bool kiwi_solver_has_edit_var(const KiwiSolver* s, const KiwiVar* var);
|
||||||
const KiwiErr* kiwi_solver_suggest_value(KiwiSolver* sp, KiwiVarRef var, double value);
|
const KiwiErr* kiwi_solver_suggest_value(KiwiSolver* s, const KiwiVar* var, double value);
|
||||||
void kiwi_solver_update_vars(KiwiSolver* sp);
|
void kiwi_solver_update_vars(KiwiSolver* sp);
|
||||||
void kiwi_solver_reset(KiwiSolver* sp);
|
void kiwi_solver_reset(KiwiSolver* sp);
|
||||||
void kiwi_solver_dump(const KiwiSolver* sp);
|
void kiwi_solver_dump(const KiwiSolver* sp);
|
||||||
char* kiwi_solver_dumps(const KiwiSolver* sp);
|
char* kiwi_solver_dumps(const KiwiSolver* sp);
|
||||||
|
|
||||||
void free(void *);
|
|
||||||
]])
|
]])
|
||||||
|
|
||||||
local strformat = string.format
|
local strformat = string.format
|
||||||
@@ -159,7 +188,7 @@ do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local Var = ffi.typeof("struct KiwiVarRefType") --[[@as kiwi.Var]]
|
local Var = ffi.typeof("struct KiwiVar") --[[@as kiwi.Var]]
|
||||||
kiwi.Var = Var
|
kiwi.Var = Var
|
||||||
|
|
||||||
function kiwi.is_var(o)
|
function kiwi.is_var(o)
|
||||||
@@ -173,14 +202,14 @@ function kiwi.is_term(o)
|
|||||||
return ffi_istype(Term, o)
|
return ffi_istype(Term, o)
|
||||||
end
|
end
|
||||||
|
|
||||||
local Expression = ffi.typeof("struct KiwiExpression") --[[@as kiwi.Expression]]
|
local Expression = ffi.typeof("KiwiExpression") --[[@as kiwi.Expression]]
|
||||||
kiwi.Expression = Expression
|
kiwi.Expression = Expression
|
||||||
|
|
||||||
function kiwi.is_expression(o)
|
function kiwi.is_expression(o)
|
||||||
return ffi_istype(Expression, o)
|
return ffi_istype(Expression, o)
|
||||||
end
|
end
|
||||||
|
|
||||||
local Constraint = ffi.typeof("struct KiwiConstraintRefType") --[[@as kiwi.Constraint]]
|
local Constraint = ffi.typeof("KiwiConstraint") --[[@as kiwi.Constraint]]
|
||||||
kiwi.Constraint = Constraint
|
kiwi.Constraint = Constraint
|
||||||
|
|
||||||
function kiwi.is_constraint(o)
|
function kiwi.is_constraint(o)
|
||||||
@@ -192,18 +221,19 @@ end
|
|||||||
---@param coeff number?
|
---@param coeff number?
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
local function add_expr_term(expr, var, coeff)
|
local function add_expr_term(expr, var, coeff)
|
||||||
local ret = ffi_gc(ffi_new(Expression, expr.term_count + 1), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
local ret = ffi_gc(ffi_new(Expression, expr.term_count + 1), ljkiwi.kiwi_expression_destroy) --[[@as kiwi.Expression]]
|
||||||
for i = 0, expr.term_count - 1 do
|
for i = 0, expr.term_count - 1 do
|
||||||
local st = expr.terms_[i] --[[@as kiwi.Term]]
|
local st = expr.terms_[i] --[[@as kiwi.Term]]
|
||||||
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
||||||
dt.var = ckiwi.kiwi_var_clone(st.var)
|
dt.var = st.var
|
||||||
dt.coefficient = st.coefficient
|
dt.coefficient = st.coefficient
|
||||||
end
|
end
|
||||||
local dt = ret.terms_[expr.term_count]
|
local dt = ret.terms_[expr.term_count]
|
||||||
dt.var = ckiwi.kiwi_var_clone(var)
|
dt.var = var
|
||||||
dt.coefficient = coeff or 1.0
|
dt.coefficient = coeff or 1.0
|
||||||
ret.constant = expr.constant
|
ret.constant = expr.constant
|
||||||
ret.term_count = expr.term_count + 1
|
ret.term_count = expr.term_count + 1
|
||||||
|
ljkiwi.kiwi_expression_retain(ret)
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -212,12 +242,13 @@ end
|
|||||||
---@param coeff number?
|
---@param coeff number?
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
local function new_expr_one(constant, var, coeff)
|
local function new_expr_one(constant, var, coeff)
|
||||||
local ret = ffi_gc(ffi_new(Expression, 1), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
local ret = ffi_gc(ffi_new(Expression, 1), ljkiwi.kiwi_expression_destroy) --[[@as kiwi.Expression]]
|
||||||
local dt = ret.terms_[0]
|
local dt = ret.terms_[0]
|
||||||
dt.var = ckiwi.kiwi_var_clone(var)
|
dt.var = var
|
||||||
dt.coefficient = coeff or 1.0
|
dt.coefficient = coeff or 1.0
|
||||||
ret.constant = constant
|
ret.constant = constant
|
||||||
ret.term_count = 1
|
ret.term_count = 1
|
||||||
|
ljkiwi.kiwi_var_retain(var)
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -228,15 +259,16 @@ end
|
|||||||
---@param coeff2 number?
|
---@param coeff2 number?
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
local function new_expr_pair(constant, var1, var2, coeff1, coeff2)
|
local function new_expr_pair(constant, var1, var2, coeff1, coeff2)
|
||||||
local ret = ffi_gc(ffi_new(Expression, 2), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
local ret = ffi_gc(ffi_new(Expression, 2), ljkiwi.kiwi_expression_destroy) --[[@as kiwi.Expression]]
|
||||||
local dt = ret.terms_[0]
|
local dt = ret.terms_[0]
|
||||||
dt.var = ckiwi.kiwi_var_clone(var1)
|
dt.var = var1
|
||||||
dt.coefficient = coeff1 or 1.0
|
dt.coefficient = coeff1 or 1.0
|
||||||
dt = ret.terms_[1]
|
dt = ret.terms_[1]
|
||||||
dt.var = ckiwi.kiwi_var_clone(var2)
|
dt.var = var2
|
||||||
dt.coefficient = coeff2 or 1.0
|
dt.coefficient = coeff2 or 1.0
|
||||||
ret.constant = constant
|
ret.constant = constant
|
||||||
ret.term_count = 2
|
ret.term_count = 2
|
||||||
|
ljkiwi.kiwi_expression_retain(ret)
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -311,7 +343,9 @@ local function rel(lhs, rhs, op, strength)
|
|||||||
op_error(lhs, rhs, OP_NAMES[op])
|
op_error(lhs, rhs, OP_NAMES[op])
|
||||||
end
|
end
|
||||||
|
|
||||||
return ffi_gc(ckiwi.kiwi_constraint_new(el, er, op, strength or REQUIRED), ckiwi.kiwi_constraint_del) --[[@as kiwi.Constraint]]
|
local c = ffi_new(Constraint)
|
||||||
|
ljkiwi.kiwi_constraint_construct(el, er, op, strength or REQUIRED, c)
|
||||||
|
return ffi_gc(c, ljkiwi.kiwi_constraint_release) --[[@as kiwi.Constraint]]
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Define a constraint with expressions as `a <= b`.
|
--- Define a constraint with expressions as `a <= b`.
|
||||||
@@ -357,22 +391,22 @@ do
|
|||||||
|
|
||||||
--- Change the name of the variable.
|
--- Change the name of the variable.
|
||||||
---@type fun(self: kiwi.Var, name: string)
|
---@type fun(self: kiwi.Var, name: string)
|
||||||
set_name = ckiwi.kiwi_var_set_name,
|
set_name = ljkiwi.kiwi_var_set_name,
|
||||||
|
|
||||||
--- Get the current value of the variable.
|
--- Get the current value of the variable.
|
||||||
---@type fun(self: kiwi.Var): number
|
---@type fun(self: kiwi.Var): number
|
||||||
value = ckiwi.kiwi_var_value,
|
value = ljkiwi.kiwi_var_value,
|
||||||
|
|
||||||
--- Set the value of the variable.
|
--- Set the value of the variable.
|
||||||
---@type fun(self: kiwi.Var, value: number)
|
---@type fun(self: kiwi.Var, value: number)
|
||||||
set = ckiwi.kiwi_var_set_value,
|
set = ljkiwi.kiwi_var_set_value,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Get the name of the variable.
|
--- Get the name of the variable.
|
||||||
---@return string
|
---@return string
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function Var_cls:name()
|
function Var_cls:name()
|
||||||
return ffi_string(ckiwi.kiwi_var_name(self))
|
return ffi_string(ljkiwi.kiwi_var_name(self))
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Create a term from this variable.
|
--- Create a term from this variable.
|
||||||
@@ -397,7 +431,9 @@ do
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Var_mt:__new(name)
|
function Var_mt:__new(name)
|
||||||
return ffi_gc(ckiwi.kiwi_var_new(name), ckiwi.kiwi_var_del)
|
local v = ffi_new(self)
|
||||||
|
ljkiwi.kiwi_var_construct(name, v)
|
||||||
|
return ffi_gc(v, ljkiwi.kiwi_var_release)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Var_mt.__mul(a, b)
|
function Var_mt.__mul(a, b)
|
||||||
@@ -441,6 +477,10 @@ do
|
|||||||
return a + -b
|
return a + -b
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Var_mt:__eq(other)
|
||||||
|
return ljkiwi.kiwi_var_eq(self, other)
|
||||||
|
end
|
||||||
|
|
||||||
function Var_mt:__tostring()
|
function Var_mt:__tostring()
|
||||||
return self:name() .. "(" .. self:value() .. ")"
|
return self:name() .. "(" .. self:value() .. ")"
|
||||||
end
|
end
|
||||||
@@ -482,11 +522,13 @@ do
|
|||||||
local Term_mt = { __index = Term_cls }
|
local Term_mt = { __index = Term_cls }
|
||||||
|
|
||||||
local function term_gc(term)
|
local function term_gc(term)
|
||||||
ckiwi.kiwi_var_del(term.var)
|
ljkiwi.kiwi_var_release(term.var)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Term_mt.__new(T, var, coefficient)
|
function Term_mt.__new(T, var, coefficient)
|
||||||
return ffi_gc(ffi_new(T, ckiwi.kiwi_var_clone(var), coefficient or 1.0), term_gc)
|
local t = ffi_gc(ffi_new(T, var, coefficient or 1.0), term_gc)
|
||||||
|
ljkiwi.kiwi_var_retain(var)
|
||||||
|
return t
|
||||||
end
|
end
|
||||||
|
|
||||||
function Term_mt.__mul(a, b)
|
function Term_mt.__mul(a, b)
|
||||||
@@ -542,6 +584,7 @@ do
|
|||||||
---@class kiwi.Expression: ffi.cdata*
|
---@class kiwi.Expression: ffi.cdata*
|
||||||
---@overload fun(constant: number, ...: kiwi.Term): kiwi.Expression
|
---@overload fun(constant: number, ...: kiwi.Term): kiwi.Expression
|
||||||
---@field constant number
|
---@field constant number
|
||||||
|
---@field package owner ffi.cdata*
|
||||||
---@field package term_count number
|
---@field package term_count number
|
||||||
---@field package terms_ ffi.cdata*
|
---@field package terms_ ffi.cdata*
|
||||||
---@operator mul(number): kiwi.Expression
|
---@operator mul(number): kiwi.Expression
|
||||||
@@ -559,15 +602,16 @@ do
|
|||||||
---@param constant number
|
---@param constant number
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
local function mul_expr_coeff(expr, constant)
|
local function mul_expr_coeff(expr, constant)
|
||||||
local ret = ffi_gc(ffi_new(Expression, expr.term_count), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
local ret = ffi_gc(ffi_new(Expression, expr.term_count), ljkiwi.kiwi_expression_destroy) --[[@as kiwi.Expression]]
|
||||||
for i = 0, expr.term_count - 1 do
|
for i = 0, expr.term_count - 1 do
|
||||||
local st = expr.terms_[i] --[[@as kiwi.Term]]
|
local st = expr.terms_[i] --[[@as kiwi.Term]]
|
||||||
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
||||||
dt.var = ckiwi.kiwi_var_clone(st.var)
|
dt.var = st.var
|
||||||
dt.coefficient = st.coefficient * constant
|
dt.coefficient = st.coefficient * constant
|
||||||
end
|
end
|
||||||
ret.constant = expr.constant * constant
|
ret.constant = expr.constant * constant
|
||||||
ret.term_count = expr.term_count
|
ret.term_count = expr.term_count
|
||||||
|
ljkiwi.kiwi_expression_retain(ret)
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -577,22 +621,23 @@ do
|
|||||||
local function add_expr_expr(a, b)
|
local function add_expr_expr(a, b)
|
||||||
local a_count = a.term_count
|
local a_count = a.term_count
|
||||||
local b_count = b.term_count
|
local b_count = b.term_count
|
||||||
local ret = ffi_gc(ffi_new(Expression, a_count + b_count), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
local ret = ffi_gc(ffi_new(Expression, a_count + b_count), ljkiwi.kiwi_expression_destroy) --[[@as kiwi.Expression]]
|
||||||
|
|
||||||
for i = 0, a_count - 1 do
|
for i = 0, a_count - 1 do
|
||||||
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
||||||
local st = a.terms_[i] --[[@as kiwi.Term]]
|
local st = a.terms_[i] --[[@as kiwi.Term]]
|
||||||
dt.var = ckiwi.kiwi_var_clone(st.var)
|
dt.var = st.var
|
||||||
dt.coefficient = st.coefficient
|
dt.coefficient = st.coefficient
|
||||||
end
|
end
|
||||||
for i = 0, b_count - 1 do
|
for i = 0, b_count - 1 do
|
||||||
local dt = ret.terms_[a_count + i] --[[@as kiwi.Term]]
|
local dt = ret.terms_[a_count + i] --[[@as kiwi.Term]]
|
||||||
local st = b.terms_[i] --[[@as kiwi.Term]]
|
local st = b.terms_[i] --[[@as kiwi.Term]]
|
||||||
dt.var = ckiwi.kiwi_var_clone(st.var)
|
dt.var = st.var
|
||||||
dt.coefficient = st.coefficient
|
dt.coefficient = st.coefficient
|
||||||
end
|
end
|
||||||
ret.constant = a.constant + b.constant
|
ret.constant = a.constant + b.constant
|
||||||
ret.term_count = a_count + b_count
|
ret.term_count = a_count + b_count
|
||||||
|
ljkiwi.kiwi_expression_retain(ret)
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -600,16 +645,17 @@ do
|
|||||||
---@param constant number
|
---@param constant number
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
local function new_expr_constant(expr, constant)
|
local function new_expr_constant(expr, constant)
|
||||||
local ret = ffi_gc(ffi_new(Expression, expr.term_count), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
local ret = ffi_gc(ffi_new(Expression, expr.term_count), ljkiwi.kiwi_expression_destroy) --[[@as kiwi.Expression]]
|
||||||
|
|
||||||
for i = 0, expr.term_count - 1 do
|
for i = 0, expr.term_count - 1 do
|
||||||
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
||||||
local st = expr.terms_[i] --[[@as kiwi.Term]]
|
local st = expr.terms_[i] --[[@as kiwi.Term]]
|
||||||
dt.var = ckiwi.kiwi_var_clone(st.var)
|
dt.var = st.var
|
||||||
dt.coefficient = st.coefficient
|
dt.coefficient = st.coefficient
|
||||||
end
|
end
|
||||||
ret.constant = constant
|
ret.constant = constant
|
||||||
ret.term_count = expr.term_count
|
ret.term_count = expr.term_count
|
||||||
|
ljkiwi.kiwi_expression_retain(ret)
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -645,17 +691,18 @@ do
|
|||||||
__index = Expression_cls,
|
__index = Expression_cls,
|
||||||
}
|
}
|
||||||
|
|
||||||
function Expression_mt.__new(T, constant, ...)
|
function Expression_mt:__new(constant, ...)
|
||||||
local term_count = select("#", ...)
|
local term_count = select("#", ...)
|
||||||
local e = ffi_gc(ffi_new(T, term_count), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
local e = ffi_gc(ffi_new(self, term_count), ljkiwi.kiwi_expression_destroy) --[[@as kiwi.Expression]]
|
||||||
e.term_count = term_count
|
e.term_count = term_count
|
||||||
e.constant = constant
|
e.constant = constant
|
||||||
for i = 1, term_count do
|
for i = 1, term_count do
|
||||||
local t = select(i, ...)
|
local t = select(i, ...)
|
||||||
local dt = e.terms_[i - 1] --[[@as kiwi.Term]]
|
local dt = e.terms_[i - 1] --[[@as kiwi.Term]]
|
||||||
dt.var = ckiwi.kiwi_var_clone(t.var)
|
dt.var = t.var
|
||||||
dt.coefficient = t.coefficient
|
dt.coefficient = t.coefficient
|
||||||
end
|
end
|
||||||
|
ljkiwi.kiwi_expression_retain(e)
|
||||||
return e
|
return e
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -722,29 +769,29 @@ do
|
|||||||
local Constraint_cls = {
|
local Constraint_cls = {
|
||||||
--- The strength of the constraint.
|
--- The strength of the constraint.
|
||||||
---@type fun(self: kiwi.Constraint): number
|
---@type fun(self: kiwi.Constraint): number
|
||||||
strength = ckiwi.kiwi_constraint_strength,
|
strength = ljkiwi.kiwi_constraint_strength,
|
||||||
|
|
||||||
--- The relational operator of the constraint.
|
--- The relational operator of the constraint.
|
||||||
---@type fun(self: kiwi.Constraint): kiwi.RelOp
|
---@type fun(self: kiwi.Constraint): kiwi.RelOp
|
||||||
op = ckiwi.kiwi_constraint_op,
|
op = ljkiwi.kiwi_constraint_op,
|
||||||
|
|
||||||
--- Whether the constraint is violated in the current solution.
|
--- Whether the constraint is violated in the current solution.
|
||||||
---@type fun(self: kiwi.Constraint): boolean
|
---@type fun(self: kiwi.Constraint): boolean
|
||||||
violated = ckiwi.kiwi_constraint_violated,
|
violated = ljkiwi.kiwi_constraint_violated,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- The reduced expression defining the constraint.
|
--- The reduced expression defining the constraint.
|
||||||
---@return kiwi.Expression
|
---@return kiwi.Expression
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function Constraint_cls:expression()
|
function Constraint_cls:expression()
|
||||||
local SZ = 7 -- 2**7 bytes on x64
|
local SZ = 7
|
||||||
local expr = ffi_new(Expression, SZ) --[[@as kiwi.Expression]]
|
local expr = ffi_new(Expression, SZ) --[[@as kiwi.Expression]]
|
||||||
local n = ckiwi.kiwi_constraint_expression(self, expr, SZ)
|
local n = ljkiwi.kiwi_constraint_expression(self, expr, SZ)
|
||||||
if n > SZ then
|
if n > SZ then
|
||||||
expr = ffi_new(Expression, n) --[[@as kiwi.Expression]]
|
expr = ffi_new(Expression, n) --[[@as kiwi.Expression]]
|
||||||
n = ckiwi.kiwi_constraint_expression(self, expr, n)
|
n = ljkiwi.kiwi_constraint_expression(self, expr, n)
|
||||||
end
|
end
|
||||||
return ffi_gc(expr, ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
return ffi_gc(expr, ljkiwi.kiwi_expression_destroy) --[[@as kiwi.Expression]]
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Add the constraint to the solver.
|
--- Add the constraint to the solver.
|
||||||
@@ -773,10 +820,9 @@ do
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Constraint_mt:__new(lhs, rhs, op, strength)
|
function Constraint_mt:__new(lhs, rhs, op, strength)
|
||||||
return ffi_gc(
|
local c = ffi_new(self)
|
||||||
ckiwi.kiwi_constraint_new(lhs, rhs, op or "EQ", strength or REQUIRED),
|
ljkiwi.kiwi_constraint_construct(lhs, rhs, op or "EQ", strength or REQUIRED, c)
|
||||||
ckiwi.kiwi_constraint_del
|
return ffi_gc(c, ljkiwi.kiwi_constraint_release)
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local OPS = { [0] = "<=", ">=", "==" }
|
local OPS = { [0] = "<=", ">=", "==" }
|
||||||
@@ -822,10 +868,9 @@ do
|
|||||||
tmpexpr.constant = constant ~= nil and constant or 0
|
tmpexpr.constant = constant ~= nil and constant or 0
|
||||||
tmpexpr.term_count = 2
|
tmpexpr.term_count = 2
|
||||||
|
|
||||||
return ffi_gc(
|
local c = ffi_new(Constraint)
|
||||||
ckiwi.kiwi_constraint_new(tmpexpr, nil, op or "EQ", strength or REQUIRED),
|
ljkiwi.kiwi_constraint_construct(tmpexpr, nil, op or "EQ", strength or REQUIRED, c)
|
||||||
ckiwi.kiwi_constraint_del
|
return ffi_gc(c, ljkiwi.kiwi_constraint_release) --[[@as kiwi.Constraint]]
|
||||||
) --[[@as kiwi.Constraint]]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local pair_ratio = constraints.pair_ratio
|
local pair_ratio = constraints.pair_ratio
|
||||||
@@ -858,10 +903,10 @@ do
|
|||||||
local t = tmpexpr.terms_[0]
|
local t = tmpexpr.terms_[0]
|
||||||
t.var = var
|
t.var = var
|
||||||
t.coefficient = 1.0
|
t.coefficient = 1.0
|
||||||
return ffi_gc(
|
|
||||||
ckiwi.kiwi_constraint_new(tmpexpr, nil, op or "EQ", strength or REQUIRED),
|
local c = ffi_new(Constraint)
|
||||||
ckiwi.kiwi_constraint_del
|
ljkiwi.kiwi_constraint_construct(tmpexpr, nil, op or "EQ", strength or REQUIRED, c)
|
||||||
) --[[@as kiwi.Constraint]]
|
return ffi_gc(c, ljkiwi.kiwi_constraint_release) --[[@as kiwi.Constraint]]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -947,7 +992,7 @@ do
|
|||||||
C.free(err)
|
C.free(err)
|
||||||
end
|
end
|
||||||
local errdata = new_error(kind, message, solver, item)
|
local errdata = new_error(kind, message, solver, item)
|
||||||
local error_mask = solver and solver.error_mask_ or 0
|
local error_mask = ljkiwi.kiwi_solver_get_error_mask(solver)
|
||||||
return item,
|
return item,
|
||||||
band(error_mask, lshift(1, kind --[[@as integer]])) == 0 and error(errdata)
|
band(error_mask, lshift(1, kind --[[@as integer]])) == 0 and error(errdata)
|
||||||
or errdata
|
or errdata
|
||||||
@@ -955,20 +1000,19 @@ do
|
|||||||
return item
|
return item
|
||||||
end
|
end
|
||||||
---@class kiwi.Solver: ffi.cdata*
|
---@class kiwi.Solver: ffi.cdata*
|
||||||
---@field package error_mask_ integer
|
|
||||||
---@overload fun(error_mask: (integer|(kiwi.ErrKind|integer)[] )?): kiwi.Solver
|
---@overload fun(error_mask: (integer|(kiwi.ErrKind|integer)[] )?): kiwi.Solver
|
||||||
local Solver_cls = {
|
local Solver_cls = {
|
||||||
--- Test whether a constraint is in the solver.
|
--- Test whether a constraint is in the solver.
|
||||||
---@type fun(self: kiwi.Solver, constraint: kiwi.Constraint): boolean
|
---@type fun(self: kiwi.Solver, constraint: kiwi.Constraint): boolean
|
||||||
has_constraint = ckiwi.kiwi_solver_has_constraint,
|
has_constraint = ljkiwi.kiwi_solver_has_constraint,
|
||||||
|
|
||||||
--- Test whether an edit variable has been added to the solver.
|
--- Test whether an edit variable has been added to the solver.
|
||||||
---@type fun(self: kiwi.Solver, var: kiwi.Var): boolean
|
---@type fun(self: kiwi.Solver, var: kiwi.Var): boolean
|
||||||
has_edit_var = ckiwi.kiwi_solver_has_edit_var,
|
has_edit_var = ljkiwi.kiwi_solver_has_edit_var,
|
||||||
|
|
||||||
--- Update the values of the external solver variables.
|
--- Update the values of the external solver variables.
|
||||||
---@type fun(self: kiwi.Solver)
|
---@type fun(self: kiwi.Solver)
|
||||||
update_vars = ckiwi.kiwi_solver_update_vars,
|
update_vars = ljkiwi.kiwi_solver_update_vars,
|
||||||
|
|
||||||
--- Reset the solver to the empty starting conditions.
|
--- Reset the solver to the empty starting conditions.
|
||||||
---
|
---
|
||||||
@@ -978,11 +1022,11 @@ do
|
|||||||
--- when the entire system must change, since it can avoid unecessary
|
--- when the entire system must change, since it can avoid unecessary
|
||||||
--- heap (de)allocations.
|
--- heap (de)allocations.
|
||||||
---@type fun(self: kiwi.Solver)
|
---@type fun(self: kiwi.Solver)
|
||||||
reset = ckiwi.kiwi_solver_reset,
|
reset = ljkiwi.kiwi_solver_reset,
|
||||||
|
|
||||||
--- Dump a representation of the solver to stdout.
|
--- Dump a representation of the solver to stdout.
|
||||||
---@type fun(self: kiwi.Solver)
|
---@type fun(self: kiwi.Solver)
|
||||||
dump = ckiwi.kiwi_solver_dump,
|
dump = ljkiwi.kiwi_solver_dump,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Sets the error mask for the solver.
|
--- Sets the error mask for the solver.
|
||||||
@@ -992,7 +1036,7 @@ do
|
|||||||
if type(mask) == "table" then
|
if type(mask) == "table" then
|
||||||
mask = kiwi.error_mask(mask, invert)
|
mask = kiwi.error_mask(mask, invert)
|
||||||
end
|
end
|
||||||
self.error_mask_ = mask
|
ljkiwi.kiwi_solver_set_error_mask(self, mask)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@generic T
|
---@generic T
|
||||||
@@ -1017,7 +1061,7 @@ do
|
|||||||
---@param constraint kiwi.Constraint
|
---@param constraint kiwi.Constraint
|
||||||
---@return kiwi.Constraint constraint, kiwi.Error?
|
---@return kiwi.Constraint constraint, kiwi.Error?
|
||||||
function Solver_cls:add_constraint(constraint)
|
function Solver_cls:add_constraint(constraint)
|
||||||
return try_solver(ckiwi.kiwi_solver_add_constraint, self, constraint)
|
return try_solver(ljkiwi.kiwi_solver_add_constraint, self, constraint)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Add constraints to the solver.
|
--- Add constraints to the solver.
|
||||||
@@ -1027,7 +1071,7 @@ do
|
|||||||
---@param constraints kiwi.Constraint[]
|
---@param constraints kiwi.Constraint[]
|
||||||
---@return kiwi.Constraint[] constraints, kiwi.Error?
|
---@return kiwi.Constraint[] constraints, kiwi.Error?
|
||||||
function Solver_cls:add_constraints(constraints)
|
function Solver_cls:add_constraints(constraints)
|
||||||
return add_remove_items(self, constraints, ckiwi.kiwi_solver_add_constraint)
|
return add_remove_items(self, constraints, ljkiwi.kiwi_solver_add_constraint)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Remove a constraint from the solver.
|
--- Remove a constraint from the solver.
|
||||||
@@ -1036,7 +1080,7 @@ do
|
|||||||
---@param constraint kiwi.Constraint
|
---@param constraint kiwi.Constraint
|
||||||
---@return kiwi.Constraint constraint, kiwi.Error?
|
---@return kiwi.Constraint constraint, kiwi.Error?
|
||||||
function Solver_cls:remove_constraint(constraint)
|
function Solver_cls:remove_constraint(constraint)
|
||||||
return try_solver(ckiwi.kiwi_solver_remove_constraint, self, constraint)
|
return try_solver(ljkiwi.kiwi_solver_remove_constraint, self, constraint)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Remove constraints from the solver.
|
--- Remove constraints from the solver.
|
||||||
@@ -1045,7 +1089,7 @@ do
|
|||||||
---@param constraints kiwi.Constraint[]
|
---@param constraints kiwi.Constraint[]
|
||||||
---@return kiwi.Constraint[] constraints, kiwi.Error?
|
---@return kiwi.Constraint[] constraints, kiwi.Error?
|
||||||
function Solver_cls:remove_constraints(constraints)
|
function Solver_cls:remove_constraints(constraints)
|
||||||
return add_remove_items(self, constraints, ckiwi.kiwi_solver_remove_constraint)
|
return add_remove_items(self, constraints, ljkiwi.kiwi_solver_remove_constraint)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Add an edit variables to the solver.
|
--- Add an edit variables to the solver.
|
||||||
@@ -1059,7 +1103,7 @@ do
|
|||||||
---@param strength number the strength of the edit variable (must be less than `Strength.REQUIRED`)
|
---@param strength number the strength of the edit variable (must be less than `Strength.REQUIRED`)
|
||||||
---@return kiwi.Var var, kiwi.Error?
|
---@return kiwi.Var var, kiwi.Error?
|
||||||
function Solver_cls:add_edit_var(var, strength)
|
function Solver_cls:add_edit_var(var, strength)
|
||||||
return try_solver(ckiwi.kiwi_solver_add_edit_var, self, var, strength)
|
return try_solver(ljkiwi.kiwi_solver_add_edit_var, self, var, strength)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Add edit variables to the solver.
|
--- Add edit variables to the solver.
|
||||||
@@ -1073,7 +1117,7 @@ do
|
|||||||
---@param strength number the strength of the edit variables (must be less than `Strength.REQUIRED`)
|
---@param strength number the strength of the edit variables (must be less than `Strength.REQUIRED`)
|
||||||
---@return kiwi.Var[] vars, kiwi.Error?
|
---@return kiwi.Var[] vars, kiwi.Error?
|
||||||
function Solver_cls:add_edit_vars(vars, strength)
|
function Solver_cls:add_edit_vars(vars, strength)
|
||||||
return add_remove_items(self, vars, ckiwi.kiwi_solver_add_edit_var, strength)
|
return add_remove_items(self, vars, ljkiwi.kiwi_solver_add_edit_var, strength)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Remove an edit variable from the solver.
|
--- Remove an edit variable from the solver.
|
||||||
@@ -1082,7 +1126,7 @@ do
|
|||||||
---@param var kiwi.Var the edit variable to remove
|
---@param var kiwi.Var the edit variable to remove
|
||||||
---@return kiwi.Var var, kiwi.Error?
|
---@return kiwi.Var var, kiwi.Error?
|
||||||
function Solver_cls:remove_edit_var(var)
|
function Solver_cls:remove_edit_var(var)
|
||||||
return try_solver(ckiwi.kiwi_solver_remove_edit_var, self, var)
|
return try_solver(ljkiwi.kiwi_solver_remove_edit_var, self, var)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Removes edit variables from the solver.
|
--- Removes edit variables from the solver.
|
||||||
@@ -1091,7 +1135,7 @@ do
|
|||||||
---@param vars kiwi.Var[] the edit variables to remove
|
---@param vars kiwi.Var[] the edit variables to remove
|
||||||
---@return kiwi.Var[] vars, kiwi.Error?
|
---@return kiwi.Var[] vars, kiwi.Error?
|
||||||
function Solver_cls:remove_edit_vars(vars)
|
function Solver_cls:remove_edit_vars(vars)
|
||||||
return add_remove_items(self, vars, ckiwi.kiwi_solver_remove_edit_var)
|
return add_remove_items(self, vars, ljkiwi.kiwi_solver_remove_edit_var)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Suggest a value for the given edit variable.
|
--- Suggest a value for the given edit variable.
|
||||||
@@ -1104,7 +1148,7 @@ do
|
|||||||
---@param value number the suggested value
|
---@param value number the suggested value
|
||||||
---@return kiwi.Var var, kiwi.Error?
|
---@return kiwi.Var var, kiwi.Error?
|
||||||
function Solver_cls:suggest_value(var, value)
|
function Solver_cls:suggest_value(var, value)
|
||||||
return try_solver(ckiwi.kiwi_solver_suggest_value, self, var, value)
|
return try_solver(ljkiwi.kiwi_solver_suggest_value, self, var, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Suggest values for the given edit variables.
|
--- Suggest values for the given edit variables.
|
||||||
@@ -1116,7 +1160,7 @@ do
|
|||||||
---@return kiwi.Var[] vars, number[] values, kiwi.Error?
|
---@return kiwi.Var[] vars, number[] values, kiwi.Error?
|
||||||
function Solver_cls:suggest_values(vars, values)
|
function Solver_cls:suggest_values(vars, values)
|
||||||
for i, var in ipairs(vars) do
|
for i, var in ipairs(vars) do
|
||||||
local _, err = try_solver(ckiwi.kiwi_solver_suggest_value, self, var, values[i])
|
local _, err = try_solver(ljkiwi.kiwi_solver_suggest_value, self, var, values[i])
|
||||||
if err ~= nil then
|
if err ~= nil then
|
||||||
return vars, values, err
|
return vars, values, err
|
||||||
end
|
end
|
||||||
@@ -1128,7 +1172,7 @@ do
|
|||||||
---@return string
|
---@return string
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function Solver_cls:dumps()
|
function Solver_cls:dumps()
|
||||||
local cs = ckiwi.kiwi_solver_dumps(self)
|
local cs = ljkiwi.kiwi_solver_dumps(self)
|
||||||
local s = ffi_string(cs)
|
local s = ffi_string(cs)
|
||||||
C.free(cs)
|
C.free(cs)
|
||||||
return s
|
return s
|
||||||
@@ -1138,17 +1182,23 @@ do
|
|||||||
__index = Solver_cls,
|
__index = Solver_cls,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local Solver = ffi.typeof("struct KiwiSolver") --[[@as kiwi.Solver]]
|
||||||
|
kiwi.Solver = Solver
|
||||||
|
|
||||||
function Solver_mt:__new(error_mask)
|
function Solver_mt:__new(error_mask)
|
||||||
if type(error_mask) == "table" then
|
if type(error_mask) == "table" then
|
||||||
error_mask = kiwi.error_mask(error_mask)
|
error_mask = kiwi.error_mask(error_mask)
|
||||||
end
|
end
|
||||||
return ffi_gc(ckiwi.kiwi_solver_new(error_mask or 0), ckiwi.kiwi_solver_del)
|
|
||||||
|
local s = ffi_new(Solver)
|
||||||
|
ljkiwi.kiwi_solver_construct(error_mask or 0, s)
|
||||||
|
return ffi_gc(s, ljkiwi.kiwi_solver_destroy) --[[@as kiwi.Constraint]]
|
||||||
end
|
end
|
||||||
|
|
||||||
kiwi.Solver = ffi.metatype("struct KiwiSolver", Solver_mt) --[[@as kiwi.Solver]]
|
kiwi.Solver = ffi.metatype(Solver, Solver_mt) --[[@as kiwi.Solver]]
|
||||||
|
|
||||||
function kiwi.is_solver(s)
|
function kiwi.is_solver(s)
|
||||||
return ffi_istype(kiwi.Solver, s)
|
return ffi_istype(Solver, s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
37
ljkiwi.def
Normal file
37
ljkiwi.def
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
EXPORTS
|
||||||
|
luaopen_ljkiwi
|
||||||
|
|
||||||
|
kiwi_ti_KiwiVar
|
||||||
|
kiwi_ti_KiwiConstraint
|
||||||
|
kiwi_ti_KiwiSolver
|
||||||
|
|
||||||
|
kiwi_constraint_construct
|
||||||
|
kiwi_constraint_expression
|
||||||
|
kiwi_constraint_op
|
||||||
|
kiwi_constraint_release
|
||||||
|
kiwi_constraint_retain
|
||||||
|
kiwi_constraint_strength
|
||||||
|
kiwi_constraint_violated
|
||||||
|
kiwi_expression_destroy
|
||||||
|
kiwi_solver_add_constraint
|
||||||
|
kiwi_solver_add_edit_var
|
||||||
|
kiwi_solver_construct
|
||||||
|
kiwi_solver_destroy
|
||||||
|
kiwi_solver_dump
|
||||||
|
kiwi_solver_dumps
|
||||||
|
kiwi_solver_has_constraint
|
||||||
|
kiwi_solver_has_edit_var
|
||||||
|
kiwi_solver_remove_constraint
|
||||||
|
kiwi_solver_remove_edit_var
|
||||||
|
kiwi_solver_reset
|
||||||
|
kiwi_solver_suggest_value
|
||||||
|
kiwi_solver_update_vars
|
||||||
|
kiwi_var_construct
|
||||||
|
kiwi_var_destroy
|
||||||
|
kiwi_var_eq
|
||||||
|
kiwi_var_name
|
||||||
|
kiwi_var_release
|
||||||
|
kiwi_var_retain
|
||||||
|
kiwi_var_set_name
|
||||||
|
kiwi_var_set_value
|
||||||
|
kiwi_var_value
|
||||||
1
ljkiwi.hpp
Normal file
1
ljkiwi.hpp
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#include <kiwi/kiwi.h>
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
EXPORTS
|
|
||||||
luaopen_ckiwi
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
AccessModifierOffset: -2
|
|
||||||
AlignAfterOpenBracket: BlockIndent # New in v14. For earlier clang-format versions, use AlwaysBreak instead.
|
|
||||||
AlignConsecutiveMacros: false
|
|
||||||
AlignConsecutiveAssignments: false
|
|
||||||
AlignConsecutiveDeclarations: false
|
|
||||||
AlignEscapedNewlines: DontAlign
|
|
||||||
AlignOperands: false
|
|
||||||
AlignTrailingComments: false
|
|
||||||
AllowAllArgumentsOnNextLine: false
|
|
||||||
AllowAllConstructorInitializersOnNextLine: false
|
|
||||||
AllowAllParametersOfDeclarationOnNextLine: false
|
|
||||||
AllowShortBlocksOnASingleLine: Empty
|
|
||||||
AllowShortCaseLabelsOnASingleLine: false
|
|
||||||
AllowShortFunctionsOnASingleLine: Empty
|
|
||||||
AllowShortIfStatementsOnASingleLine: Never
|
|
||||||
AllowShortLambdasOnASingleLine: All
|
|
||||||
AllowShortLoopsOnASingleLine: false
|
|
||||||
AlwaysBreakAfterReturnType: None
|
|
||||||
AlwaysBreakBeforeMultilineStrings: true
|
|
||||||
AlwaysBreakTemplateDeclarations: Yes
|
|
||||||
BinPackArguments: false
|
|
||||||
BinPackParameters: false
|
|
||||||
BreakAfterAttributes: Always
|
|
||||||
BreakBeforeBinaryOperators: NonAssignment
|
|
||||||
BreakBeforeBraces: Attach
|
|
||||||
BreakBeforeTernaryOperators: true
|
|
||||||
BreakConstructorInitializers: AfterColon
|
|
||||||
BreakInheritanceList: AfterColon
|
|
||||||
BreakStringLiterals: false
|
|
||||||
ColumnLimit: 98
|
|
||||||
CompactNamespaces: false
|
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
|
||||||
ConstructorInitializerIndentWidth: 4
|
|
||||||
ContinuationIndentWidth: 4
|
|
||||||
Cpp11BracedListStyle: true
|
|
||||||
DerivePointerAlignment: false
|
|
||||||
FixNamespaceComments: true
|
|
||||||
IncludeBlocks: Regroup
|
|
||||||
IncludeCategories:
|
|
||||||
- Regex: '^<ext/.*\.h>'
|
|
||||||
Priority: 2
|
|
||||||
SortPriority: 0
|
|
||||||
CaseSensitive: false
|
|
||||||
- Regex: '^<.*\.h>'
|
|
||||||
Priority: 1
|
|
||||||
SortPriority: 0
|
|
||||||
CaseSensitive: false
|
|
||||||
- Regex: '^<.*'
|
|
||||||
Priority: 2
|
|
||||||
SortPriority: 0
|
|
||||||
CaseSensitive: false
|
|
||||||
- Regex: '.*'
|
|
||||||
Priority: 3
|
|
||||||
SortPriority: 0
|
|
||||||
CaseSensitive: false
|
|
||||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
|
||||||
IndentCaseLabels: true
|
|
||||||
IndentPPDirectives: BeforeHash
|
|
||||||
IndentWidth: 3
|
|
||||||
IndentWrappedFunctionNames: false
|
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
|
||||||
MaxEmptyLinesToKeep: 1
|
|
||||||
NamespaceIndentation: Inner
|
|
||||||
PointerAlignment: Left
|
|
||||||
ReferenceAlignment: Left # New in v13. int &name ==> int& name
|
|
||||||
ReflowComments: false
|
|
||||||
SeparateDefinitionBlocks: Always # New in v14.
|
|
||||||
SortIncludes: true
|
|
||||||
SortUsingDeclarations: true
|
|
||||||
SpaceAfterCStyleCast: false
|
|
||||||
SpaceAfterLogicalNot: false
|
|
||||||
SpaceAfterTemplateKeyword: false
|
|
||||||
SpaceBeforeAssignmentOperators: true
|
|
||||||
SpaceBeforeCpp11BracedList: true
|
|
||||||
SpaceBeforeCtorInitializerColon: true
|
|
||||||
SpaceBeforeInheritanceColon: false
|
|
||||||
SpaceBeforeParens: ControlStatements
|
|
||||||
SpaceBeforeRangeBasedForLoopColon: true
|
|
||||||
SpaceInEmptyParentheses: false
|
|
||||||
SpacesBeforeTrailingComments: 2
|
|
||||||
SpacesInAngles: false
|
|
||||||
SpacesInCStyleCastParentheses: false
|
|
||||||
SpacesInContainerLiterals: false
|
|
||||||
SpacesInParentheses: false
|
|
||||||
SpacesInSquareBrackets: false
|
|
||||||
Standard: Cpp11
|
|
||||||
TabWidth: 4
|
|
||||||
UseTab: Never
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "luacompat.h"
|
#include "luacompat.h"
|
||||||
|
|
||||||
#if defined(__GNUC__) && !defined(LKIWI_NO_BUILTIN)
|
#if defined(__GNUC__) && !defined(LJKIWI_NO_BUILTIN)
|
||||||
#define lk_likely(x) (__builtin_expect(((x) != 0), 1))
|
#define lk_likely(x) (__builtin_expect(((x) != 0), 1))
|
||||||
#define lk_unlikely(x) (__builtin_expect(((x) != 0), 0))
|
#define lk_unlikely(x) (__builtin_expect(((x) != 0), 0))
|
||||||
#else
|
#else
|
||||||
@@ -58,7 +58,7 @@ constexpr int array_count(T (&)[N]) {
|
|||||||
return static_cast<int>(N);
|
return static_cast<int>(N);
|
||||||
}
|
}
|
||||||
|
|
||||||
void newlib(lua_State* L, const luaL_Reg* l) {
|
inline void newlib(lua_State* L, const luaL_Reg* l) {
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
setfuncs(L, l, 0);
|
setfuncs(L, l, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include "ljkiwi.hpp"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -955,7 +956,7 @@ int lkiwi_constraint_expression(lua_State* L) {
|
|||||||
auto* c = get_constraint(L, 1);
|
auto* c = get_constraint(L, 1);
|
||||||
const auto& expr = c->expression();
|
const auto& expr = c->expression();
|
||||||
const auto& terms = expr.terms();
|
const auto& terms = expr.terms();
|
||||||
const int term_count = terms.size();
|
const auto term_count = static_cast<int>(terms.size());
|
||||||
|
|
||||||
auto* ne = expr_new(L, term_count);
|
auto* ne = expr_new(L, term_count);
|
||||||
ne->owner = kiwi_constraint_retain(c);
|
ne->owner = kiwi_constraint_retain(c);
|
||||||
@@ -1562,7 +1563,7 @@ void register_type_n(
|
|||||||
const luaL_Reg* m,
|
const luaL_Reg* m,
|
||||||
size_t mcnt
|
size_t mcnt
|
||||||
) {
|
) {
|
||||||
lua_createtable(L, 0, mcnt + 2);
|
lua_createtable(L, 0, static_cast<int>(mcnt + 2));
|
||||||
lua_pushvalue(L, -2); // no_member_mt
|
lua_pushvalue(L, -2); // no_member_mt
|
||||||
lua_setmetatable(L, -2);
|
lua_setmetatable(L, -2);
|
||||||
lua_pushstring(L, name);
|
lua_pushstring(L, name);
|
||||||
@@ -1605,7 +1606,11 @@ void compat_init(lua_State*, int) {}
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
extern "C" int luaopen_ckiwi(lua_State* L) {
|
#if defined __GNUC__ && (!defined _WIN32 || defined __CYGWIN__)
|
||||||
|
#define LJKIWI_EXPORT __attribute__((__visibility__("default")))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C" LJKIWI_EXPORT int luaopen_ljkiwi(lua_State* L) {
|
||||||
luaL_checkversion(L);
|
luaL_checkversion(L);
|
||||||
|
|
||||||
/* context table */
|
/* context table */
|
||||||
|
|||||||
Reference in New Issue
Block a user