skin this cat
This commit is contained in:
4
Makefile
4
Makefile
@@ -29,7 +29,7 @@ endif
|
|||||||
|
|
||||||
OBJS := ckiwi.o luakiwi.o
|
OBJS := ckiwi.o luakiwi.o
|
||||||
|
|
||||||
VPATH = $(SRCDIR)/ckiwi
|
VPATH = $(SRCDIR)/ckiwi $(SRCDIR)/luakiwi
|
||||||
|
|
||||||
all: ckiwi.$(LIB_EXT)
|
all: ckiwi.$(LIB_EXT)
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ ckiwi.$(LIB_EXT): $(OBJS)
|
|||||||
$(CXX) $(CXXFLAGS) $(CFLAGS) $(CFLAGS_EXTRA) -I$(SRCDIR)/kiwi $(LIBFLAG) -o $@ $^
|
$(CXX) $(CXXFLAGS) $(CFLAGS) $(CFLAGS_EXTRA) -I$(SRCDIR)/kiwi $(LIBFLAG) -o $@ $^
|
||||||
|
|
||||||
ckiwi.o: ckiwi.h
|
ckiwi.o: ckiwi.h
|
||||||
luakiwi.o: ckiwi.h luakiwi-int.h luacompat.h
|
luakiwi.o: ckiwi.h kiwibridge.cpp luakiwi-int.h luacompat.h
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) -I$(LUA_INCDIR) $(CFLAGS) $(CFLAGS_EXTRA) -c -o $@ $<
|
$(CC) -I$(LUA_INCDIR) $(CFLAGS) $(CFLAGS_EXTRA) -c -o $@ $<
|
||||||
|
|||||||
1
kiwi.lua
1
kiwi.lua
@@ -78,7 +78,6 @@ KiwiConstraintRef kiwi_constraint_new(
|
|||||||
double strength
|
double strength
|
||||||
);
|
);
|
||||||
void kiwi_constraint_del(KiwiConstraintRef constraint);
|
void kiwi_constraint_del(KiwiConstraintRef constraint);
|
||||||
KiwiConstraintRef kiwi_constraint_clone(KiwiConstraintRef constraint);
|
|
||||||
|
|
||||||
double kiwi_constraint_strength(KiwiConstraintRef constraint);
|
double kiwi_constraint_strength(KiwiConstraintRef constraint);
|
||||||
enum KiwiRelOp kiwi_constraint_op(KiwiConstraintRef constraint);
|
enum KiwiRelOp kiwi_constraint_op(KiwiConstraintRef constraint);
|
||||||
|
|||||||
88
luakiwi/.clang-format
Normal file
88
luakiwi/.clang-format
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
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
|
||||||
331
luakiwi/kiwibridge.cpp
Normal file
331
luakiwi/kiwibridge.cpp
Normal file
@@ -0,0 +1,331 @@
|
|||||||
|
#include <kiwi/kiwi.h>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using namespace kiwi;
|
||||||
|
|
||||||
|
enum KiwiErrKind {
|
||||||
|
KiwiErrNone,
|
||||||
|
KiwiErrUnsatisfiableConstraint = 1,
|
||||||
|
KiwiErrUnknownConstraint,
|
||||||
|
KiwiErrDuplicateConstraint,
|
||||||
|
KiwiErrUnknownEditVariable,
|
||||||
|
KiwiErrDuplicateEditVariable,
|
||||||
|
KiwiErrBadRequiredStrength,
|
||||||
|
KiwiErrInternalSolverError,
|
||||||
|
KiwiErrAlloc,
|
||||||
|
KiwiErrNullObject,
|
||||||
|
KiwiErrUnknown,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum KiwiRelOp { KIWI_OP_LE, KIWI_OP_GE, KIWI_OP_EQ };
|
||||||
|
|
||||||
|
typedef struct KiwiVarRefType* KiwiVarRef;
|
||||||
|
typedef struct KiwiConstraintRefType* KiwiConstraintRef;
|
||||||
|
|
||||||
|
struct KiwiTerm {
|
||||||
|
Variable* var;
|
||||||
|
double coefficient;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KiwiExpression {
|
||||||
|
double constant;
|
||||||
|
int term_count;
|
||||||
|
Constraint* owner;
|
||||||
|
KiwiTerm terms[1]; // LuaJIT: struct KiwiTerm terms_[?];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KiwiErr {
|
||||||
|
enum KiwiErrKind kind;
|
||||||
|
const char* message;
|
||||||
|
bool must_free;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KiwiSolver {
|
||||||
|
unsigned error_mask;
|
||||||
|
Solver solver;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
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) {
|
||||||
|
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));
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
const constexpr KiwiErr kKiwiErrUnhandledCxxException {
|
||||||
|
KiwiErrUnknown,
|
||||||
|
"An unhandled C++ exception occurred."};
|
||||||
|
|
||||||
|
const constexpr KiwiErr kKiwiErrNullObjectArg0 {
|
||||||
|
KiwiErrNullObject,
|
||||||
|
"null object passed as argument #0 (self)"};
|
||||||
|
|
||||||
|
const constexpr KiwiErr kKiwiErrNullObjectArg1 {
|
||||||
|
KiwiErrNullObject,
|
||||||
|
"null object passed as argument #1"};
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
inline const KiwiErr* wrap_err(F&& f) {
|
||||||
|
try {
|
||||||
|
f();
|
||||||
|
} catch (const UnsatisfiableConstraint& ex) {
|
||||||
|
static const constexpr KiwiErr err {
|
||||||
|
KiwiErrUnsatisfiableConstraint,
|
||||||
|
"The constraint cannot be satisfied."};
|
||||||
|
return &err;
|
||||||
|
} catch (const UnknownConstraint& ex) {
|
||||||
|
static const constexpr KiwiErr err {
|
||||||
|
KiwiErrUnknownConstraint,
|
||||||
|
"The constraint has not been added to the solver."};
|
||||||
|
return &err;
|
||||||
|
|
||||||
|
} catch (const DuplicateConstraint& ex) {
|
||||||
|
static const constexpr KiwiErr err {
|
||||||
|
KiwiErrDuplicateConstraint,
|
||||||
|
"The constraint has already been added to the solver."};
|
||||||
|
return &err;
|
||||||
|
|
||||||
|
} catch (const UnknownEditVariable& ex) {
|
||||||
|
static const constexpr KiwiErr err {
|
||||||
|
KiwiErrUnknownEditVariable,
|
||||||
|
"The edit variable has not been added to the solver."};
|
||||||
|
return &err;
|
||||||
|
|
||||||
|
} catch (const DuplicateEditVariable& ex) {
|
||||||
|
static const constexpr KiwiErr err {
|
||||||
|
KiwiErrDuplicateEditVariable,
|
||||||
|
"The edit variable has already been added to the solver."};
|
||||||
|
return &err;
|
||||||
|
|
||||||
|
} catch (const BadRequiredStrength& ex) {
|
||||||
|
static const constexpr KiwiErr err {
|
||||||
|
KiwiErrBadRequiredStrength,
|
||||||
|
"A required strength cannot be used in this context."};
|
||||||
|
return &err;
|
||||||
|
|
||||||
|
} catch (const InternalSolverError& ex) {
|
||||||
|
static const constexpr KiwiErr base {
|
||||||
|
KiwiErrInternalSolverError,
|
||||||
|
"An internal solver error occurred."};
|
||||||
|
return new_error(&base, ex);
|
||||||
|
} catch (std::bad_alloc&) {
|
||||||
|
static const constexpr KiwiErr err {KiwiErrAlloc, "A memory allocation failed."};
|
||||||
|
return &err;
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
return new_error(&kKiwiErrUnhandledCxxException, ex);
|
||||||
|
} catch (...) {
|
||||||
|
return &kKiwiErrUnhandledCxxException;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename P, typename R, typename F>
|
||||||
|
inline const KiwiErr* wrap_err(P ptr, F&& f) {
|
||||||
|
if (!ptr) {
|
||||||
|
return &kKiwiErrNullObjectArg0;
|
||||||
|
}
|
||||||
|
return wrap_err([&]() { f(ptr); });
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename P, typename R, typename F>
|
||||||
|
inline const KiwiErr* wrap_err(P ptr, R& ref, F&& f) {
|
||||||
|
if (!ptr) {
|
||||||
|
return &kKiwiErrNullObjectArg0;
|
||||||
|
}
|
||||||
|
return wrap_err([&]() { f(ptr, ref); });
|
||||||
|
}
|
||||||
|
|
||||||
|
// inline void kiwi_var_del(KiwiVarRef var) { VariableRef(var).release(); }
|
||||||
|
|
||||||
|
inline Variable* kiwi_var_retain(Variable* var) {
|
||||||
|
alignas(Variable) unsigned char buf[sizeof(Variable)];
|
||||||
|
new (buf) Variable(*var);
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Constraint* kiwi_constraint_retain(Constraint* c) {
|
||||||
|
alignas(Constraint) unsigned char buf[sizeof(Constraint)];
|
||||||
|
new (buf) Constraint(*c);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void kiwi_constraint_new(
|
||||||
|
const KiwiExpression* lhs,
|
||||||
|
const KiwiExpression* rhs,
|
||||||
|
enum KiwiRelOp op,
|
||||||
|
double strength,
|
||||||
|
Constraint* mem
|
||||||
|
) {
|
||||||
|
if (strength < 0.0) {
|
||||||
|
strength = kiwi::strength::required;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Term> terms;
|
||||||
|
terms.reserve((lhs ? lhs->term_count : 0) + (rhs ? rhs->term_count : 0));
|
||||||
|
|
||||||
|
if (lhs) {
|
||||||
|
// FIXME FIXME: this should cause a copy!
|
||||||
|
for (auto* t = lhs->terms; t != lhs->terms + lhs->term_count; ++t) {
|
||||||
|
terms.emplace_back(*t->var, t->coefficient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rhs) {
|
||||||
|
for (auto* t = rhs->terms; t != rhs->terms + rhs->term_count; ++t) {
|
||||||
|
terms.emplace_back(*t->var, -t->coefficient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new (mem) Constraint(
|
||||||
|
Expression(std::move(terms), (lhs ? lhs->constant : 0.0) - (rhs ? rhs->constant : 0.0)),
|
||||||
|
static_cast<RelationalOperator>(op),
|
||||||
|
strength
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int kiwi_constraint_expression(const Constraint* c, KiwiExpression* out, int out_size) {
|
||||||
|
const auto& expr = c->expression();
|
||||||
|
const auto& terms = expr.terms();
|
||||||
|
const int n_terms = terms.size();
|
||||||
|
if (!out || out_size < n_terms)
|
||||||
|
return n_terms;
|
||||||
|
|
||||||
|
// FIXME FIXME FIXME: dangling pointer
|
||||||
|
auto* p = out->terms;
|
||||||
|
for (const auto& t : terms) {
|
||||||
|
Variable* v = const_cast<Variable*>(&t.variable());
|
||||||
|
*p = KiwiTerm {v, t.coefficient()};
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
out->term_count = p - out->terms;
|
||||||
|
out->constant = expr.constant();
|
||||||
|
|
||||||
|
return n_terms;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const KiwiErr* kiwi_solver_add_constraint(KiwiSolver* s, const Constraint& constraint) {
|
||||||
|
return wrap_err(s, constraint, [](auto* s, const auto& c) { s->solver.addConstraint(c); });
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const KiwiErr* kiwi_solver_remove_constraint(KiwiSolver* s, const Constraint& constraint) {
|
||||||
|
return wrap_err(s, constraint, [](auto* s, const auto& c) { s->solver.removeConstraint(c); });
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const KiwiErr*
|
||||||
|
kiwi_solver_add_edit_var(KiwiSolver* s, const Variable& var, double strength) {
|
||||||
|
return wrap_err(s, var, [strength](auto* s, const auto& v) {
|
||||||
|
s->solver.addEditVariable(v, strength);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const KiwiErr* kiwi_solver_remove_edit_var(KiwiSolver* s, const Variable& var) {
|
||||||
|
return wrap_err(s, var, [](auto* s, const auto& v) { s->solver.removeEditVariable(v); });
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const KiwiErr*
|
||||||
|
kiwi_solver_suggest_value(KiwiSolver* s, const Variable& var, double value) {
|
||||||
|
return wrap_err(s, var, [value](auto* s, const auto& v) { s->solver.suggestValue(v, value); });
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "ckiwi.h"
|
#include "kiwibridge.cpp"
|
||||||
#include "luacompat.h"
|
#include "luacompat.h"
|
||||||
#include "luakiwi-int.h"
|
#include "luakiwi-int.h"
|
||||||
|
|
||||||
@@ -144,17 +144,16 @@ static inline void* try_type(lua_State* L, int idx, enum TypeId type_id) {
|
|||||||
return lua_rawequal(L, -1, -2) ? p : 0;
|
return lua_rawequal(L, -1, -2) ? p : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline KiwiVarRef try_var(lua_State* L, int idx) {
|
static inline Variable* try_var(lua_State* L, int idx) {
|
||||||
void* p = try_type(L, idx, VAR);
|
return static_cast<Variable*>(try_type(L, idx, VAR));
|
||||||
return p ? *(KiwiVarRef*)p : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline KiwiTerm* try_term(lua_State* L, int idx) {
|
static inline KiwiTerm* try_term(lua_State* L, int idx) {
|
||||||
return (KiwiTerm*)try_type(L, idx, TERM);
|
return static_cast<KiwiTerm*>(try_type(L, idx, TERM));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline KiwiExpression* try_expr(lua_State* L, int idx) {
|
static inline KiwiExpression* try_expr(lua_State* L, int idx) {
|
||||||
return (KiwiExpression*)try_type(L, idx, EXPR);
|
return static_cast<KiwiExpression*>(try_type(L, idx, EXPR));
|
||||||
}
|
}
|
||||||
|
|
||||||
// method to test types for expression functions
|
// method to test types for expression functions
|
||||||
@@ -190,51 +189,52 @@ static inline void* try_arg(lua_State* L, int idx, enum TypeId* type_id, double*
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline KiwiVarRef get_var(lua_State* L, int idx) {
|
static inline Variable* get_var(lua_State* L, int idx) {
|
||||||
return *((KiwiVarRef*)check_arg(L, idx, VAR));
|
return static_cast<Variable*>(check_arg(L, idx, VAR));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline KiwiTerm* get_term(lua_State* L, int idx) {
|
static inline KiwiTerm* get_term(lua_State* L, int idx) {
|
||||||
return (KiwiTerm*)check_arg(L, idx, TERM);
|
return static_cast<KiwiTerm*>(check_arg(L, idx, TERM));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline KiwiExpression* get_expr(lua_State* L, int idx) {
|
static inline KiwiExpression* get_expr(lua_State* L, int idx) {
|
||||||
return (KiwiExpression*)check_arg(L, idx, EXPR);
|
return static_cast<KiwiExpression*>(check_arg(L, idx, EXPR));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline KiwiExpression* get_expr_opt(lua_State* L, int idx) {
|
static inline KiwiExpression* get_expr_opt(lua_State* L, int idx) {
|
||||||
if (lua_isnoneornil(L, idx)) {
|
if (lua_isnoneornil(L, idx)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return (KiwiExpression*)check_arg(L, idx, EXPR);
|
return static_cast<KiwiExpression*>(check_arg(L, idx, EXPR));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline KiwiConstraintRef get_constraint(lua_State* L, int idx) {
|
static inline Constraint* get_constraint(lua_State* L, int idx) {
|
||||||
return *((KiwiConstraintRef*)check_arg(L, idx, CONSTRAINT));
|
return static_cast<Constraint*>(check_arg(L, idx, CONSTRAINT));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline KiwiSolver* get_solver(lua_State* L, int idx) {
|
static inline KiwiSolver* get_solver(lua_State* L, int idx) {
|
||||||
return *(KiwiSolver**)check_arg(L, idx, SOLVER);
|
return static_cast<KiwiSolver*>(check_arg(L, idx, SOLVER));
|
||||||
}
|
}
|
||||||
|
|
||||||
// note this expects the 2nd upvalue to have the variable weak table
|
// note this expects the 2nd upvalue to have the variable weak table
|
||||||
static inline KiwiVarRef var_new(lua_State* L, KiwiVarRef var) {
|
template<typename... Args>
|
||||||
KiwiVarRef* varp = (KiwiVarRef*)lua_newuserdata(L, sizeof(KiwiVarRef));
|
static inline Variable* var_new(lua_State* L, Args&&... args) {
|
||||||
*varp = var;
|
auto* p = static_cast<Variable*>(lua_newuserdata(L, sizeof(Variable)));
|
||||||
|
new (p) Variable(std::forward<Args>(args)...);
|
||||||
|
|
||||||
push_type(L, VAR);
|
push_type(L, VAR);
|
||||||
lua_setmetatable(L, -2);
|
lua_setmetatable(L, -2);
|
||||||
|
|
||||||
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
|
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
|
||||||
// a true compatibility shim has performance implications here
|
// a true compatibility shim has performance implications here
|
||||||
lua_pushlightuserdata(L, var);
|
lua_pushlightuserdata(L, p);
|
||||||
lua_pushvalue(L, -2);
|
lua_pushvalue(L, -2);
|
||||||
lua_rawset(L, lua_upvalueindex(2));
|
lua_rawset(L, lua_upvalueindex(2));
|
||||||
#else
|
#else
|
||||||
lua_pushvalue(L, -1);
|
lua_pushvalue(L, -1);
|
||||||
lua_rawsetp(L, lua_upvalueindex(2), var);
|
lua_rawsetp(L, lua_upvalueindex(2), p);
|
||||||
#endif
|
#endif
|
||||||
return var;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline KiwiTerm* term_new(lua_State* L) {
|
static inline KiwiTerm* term_new(lua_State* L) {
|
||||||
@@ -254,19 +254,19 @@ static inline KiwiExpression* expr_new(lua_State* L, int nterms) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline KiwiConstraintRef constraint_new(
|
static inline Constraint* constraint_new(
|
||||||
lua_State* L,
|
lua_State* L,
|
||||||
const KiwiExpression* lhs,
|
const KiwiExpression* lhs,
|
||||||
const KiwiExpression* rhs,
|
const KiwiExpression* rhs,
|
||||||
enum KiwiRelOp op,
|
enum KiwiRelOp op,
|
||||||
double strength
|
double strength
|
||||||
) {
|
) {
|
||||||
KiwiConstraintRef* ref = (KiwiConstraintRef*)lua_newuserdata(L, sizeof(KiwiConstraintRef));
|
auto* ref = static_cast<Constraint*>(lua_newuserdata(L, sizeof(Constraint)));
|
||||||
*ref = kiwi_constraint_new(lhs, rhs, op, strength);
|
kiwi_constraint_new(lhs, rhs, op, strength, ref);
|
||||||
|
|
||||||
push_type(L, CONSTRAINT);
|
push_type(L, CONSTRAINT);
|
||||||
lua_setmetatable(L, -2);
|
lua_setmetatable(L, -2);
|
||||||
return *ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
// stack disposition: dirty
|
// stack disposition: dirty
|
||||||
@@ -291,7 +291,7 @@ static KiwiExpression* toexpr(lua_State* L, int idx, KiwiExpression* temp) {
|
|||||||
temp->term_count = 1;
|
temp->term_count = 1;
|
||||||
push_type(L, VAR);
|
push_type(L, VAR);
|
||||||
if (lua_rawequal(L, -1, -3)) {
|
if (lua_rawequal(L, -1, -3)) {
|
||||||
temp->terms[0].var = *(KiwiVarRef*)ud;
|
temp->terms[0].var = static_cast<Variable*>(ud);
|
||||||
temp->terms[0].coefficient = 1.0;
|
temp->terms[0].coefficient = 1.0;
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
@@ -334,7 +334,7 @@ static inline int push_expr_one(lua_State* L, double constant, const KiwiTerm* t
|
|||||||
expr->constant = constant;
|
expr->constant = constant;
|
||||||
expr->term_count = 1;
|
expr->term_count = 1;
|
||||||
expr->terms[0].coefficient = term->coefficient;
|
expr->terms[0].coefficient = term->coefficient;
|
||||||
expr->terms[0].var = kiwi_var_clone(term->var);
|
expr->terms[0].var = kiwi_var_retain(term->var);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,21 +344,21 @@ push_expr_pair(lua_State* L, double constant, const KiwiTerm* ta, const KiwiTerm
|
|||||||
e->constant = constant;
|
e->constant = constant;
|
||||||
e->term_count = 2;
|
e->term_count = 2;
|
||||||
e->terms[0].coefficient = ta->coefficient;
|
e->terms[0].coefficient = ta->coefficient;
|
||||||
e->terms[0].var = kiwi_var_clone(ta->var);
|
e->terms[0].var = kiwi_var_retain(ta->var);
|
||||||
e->terms[1].coefficient = tb->coefficient;
|
e->terms[1].coefficient = tb->coefficient;
|
||||||
e->terms[1].var = kiwi_var_clone(tb->var);
|
e->terms[1].var = kiwi_var_retain(tb->var);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
push_expr_var_term(lua_State* L, double constant, KiwiVarRef var, const KiwiTerm* t) {
|
push_expr_var_term(lua_State* L, double constant, Variable* var, const KiwiTerm* t) {
|
||||||
KiwiExpression* e = expr_new(L, 2);
|
KiwiExpression* e = expr_new(L, 2);
|
||||||
e->constant = constant;
|
e->constant = constant;
|
||||||
e->term_count = 2;
|
e->term_count = 2;
|
||||||
e->terms[0].coefficient = 1.0;
|
e->terms[0].coefficient = 1.0;
|
||||||
e->terms[0].var = kiwi_var_clone(var);
|
e->terms[0].var = kiwi_var_retain(var);
|
||||||
e->terms[1].coefficient = t->coefficient;
|
e->terms[1].coefficient = t->coefficient;
|
||||||
e->terms[1].var = kiwi_var_clone(t->var);
|
e->terms[1].var = kiwi_var_retain(t->var);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,42 +369,42 @@ static int push_add_expr_term(lua_State* L, const KiwiExpression* expr, const Ki
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
for (; i < expr->term_count; ++i) {
|
for (; i < expr->term_count; ++i) {
|
||||||
e->terms[i].coefficient = expr->terms[i].coefficient;
|
e->terms[i].coefficient = expr->terms[i].coefficient;
|
||||||
e->terms[i].var = kiwi_var_clone(expr->terms[i].var);
|
e->terms[i].var = kiwi_var_retain(expr->terms[i].var);
|
||||||
}
|
}
|
||||||
e->terms[i].coefficient = t->coefficient;
|
e->terms[i].coefficient = t->coefficient;
|
||||||
e->terms[i].var = kiwi_var_clone(t->var);
|
e->terms[i].var = kiwi_var_retain(t->var);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_var_m_add(lua_State* L) {
|
static int lkiwi_var_m_add(lua_State* L) {
|
||||||
enum TypeId type_id_b;
|
enum TypeId type_id_b;
|
||||||
double num;
|
double num;
|
||||||
const void* arg_b = try_arg(L, 2, &type_id_b, &num);
|
void* arg_b = try_arg(L, 2, &type_id_b, &num);
|
||||||
|
|
||||||
if (type_id_b == VAR) {
|
if (type_id_b == VAR) {
|
||||||
int isnum_a;
|
int isnum_a;
|
||||||
num = lua_tonumberx(L, 1, &isnum_a);
|
num = lua_tonumberx(L, 1, &isnum_a);
|
||||||
if (isnum_a) {
|
if (isnum_a) {
|
||||||
const KiwiTerm t = {*(KiwiVarRef*)arg_b, 1.0};
|
const KiwiTerm t {static_cast<Variable*>(arg_b), 1.0};
|
||||||
return push_expr_one(L, num, &t);
|
return push_expr_one(L, num, &t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KiwiVarRef var_a = try_var(L, 1);
|
Variable* var_a = try_var(L, 1);
|
||||||
if (var_a) {
|
if (var_a) {
|
||||||
switch (type_id_b) {
|
switch (type_id_b) {
|
||||||
case VAR: {
|
case VAR: {
|
||||||
const KiwiTerm ta = {var_a, 1.0}, tb = {*(KiwiVarRef*)arg_b, 1.0};
|
const KiwiTerm ta {var_a, 1.0}, tb {static_cast<Variable*>(arg_b), 1.0};
|
||||||
return push_expr_pair(L, 0.0, &ta, &tb);
|
return push_expr_pair(L, 0.0, &ta, &tb);
|
||||||
}
|
}
|
||||||
case TERM:
|
case TERM:
|
||||||
return push_expr_var_term(L, 0.0, var_a, (const KiwiTerm*)arg_b);
|
return push_expr_var_term(L, 0.0, var_a, (static_cast<KiwiTerm*>(arg_b)));
|
||||||
case EXPR: {
|
case EXPR: {
|
||||||
const KiwiTerm t = {var_a, 1.0};
|
const KiwiTerm t {var_a, 1.0};
|
||||||
return push_add_expr_term(L, (const KiwiExpression*)arg_b, &t);
|
return push_add_expr_term(L, static_cast<KiwiExpression*>(arg_b), &t);
|
||||||
}
|
}
|
||||||
case NUMBER: {
|
case NUMBER: {
|
||||||
const KiwiTerm t = {var_a, 1.0};
|
const KiwiTerm t {var_a, 1.0};
|
||||||
return push_expr_one(L, num, &t);
|
return push_expr_one(L, num, &t);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -437,10 +437,10 @@ static int lkiwi_var_m_mul(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isnum) {
|
if (isnum) {
|
||||||
KiwiVarRef var = try_var(L, varidx);
|
auto* var = try_var(L, varidx);
|
||||||
if (var) {
|
if (var) {
|
||||||
KiwiTerm* term = term_new(L);
|
auto* term = term_new(L);
|
||||||
term->var = kiwi_var_clone(var);
|
term->var = kiwi_var_retain(var);
|
||||||
term->coefficient = num;
|
term->coefficient = num;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -449,82 +449,78 @@ static int lkiwi_var_m_mul(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_var_m_div(lua_State* L) {
|
static int lkiwi_var_m_div(lua_State* L) {
|
||||||
KiwiVarRef var = try_var(L, 1);
|
auto* var = try_var(L, 1);
|
||||||
int isnum;
|
int isnum;
|
||||||
double num = lua_tonumberx(L, 2, &isnum);
|
double num = lua_tonumberx(L, 2, &isnum);
|
||||||
if (!var || !isnum) {
|
if (!var || !isnum) {
|
||||||
return op_error(L, "/", 1, 2);
|
return op_error(L, "/", 1, 2);
|
||||||
}
|
}
|
||||||
KiwiTerm* term = term_new(L);
|
KiwiTerm* term = term_new(L);
|
||||||
term->var = kiwi_var_clone(var);
|
term->var = kiwi_var_retain(var);
|
||||||
term->coefficient = 1.0 / num;
|
term->coefficient = 1.0 / num;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_var_m_unm(lua_State* L) {
|
static int lkiwi_var_m_unm(lua_State* L) {
|
||||||
KiwiVarRef var = get_var(L, 1);
|
auto* term = term_new(L);
|
||||||
KiwiTerm* term = term_new(L);
|
term->var = kiwi_var_retain(get_var(L, 1));
|
||||||
term->var = kiwi_var_clone(var);
|
|
||||||
term->coefficient = -1.0;
|
term->coefficient = -1.0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_var_m_eq(lua_State* L) {
|
static int lkiwi_var_m_eq(lua_State* L) {
|
||||||
lua_pushboolean(L, get_var(L, 1) == get_var(L, 2));
|
lua_pushboolean(L, get_var(L, 1)->equals(*get_var(L, 2)));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_var_m_tostring(lua_State* L) {
|
static int lkiwi_var_m_tostring(lua_State* L) {
|
||||||
KiwiVarRef var = get_var(L, 1);
|
auto* var = get_var(L, 1);
|
||||||
lua_pushfstring(L, "%s(%f)", kiwi_var_name(var), kiwi_var_value(var));
|
lua_pushfstring(L, "%s(%f)", var->name().c_str(), var->value());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_var_m_gc(lua_State* L) {
|
static int lkiwi_var_m_gc(lua_State* L) {
|
||||||
KiwiVarRef var = get_var(L, 1);
|
get_var(L, 1)->~Variable();
|
||||||
kiwi_var_del(var);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_var_set_name(lua_State* L) {
|
static int lkiwi_var_set_name(lua_State* L) {
|
||||||
KiwiVarRef var = get_var(L, 1);
|
auto* var = get_var(L, 1);
|
||||||
const char* name = luaL_checkstring(L, 2);
|
const char* name = luaL_checkstring(L, 2);
|
||||||
kiwi_var_set_name(var, name);
|
var->setName(name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_var_name(lua_State* L) {
|
static int lkiwi_var_name(lua_State* L) {
|
||||||
KiwiVarRef var = get_var(L, 1);
|
lua_pushstring(L, get_var(L, 1)->name().c_str());
|
||||||
lua_pushstring(L, kiwi_var_name(var));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_var_set(lua_State* L) {
|
static int lkiwi_var_set(lua_State* L) {
|
||||||
KiwiVarRef var = get_var(L, 1);
|
auto* var = get_var(L, 1);
|
||||||
const double value = luaL_checknumber(L, 2);
|
const double value = luaL_checknumber(L, 2);
|
||||||
kiwi_var_set_value(var, value);
|
var->setValue(value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_var_value(lua_State* L) {
|
static int lkiwi_var_value(lua_State* L) {
|
||||||
KiwiVarRef var = get_var(L, 1);
|
lua_pushnumber(L, get_var(L, 1)->value());
|
||||||
lua_pushnumber(L, kiwi_var_value(var));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_var_toterm(lua_State* L) {
|
static int lkiwi_var_toterm(lua_State* L) {
|
||||||
KiwiVarRef var = get_var(L, 1);
|
auto* var = get_var(L, 1);
|
||||||
double coefficient = luaL_optnumber(L, 2, 1.0);
|
double coefficient = luaL_optnumber(L, 2, 1.0);
|
||||||
|
auto* term = term_new(L);
|
||||||
|
|
||||||
KiwiTerm* term = term_new(L);
|
term->var = kiwi_var_retain(var);
|
||||||
term->var = kiwi_var_clone(var);
|
|
||||||
term->coefficient = coefficient;
|
term->coefficient = coefficient;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_var_toexpr(lua_State* L) {
|
static int lkiwi_var_toexpr(lua_State* L) {
|
||||||
const KiwiTerm t = {get_var(L, 1), 1.0};
|
const KiwiTerm t {get_var(L, 1), 1.0};
|
||||||
return push_expr_one(L, 0.0, &t);
|
return push_expr_one(L, 0.0, &t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,7 +546,7 @@ static const struct luaL_Reg kiwi_var_m[] = {
|
|||||||
|
|
||||||
static int lkiwi_var_new(lua_State* L) {
|
static int lkiwi_var_new(lua_State* L) {
|
||||||
const char* name = luaL_optstring(L, 1, "");
|
const char* name = luaL_optstring(L, 1, "");
|
||||||
var_new(L, kiwi_var_new(name));
|
var_new(L, name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -564,10 +560,10 @@ static int lkiwi_term_m_mul(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isnum) {
|
if (isnum) {
|
||||||
const KiwiTerm* term = try_term(L, termidx);
|
const auto* term = try_term(L, termidx);
|
||||||
if (term) {
|
if (term) {
|
||||||
KiwiTerm* ret = term_new(L);
|
auto* ret = term_new(L);
|
||||||
ret->var = kiwi_var_clone(term->var);
|
ret->var = kiwi_var_retain(term->var);
|
||||||
ret->coefficient = term->coefficient * num;
|
ret->coefficient = term->coefficient * num;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -583,7 +579,7 @@ static int lkiwi_term_m_div(lua_State* L) {
|
|||||||
return op_error(L, "/", 1, 2);
|
return op_error(L, "/", 1, 2);
|
||||||
}
|
}
|
||||||
KiwiTerm* ret = term_new(L);
|
KiwiTerm* ret = term_new(L);
|
||||||
ret->var = kiwi_var_clone(term->var);
|
ret->var = kiwi_var_retain(term->var);
|
||||||
ret->coefficient = term->coefficient / num;
|
ret->coefficient = term->coefficient / num;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -591,7 +587,7 @@ static int lkiwi_term_m_div(lua_State* L) {
|
|||||||
static int lkiwi_term_m_unm(lua_State* L) {
|
static int lkiwi_term_m_unm(lua_State* L) {
|
||||||
const KiwiTerm* term = get_term(L, 1);
|
const KiwiTerm* term = get_term(L, 1);
|
||||||
KiwiTerm* ret = term_new(L);
|
KiwiTerm* ret = term_new(L);
|
||||||
ret->var = kiwi_var_clone(term->var);
|
ret->var = kiwi_var_retain(term->var);
|
||||||
ret->coefficient = -term->coefficient;
|
ret->coefficient = -term->coefficient;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -599,7 +595,7 @@ static int lkiwi_term_m_unm(lua_State* L) {
|
|||||||
static int lkiwi_term_m_add(lua_State* L) {
|
static int lkiwi_term_m_add(lua_State* L) {
|
||||||
enum TypeId type_id_b;
|
enum TypeId type_id_b;
|
||||||
double num;
|
double num;
|
||||||
const void* arg_b = try_arg(L, 2, &type_id_b, &num);
|
void* arg_b = try_arg(L, 2, &type_id_b, &num);
|
||||||
|
|
||||||
if (type_id_b == TERM) {
|
if (type_id_b == TERM) {
|
||||||
int isnum_a;
|
int isnum_a;
|
||||||
@@ -613,13 +609,13 @@ static int lkiwi_term_m_add(lua_State* L) {
|
|||||||
if (term_a) {
|
if (term_a) {
|
||||||
switch (type_id_b) {
|
switch (type_id_b) {
|
||||||
case TERM:
|
case TERM:
|
||||||
return push_expr_pair(L, 0.0, term_a, (const KiwiTerm*)arg_b);
|
return push_expr_pair(L, 0.0, term_a, static_cast<KiwiTerm*>(arg_b));
|
||||||
case VAR: {
|
case VAR: {
|
||||||
const KiwiTerm term_b = {*(KiwiVarRef*)arg_b, 1.0};
|
const KiwiTerm term_b {static_cast<Variable*>(arg_b), 1.0};
|
||||||
return push_expr_pair(L, 0.0, term_a, &term_b);
|
return push_expr_pair(L, 0.0, term_a, &term_b);
|
||||||
}
|
}
|
||||||
case EXPR:
|
case EXPR:
|
||||||
return push_add_expr_term(L, (const KiwiExpression*)arg_b, term_a);
|
return push_add_expr_term(L, static_cast<KiwiExpression*>(arg_b), term_a);
|
||||||
case NUMBER:
|
case NUMBER:
|
||||||
return push_expr_one(L, num, term_a);
|
return push_expr_one(L, num, term_a);
|
||||||
default:
|
default:
|
||||||
@@ -641,25 +637,24 @@ static int lkiwi_term_toexpr(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_term_value(lua_State* L) {
|
static int lkiwi_term_value(lua_State* L) {
|
||||||
KiwiTerm* term = get_term(L, 1);
|
const auto* term = get_term(L, 1);
|
||||||
lua_pushnumber(L, kiwi_var_value(term->var) * term->coefficient);
|
lua_pushnumber(L, term->var->value() * term->coefficient);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_term_m_tostring(lua_State* L) {
|
static int lkiwi_term_m_tostring(lua_State* L) {
|
||||||
KiwiTerm* term = get_term(L, 1);
|
const auto* term = get_term(L, 1);
|
||||||
lua_pushfstring(L, "%f %s", term->coefficient, kiwi_var_name(term->var));
|
lua_pushfstring(L, "%f %s", term->coefficient, term->var->name().c_str());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_term_m_gc(lua_State* L) {
|
static int lkiwi_term_m_gc(lua_State* L) {
|
||||||
KiwiTerm* term = get_term(L, 1);
|
get_term(L, 1)->var->~Variable();
|
||||||
kiwi_var_del(term->var);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_term_m_index(lua_State* L) {
|
static int lkiwi_term_m_index(lua_State* L) {
|
||||||
KiwiTerm* term = get_term(L, 1);
|
const auto* term = get_term(L, 1);
|
||||||
size_t len;
|
size_t len;
|
||||||
const char* k = lua_tolstring(L, 2, &len);
|
const char* k = lua_tolstring(L, 2, &len);
|
||||||
if (len == 3 && memcmp("var", k, len) == 0) {
|
if (len == 3 && memcmp("var", k, len) == 0) {
|
||||||
@@ -670,7 +665,7 @@ static int lkiwi_term_m_index(lua_State* L) {
|
|||||||
lua_rawgetp(L, lua_upvalueindex(2), term->var);
|
lua_rawgetp(L, lua_upvalueindex(2), term->var);
|
||||||
#endif
|
#endif
|
||||||
if (lua_isnil(L, -1))
|
if (lua_isnil(L, -1))
|
||||||
var_new(L, kiwi_var_clone(term->var));
|
var_new(L, *term->var);
|
||||||
return 1;
|
return 1;
|
||||||
} else if (len == 11 && memcmp("coefficient", k, len) == 0) {
|
} else if (len == 11 && memcmp("coefficient", k, len) == 0) {
|
||||||
lua_pushnumber(L, term->coefficient);
|
lua_pushnumber(L, term->coefficient);
|
||||||
@@ -702,18 +697,18 @@ static const struct luaL_Reg kiwi_term_m[] = {
|
|||||||
{0, 0}};
|
{0, 0}};
|
||||||
|
|
||||||
static int lkiwi_term_new(lua_State* L) {
|
static int lkiwi_term_new(lua_State* L) {
|
||||||
KiwiVarRef var = get_var(L, 1);
|
auto* var = get_var(L, 1);
|
||||||
double coefficient = luaL_optnumber(L, 2, 1.0);
|
double coefficient = luaL_optnumber(L, 2, 1.0);
|
||||||
KiwiTerm* term = term_new(L);
|
auto* term = term_new(L);
|
||||||
term->var = kiwi_var_clone(var);
|
term->var = kiwi_var_retain(var);
|
||||||
term->coefficient = coefficient;
|
term->coefficient = coefficient;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push_expr_constant(lua_State* L, const KiwiExpression* expr, double constant) {
|
static int push_expr_constant(lua_State* L, const KiwiExpression* expr, double constant) {
|
||||||
KiwiExpression* ne = expr_new(L, expr->term_count);
|
auto* ne = expr_new(L, expr->term_count);
|
||||||
for (int i = 0; i < expr->term_count; i++) {
|
for (int i = 0; i < expr->term_count; i++) {
|
||||||
ne->terms[i].var = kiwi_var_clone(expr->terms[i].var);
|
ne->terms[i].var = kiwi_var_retain(expr->terms[i].var);
|
||||||
ne->terms[i].coefficient = expr->terms[i].coefficient;
|
ne->terms[i].coefficient = expr->terms[i].coefficient;
|
||||||
}
|
}
|
||||||
ne->constant = constant;
|
ne->constant = constant;
|
||||||
@@ -722,11 +717,11 @@ static int push_expr_constant(lua_State* L, const KiwiExpression* expr, double c
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int push_mul_expr_coeff(lua_State* L, const KiwiExpression* expr, double coeff) {
|
static int push_mul_expr_coeff(lua_State* L, const KiwiExpression* expr, double coeff) {
|
||||||
KiwiExpression* ne = expr_new(L, expr->term_count);
|
auto* ne = expr_new(L, expr->term_count);
|
||||||
ne->constant = expr->constant * coeff;
|
ne->constant = expr->constant * coeff;
|
||||||
ne->term_count = expr->term_count;
|
ne->term_count = expr->term_count;
|
||||||
for (int i = 0; i < expr->term_count; i++) {
|
for (int i = 0; i < expr->term_count; i++) {
|
||||||
ne->terms[i].var = kiwi_var_clone(expr->terms[i].var);
|
ne->terms[i].var = kiwi_var_retain(expr->terms[i].var);
|
||||||
ne->terms[i].coefficient = expr->terms[i].coefficient * coeff;
|
ne->terms[i].coefficient = expr->terms[i].coefficient * coeff;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -735,16 +730,16 @@ static int push_mul_expr_coeff(lua_State* L, const KiwiExpression* expr, double
|
|||||||
static int push_add_expr_expr(lua_State* L, const KiwiExpression* a, const KiwiExpression* b) {
|
static int push_add_expr_expr(lua_State* L, const KiwiExpression* a, const KiwiExpression* b) {
|
||||||
int na = a->term_count, nb = b->term_count;
|
int na = a->term_count, nb = b->term_count;
|
||||||
|
|
||||||
KiwiExpression* ne = expr_new(L, na + nb);
|
auto* ne = expr_new(L, na + nb);
|
||||||
ne->constant = a->constant + b->constant;
|
ne->constant = a->constant + b->constant;
|
||||||
ne->term_count = na + nb;
|
ne->term_count = na + nb;
|
||||||
|
|
||||||
for (int i = 0; i < na; i++) {
|
for (int i = 0; i < na; i++) {
|
||||||
ne->terms[i].var = kiwi_var_clone(a->terms[i].var);
|
ne->terms[i].var = kiwi_var_retain(a->terms[i].var);
|
||||||
ne->terms[i].coefficient = a->terms[i].coefficient;
|
ne->terms[i].coefficient = a->terms[i].coefficient;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < nb; i++) {
|
for (int i = 0; i < nb; i++) {
|
||||||
ne->terms[i + na].var = kiwi_var_clone(b->terms[i].var);
|
ne->terms[i + na].var = kiwi_var_retain(b->terms[i].var);
|
||||||
ne->terms[i + na].coefficient = b->terms[i].coefficient;
|
ne->terms[i + na].coefficient = b->terms[i].coefficient;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -760,7 +755,7 @@ static int lkiwi_expr_m_mul(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isnum) {
|
if (isnum) {
|
||||||
const KiwiExpression* expr = try_expr(L, expridx);
|
const auto* expr = try_expr(L, expridx);
|
||||||
if (expr)
|
if (expr)
|
||||||
return push_mul_expr_coeff(L, expr, num);
|
return push_mul_expr_coeff(L, expr, num);
|
||||||
}
|
}
|
||||||
@@ -768,7 +763,7 @@ static int lkiwi_expr_m_mul(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_expr_m_div(lua_State* L) {
|
static int lkiwi_expr_m_div(lua_State* L) {
|
||||||
const KiwiExpression* expr = try_expr(L, 1);
|
const auto* expr = try_expr(L, 1);
|
||||||
int isnum;
|
int isnum;
|
||||||
double num = lua_tonumberx(L, 2, &isnum);
|
double num = lua_tonumberx(L, 2, &isnum);
|
||||||
if (!expr || !isnum) {
|
if (!expr || !isnum) {
|
||||||
@@ -778,20 +773,20 @@ static int lkiwi_expr_m_div(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_expr_m_unm(lua_State* L) {
|
static int lkiwi_expr_m_unm(lua_State* L) {
|
||||||
const KiwiExpression* expr = get_expr(L, 1);
|
const auto* expr = get_expr(L, 1);
|
||||||
return push_mul_expr_coeff(L, expr, -1.0);
|
return push_mul_expr_coeff(L, expr, -1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_expr_m_add(lua_State* L) {
|
static int lkiwi_expr_m_add(lua_State* L) {
|
||||||
enum TypeId type_id_b;
|
enum TypeId type_id_b;
|
||||||
double num;
|
double num;
|
||||||
const void* arg_b = try_arg(L, 2, &type_id_b, &num);
|
void* arg_b = try_arg(L, 2, &type_id_b, &num);
|
||||||
|
|
||||||
if (type_id_b == EXPR) {
|
if (type_id_b == EXPR) {
|
||||||
int isnum_a;
|
int isnum_a;
|
||||||
num = lua_tonumberx(L, 1, &isnum_a);
|
num = lua_tonumberx(L, 1, &isnum_a);
|
||||||
if (isnum_a) {
|
if (isnum_a) {
|
||||||
const KiwiExpression* expr_b = (const KiwiExpression*)arg_b;
|
auto* expr_b = static_cast<const KiwiExpression*>(arg_b);
|
||||||
return push_expr_constant(L, expr_b, num + expr_b->constant);
|
return push_expr_constant(L, expr_b, num + expr_b->constant);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -800,11 +795,11 @@ static int lkiwi_expr_m_add(lua_State* L) {
|
|||||||
if (expr_a) {
|
if (expr_a) {
|
||||||
switch (type_id_b) {
|
switch (type_id_b) {
|
||||||
case EXPR:
|
case EXPR:
|
||||||
return push_add_expr_expr(L, expr_a, (const KiwiExpression*)arg_b);
|
return push_add_expr_expr(L, expr_a, static_cast<KiwiExpression*>(arg_b));
|
||||||
case TERM:
|
case TERM:
|
||||||
return push_add_expr_term(L, expr_a, (const KiwiTerm*)arg_b);
|
return push_add_expr_term(L, expr_a, static_cast<KiwiTerm*>(arg_b));
|
||||||
case VAR: {
|
case VAR: {
|
||||||
const KiwiTerm term_b = {*(KiwiVarRef*)arg_b, 1.0};
|
const KiwiTerm term_b {static_cast<Variable*>(arg_b), 1.0};
|
||||||
return push_add_expr_term(L, expr_a, &term_b);
|
return push_add_expr_term(L, expr_a, &term_b);
|
||||||
}
|
}
|
||||||
case NUMBER:
|
case NUMBER:
|
||||||
@@ -824,23 +819,23 @@ static int lkiwi_expr_m_sub(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_expr_value(lua_State* L) {
|
static int lkiwi_expr_value(lua_State* L) {
|
||||||
KiwiExpression* expr = get_expr(L, 1);
|
const auto* expr = get_expr(L, 1);
|
||||||
double sum = expr->constant;
|
double sum = expr->constant;
|
||||||
for (int i = 0; i < expr->term_count; i++) {
|
for (int i = 0; i < expr->term_count; i++) {
|
||||||
const KiwiTerm* t = &expr->terms[i];
|
const auto* t = &expr->terms[i];
|
||||||
sum += kiwi_var_value(t->var) * t->coefficient;
|
sum += t->var->value() * t->coefficient;
|
||||||
}
|
}
|
||||||
lua_pushnumber(L, sum);
|
lua_pushnumber(L, sum);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_expr_terms(lua_State* L) {
|
static int lkiwi_expr_terms(lua_State* L) {
|
||||||
KiwiExpression* expr = get_expr(L, 1);
|
const auto* expr = get_expr(L, 1);
|
||||||
lua_createtable(L, expr->term_count, 0);
|
lua_createtable(L, expr->term_count, 0);
|
||||||
for (int i = 0; i < expr->term_count; i++) {
|
for (int i = 0; i < expr->term_count; i++) {
|
||||||
KiwiTerm* t = &expr->terms[i];
|
const auto* t = &expr->terms[i];
|
||||||
KiwiTerm* new_term = term_new(L);
|
auto* new_term = term_new(L);
|
||||||
new_term->var = kiwi_var_clone(t->var);
|
new_term->var = kiwi_var_retain(t->var);
|
||||||
new_term->coefficient = t->coefficient;
|
new_term->coefficient = t->coefficient;
|
||||||
lua_rawseti(L, -2, i + 1);
|
lua_rawseti(L, -2, i + 1);
|
||||||
}
|
}
|
||||||
@@ -858,7 +853,7 @@ static void push_expr_string(lua_State* L, KiwiExpression* expr) {
|
|||||||
|
|
||||||
for (int i = 0; i < expr->term_count; i++) {
|
for (int i = 0; i < expr->term_count; i++) {
|
||||||
KiwiTerm* t = &expr->terms[i];
|
KiwiTerm* t = &expr->terms[i];
|
||||||
lua_pushfstring(L, "%f %s", t->coefficient, kiwi_var_name(t->var));
|
lua_pushfstring(L, "%f %s", t->coefficient, t->var->name().c_str());
|
||||||
luaL_addvalue(&buf);
|
luaL_addvalue(&buf);
|
||||||
luaL_addstring(&buf, " + ");
|
luaL_addstring(&buf, " + ");
|
||||||
}
|
}
|
||||||
@@ -874,9 +869,9 @@ static int lkiwi_expr_m_tostring(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_expr_m_gc(lua_State* L) {
|
static int lkiwi_expr_m_gc(lua_State* L) {
|
||||||
KiwiExpression* expr = get_expr(L, 1);
|
const auto* expr = get_expr(L, 1);
|
||||||
for (int i = 0; i < expr->term_count; i++) {
|
for (auto* t = expr->terms; t != expr->terms + expr->term_count; ++t) {
|
||||||
kiwi_var_del(expr->terms[i].var);
|
t->var->~Variable();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -925,45 +920,42 @@ static int lkiwi_expr_new(lua_State* L) {
|
|||||||
|
|
||||||
for (int i = 0; i < nterms; i++) {
|
for (int i = 0; i < nterms; i++) {
|
||||||
const KiwiTerm* term = get_term(L, i + 2);
|
const KiwiTerm* term = get_term(L, i + 2);
|
||||||
expr->terms[i].var = kiwi_var_clone(term->var);
|
expr->terms[i].var = kiwi_var_retain(term->var);
|
||||||
expr->terms[i].coefficient = term->coefficient;
|
expr->terms[i].coefficient = term->coefficient;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_constraint_strength(lua_State* L) {
|
static int lkiwi_constraint_strength(lua_State* L) {
|
||||||
KiwiConstraintRef c = get_constraint(L, 1);
|
lua_pushnumber(L, get_constraint(L, 1)->strength());
|
||||||
lua_pushnumber(L, kiwi_constraint_strength(c));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_constraint_op(lua_State* L) {
|
static int lkiwi_constraint_op(lua_State* L) {
|
||||||
KiwiConstraintRef c = get_constraint(L, 1);
|
auto op = get_constraint(L, 1)->op();
|
||||||
enum KiwiRelOp op = kiwi_constraint_op(c);
|
|
||||||
const char* opstr = "??";
|
const char* opstr = "??";
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case KIWI_OP_EQ:
|
case kiwi::OP_LE:
|
||||||
opstr = "EQ";
|
|
||||||
break;
|
|
||||||
case KIWI_OP_LE:
|
|
||||||
opstr = "LE";
|
opstr = "LE";
|
||||||
break;
|
break;
|
||||||
case KIWI_OP_GE:
|
case kiwi::OP_GE:
|
||||||
opstr = "GE";
|
opstr = "GE";
|
||||||
break;
|
break;
|
||||||
|
case kiwi::OP_EQ:
|
||||||
|
opstr = "EQ";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
lua_pushlstring(L, opstr, 2);
|
lua_pushlstring(L, opstr, 2);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_constraint_violated(lua_State* L) {
|
static int lkiwi_constraint_violated(lua_State* L) {
|
||||||
KiwiConstraintRef c = get_constraint(L, 1);
|
lua_pushboolean(L, get_constraint(L, 1)->violated());
|
||||||
lua_pushboolean(L, kiwi_constraint_violated(c));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_constraint_expression(lua_State* L) {
|
static int lkiwi_constraint_expression(lua_State* L) {
|
||||||
KiwiConstraintRef c = get_constraint(L, 1);
|
auto* c = get_constraint(L, 1);
|
||||||
const static int SZ = 7;
|
const static int SZ = 7;
|
||||||
KiwiExpression* expr = expr_new(L, SZ);
|
KiwiExpression* expr = expr_new(L, SZ);
|
||||||
int n = kiwi_constraint_expression(c, expr, SZ);
|
int n = kiwi_constraint_expression(c, expr, SZ);
|
||||||
@@ -977,41 +969,46 @@ static int lkiwi_constraint_expression(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_constraint_m_tostring(lua_State* L) {
|
static int lkiwi_constraint_m_tostring(lua_State* L) {
|
||||||
KiwiConstraintRef c = get_constraint(L, 1);
|
const auto& c = *get_constraint(L, 1);
|
||||||
|
|
||||||
const static int SZ = 16;
|
const constexpr static int SZ = 16;
|
||||||
KiwiExpression* expr =
|
|
||||||
(KiwiExpression*)stalloc(sizeof(KiwiExpression) + sizeof(KiwiTerm) * (SZ - 1));
|
alignas(KiwiExpression
|
||||||
int n = kiwi_constraint_expression(c, expr, SZ);
|
) unsigned char expr_buf[sizeof(KiwiExpression) + sizeof(KiwiTerm) * (SZ - 1)];
|
||||||
|
auto* expr = reinterpret_cast<KiwiExpression*>(&expr_buf);
|
||||||
|
|
||||||
|
int n = kiwi_constraint_expression(&c, expr, SZ);
|
||||||
|
|
||||||
if (l_unlikely(n > SZ)) {
|
if (l_unlikely(n > SZ)) {
|
||||||
expr = (KiwiExpression*)malloc(sizeof(KiwiExpression) + sizeof(KiwiTerm) * (n - 1));
|
expr =
|
||||||
|
static_cast<KiwiExpression*>(malloc(sizeof(KiwiExpression) + sizeof(KiwiTerm) * (n - 1))
|
||||||
|
);
|
||||||
if (!expr) {
|
if (!expr) {
|
||||||
luaL_error(L, "out of memory");
|
luaL_error(L, "out of memory");
|
||||||
}
|
}
|
||||||
kiwi_constraint_expression(c, expr, n);
|
kiwi_constraint_expression(&c, expr, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
luaL_Buffer buf;
|
luaL_Buffer buf;
|
||||||
luaL_buffinit(L, &buf);
|
luaL_buffinit(L, &buf);
|
||||||
const char* oppart = " ?? 0 | ";
|
const char* oppart = " ?? 0 | ";
|
||||||
switch (kiwi_constraint_op(c)) {
|
switch (c.op()) {
|
||||||
case KIWI_OP_EQ:
|
case kiwi::OP_LE:
|
||||||
oppart = " == 0 | ";
|
|
||||||
break;
|
|
||||||
case KIWI_OP_LE:
|
|
||||||
oppart = " <= 0 | ";
|
oppart = " <= 0 | ";
|
||||||
break;
|
break;
|
||||||
case KIWI_OP_GE:
|
case kiwi::OP_GE:
|
||||||
oppart = " >= 0 | ";
|
oppart = " >= 0 | ";
|
||||||
break;
|
break;
|
||||||
|
case kiwi::OP_EQ:
|
||||||
|
oppart = " == 0 | ";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
push_expr_string(L, expr);
|
push_expr_string(L, expr);
|
||||||
luaL_addvalue(&buf);
|
luaL_addvalue(&buf);
|
||||||
luaL_addlstring(&buf, oppart, 8);
|
luaL_addlstring(&buf, oppart, 8);
|
||||||
const char* strength_name = 0;
|
const char* strength_name = 0;
|
||||||
const double strength = kiwi_constraint_strength(c);
|
const double strength = c.strength();
|
||||||
|
|
||||||
if (strength == STRENGTH_REQUIRED) {
|
if (strength == STRENGTH_REQUIRED) {
|
||||||
strength_name = "required";
|
strength_name = "required";
|
||||||
@@ -1035,8 +1032,7 @@ static int lkiwi_constraint_m_tostring(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_constraint_m_gc(lua_State* L) {
|
static int lkiwi_constraint_m_gc(lua_State* L) {
|
||||||
KiwiConstraintRef c = get_constraint(L, 1);
|
get_constraint(L, 1)->~Constraint();
|
||||||
kiwi_constraint_del(c);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1082,14 +1078,15 @@ static int lkiwi_constraint_new(lua_State* L) {
|
|||||||
|
|
||||||
static int push_pair_constraint(
|
static int push_pair_constraint(
|
||||||
lua_State* L,
|
lua_State* L,
|
||||||
KiwiVarRef left,
|
Variable* left,
|
||||||
double coeff,
|
double coeff,
|
||||||
KiwiVarRef right,
|
Variable* right,
|
||||||
double constant,
|
double constant,
|
||||||
enum KiwiRelOp op,
|
enum KiwiRelOp op,
|
||||||
double strength
|
double strength
|
||||||
) {
|
) {
|
||||||
KiwiExpression* expr = (KiwiExpression*)stalloc(sizeof(KiwiExpression) + sizeof(KiwiTerm));
|
alignas(KiwiExpression) unsigned char expr_buf[sizeof(KiwiExpression) + sizeof(KiwiTerm)];
|
||||||
|
auto* expr = reinterpret_cast<KiwiExpression*>(&expr_buf);
|
||||||
expr->constant = constant;
|
expr->constant = constant;
|
||||||
expr->term_count = 2;
|
expr->term_count = 2;
|
||||||
expr->terms[0].var = left;
|
expr->terms[0].var = left;
|
||||||
@@ -1233,8 +1230,7 @@ static int lkiwi_solver_handle_err(lua_State* L, const KiwiErr* err, const KiwiS
|
|||||||
lua_settop(L, 2);
|
lua_settop(L, 2);
|
||||||
if (err) {
|
if (err) {
|
||||||
error_new(L, err, 1, 2);
|
error_new(L, err, 1, 2);
|
||||||
unsigned error_mask;
|
unsigned error_mask = solver->error_mask;
|
||||||
memcpy(&error_mask, solver, sizeof(error_mask));
|
|
||||||
if (error_mask & (1 << err->kind)) {
|
if (error_mask & (1 << err->kind)) {
|
||||||
return 2;
|
return 2;
|
||||||
} else {
|
} else {
|
||||||
@@ -1245,22 +1241,22 @@ static int lkiwi_solver_handle_err(lua_State* L, const KiwiErr* err, const KiwiS
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_solver_add_constraint(lua_State* L) {
|
static int lkiwi_solver_add_constraint(lua_State* L) {
|
||||||
KiwiSolver* solver = get_solver(L, 1);
|
auto* solver = get_solver(L, 1);
|
||||||
KiwiConstraintRef c = get_constraint(L, 2);
|
const auto& c = *get_constraint(L, 2);
|
||||||
const KiwiErr* err = kiwi_solver_add_constraint(solver, c);
|
const KiwiErr* err = kiwi_solver_add_constraint(solver, c);
|
||||||
return lkiwi_solver_handle_err(L, err, solver);
|
return lkiwi_solver_handle_err(L, err, solver);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_solver_remove_constraint(lua_State* L) {
|
static int lkiwi_solver_remove_constraint(lua_State* L) {
|
||||||
KiwiSolver* solver = get_solver(L, 1);
|
auto* solver = get_solver(L, 1);
|
||||||
KiwiConstraintRef c = get_constraint(L, 2);
|
const auto& c = *get_constraint(L, 2);
|
||||||
const KiwiErr* err = kiwi_solver_remove_constraint(solver, c);
|
const KiwiErr* err = kiwi_solver_remove_constraint(solver, c);
|
||||||
return lkiwi_solver_handle_err(L, err, solver);
|
return lkiwi_solver_handle_err(L, err, solver);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_solver_add_edit_var(lua_State* L) {
|
static int lkiwi_solver_add_edit_var(lua_State* L) {
|
||||||
KiwiSolver* solver = get_solver(L, 1);
|
KiwiSolver* solver = get_solver(L, 1);
|
||||||
KiwiVarRef var = get_var(L, 2);
|
const auto& var = *get_var(L, 2);
|
||||||
double strength = luaL_checknumber(L, 3);
|
double strength = luaL_checknumber(L, 3);
|
||||||
const KiwiErr* err = kiwi_solver_add_edit_var(solver, var, strength);
|
const KiwiErr* err = kiwi_solver_add_edit_var(solver, var, strength);
|
||||||
return lkiwi_solver_handle_err(L, err, solver);
|
return lkiwi_solver_handle_err(L, err, solver);
|
||||||
@@ -1268,46 +1264,51 @@ static int lkiwi_solver_add_edit_var(lua_State* L) {
|
|||||||
|
|
||||||
static int lkiwi_solver_remove_edit_var(lua_State* L) {
|
static int lkiwi_solver_remove_edit_var(lua_State* L) {
|
||||||
KiwiSolver* solver = get_solver(L, 1);
|
KiwiSolver* solver = get_solver(L, 1);
|
||||||
KiwiVarRef var = get_var(L, 2);
|
const auto& var = *get_var(L, 2);
|
||||||
const KiwiErr* err = kiwi_solver_remove_edit_var(solver, var);
|
const KiwiErr* err = kiwi_solver_remove_edit_var(solver, var);
|
||||||
return lkiwi_solver_handle_err(L, err, solver);
|
return lkiwi_solver_handle_err(L, err, solver);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_solver_suggest_value(lua_State* L) {
|
static int lkiwi_solver_suggest_value(lua_State* L) {
|
||||||
KiwiSolver* solver = get_solver(L, 1);
|
KiwiSolver* solver = get_solver(L, 1);
|
||||||
KiwiVarRef var = get_var(L, 2);
|
const auto& var = *get_var(L, 2);
|
||||||
double value = luaL_checknumber(L, 3);
|
double value = luaL_checknumber(L, 3);
|
||||||
const KiwiErr* err = kiwi_solver_suggest_value(solver, var, value);
|
const KiwiErr* err = kiwi_solver_suggest_value(solver, var, value);
|
||||||
return lkiwi_solver_handle_err(L, err, solver);
|
return lkiwi_solver_handle_err(L, err, solver);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_solver_update_vars(lua_State* L) {
|
static int lkiwi_solver_update_vars(lua_State* L) {
|
||||||
kiwi_solver_update_vars(get_solver(L, 1));
|
get_solver(L, 1)->solver.updateVariables();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_solver_reset(lua_State* L) {
|
static int lkiwi_solver_reset(lua_State* L) {
|
||||||
kiwi_solver_reset(get_solver(L, 1));
|
get_solver(L, 1)->solver.reset();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_solver_has_constraint(lua_State* L) {
|
static int lkiwi_solver_has_constraint(lua_State* L) {
|
||||||
lua_pushboolean(L, kiwi_solver_has_constraint(get_solver(L, 1), get_constraint(L, 2)));
|
auto* s = get_solver(L, 1);
|
||||||
|
const auto* c = get_constraint(L, 2);
|
||||||
|
lua_pushboolean(L, s->solver.hasConstraint(*c));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_solver_has_edit_var(lua_State* L) {
|
static int lkiwi_solver_has_edit_var(lua_State* L) {
|
||||||
lua_pushboolean(L, kiwi_solver_has_edit_var(get_solver(L, 1), get_var(L, 2)));
|
auto* s = get_solver(L, 1);
|
||||||
|
const auto* var = get_var(L, 2);
|
||||||
|
lua_pushboolean(L, s->solver.hasEditVariable(*var));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_solver_dump(lua_State* L) {
|
static int lkiwi_solver_dump(lua_State* L) {
|
||||||
kiwi_solver_dump(get_solver(L, 1));
|
get_solver(L, 1)->solver.dump();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_solver_dumps(lua_State* L) {
|
static int lkiwi_solver_dumps(lua_State* L) {
|
||||||
lua_pushstring(L, kiwi_solver_dumps(get_solver(L, 1)));
|
const auto s = get_solver(L, 1)->solver.dumps();
|
||||||
|
lua_pushlstring(L, s.data(), s.length());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1328,8 +1329,7 @@ static int lkiwi_add_remove_tab(lua_State* L, add_remove_fn_t fn, void* d) {
|
|||||||
const KiwiErr* err = fn(L, solver, d);
|
const KiwiErr* err = fn(L, solver, d);
|
||||||
if (err) {
|
if (err) {
|
||||||
error_new(L, err, 1, narg + 1 /* item_absi */);
|
error_new(L, err, 1, narg + 1 /* item_absi */);
|
||||||
unsigned error_mask;
|
unsigned error_mask = solver->error_mask;
|
||||||
memcpy(&error_mask, solver, sizeof(error_mask));
|
|
||||||
if (error_mask & (1 << err->kind)) {
|
if (error_mask & (1 << err->kind)) {
|
||||||
lua_replace(L, 3);
|
lua_replace(L, 3);
|
||||||
lua_settop(L, 3);
|
lua_settop(L, 3);
|
||||||
@@ -1345,8 +1345,7 @@ static int lkiwi_add_remove_tab(lua_State* L, add_remove_fn_t fn, void* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const KiwiErr* add_constraint_fn(lua_State* L, KiwiSolver* s, void* d) {
|
static const KiwiErr* add_constraint_fn(lua_State* L, KiwiSolver* s, void* d) {
|
||||||
KiwiConstraintRef c = get_constraint(L, -1);
|
return kiwi_solver_add_constraint(s, *get_constraint(L, -1));
|
||||||
return kiwi_solver_add_constraint(s, c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_solver_add_constraints(lua_State* L) {
|
static int lkiwi_solver_add_constraints(lua_State* L) {
|
||||||
@@ -1354,8 +1353,7 @@ static int lkiwi_solver_add_constraints(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const KiwiErr* remove_constraint_fn(lua_State* L, KiwiSolver* s, void* d) {
|
static const KiwiErr* remove_constraint_fn(lua_State* L, KiwiSolver* s, void* d) {
|
||||||
KiwiConstraintRef c = get_constraint(L, -1);
|
return kiwi_solver_remove_constraint(s, *get_constraint(L, -1));
|
||||||
return kiwi_solver_remove_constraint(s, c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_solver_remove_constraints(lua_State* L) {
|
static int lkiwi_solver_remove_constraints(lua_State* L) {
|
||||||
@@ -1363,8 +1361,7 @@ static int lkiwi_solver_remove_constraints(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const KiwiErr* add_edit_var_fn(lua_State* L, KiwiSolver* s, void* d) {
|
static const KiwiErr* add_edit_var_fn(lua_State* L, KiwiSolver* s, void* d) {
|
||||||
KiwiVarRef v = get_var(L, -1);
|
return kiwi_solver_add_edit_var(s, *get_var(L, -1), *(double*)d);
|
||||||
return kiwi_solver_add_edit_var(s, v, *(double*)d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_solver_add_edit_vars(lua_State* L) {
|
static int lkiwi_solver_add_edit_vars(lua_State* L) {
|
||||||
@@ -1373,8 +1370,7 @@ static int lkiwi_solver_add_edit_vars(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const KiwiErr* remove_edit_var_fn(lua_State* L, KiwiSolver* s, void* d) {
|
static const KiwiErr* remove_edit_var_fn(lua_State* L, KiwiSolver* s, void* d) {
|
||||||
KiwiVarRef v = get_var(L, -1);
|
return kiwi_solver_remove_edit_var(s, *get_var(L, -1));
|
||||||
return kiwi_solver_remove_edit_var(s, v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_solver_remove_edit_vars(lua_State* L) {
|
static int lkiwi_solver_remove_edit_vars(lua_State* L) {
|
||||||
@@ -1398,15 +1394,15 @@ static int lkiwi_solver_suggest_values(lua_State* L) {
|
|||||||
if (lua_geti(L, 2, i) == LUA_TNIL) {
|
if (lua_geti(L, 2, i) == LUA_TNIL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
KiwiVarRef var = get_var(L, -1);
|
auto* var = get_var(L, -1);
|
||||||
|
|
||||||
lua_geti(L, 3, i);
|
lua_geti(L, 3, i);
|
||||||
double value = luaL_checknumber(L, -1);
|
double value = luaL_checknumber(L, -1);
|
||||||
|
|
||||||
const KiwiErr* err = kiwi_solver_suggest_value(solver, var, value);
|
const KiwiErr* err = kiwi_solver_suggest_value(solver, *var, value);
|
||||||
if (err) {
|
if (err) {
|
||||||
error_new(L, err, 1, narg + 1 /* item_absi */);
|
error_new(L, err, 1, narg + 1 /* item_absi */);
|
||||||
unsigned error_mask;
|
unsigned error_mask = solver->error_mask;
|
||||||
memcpy(&error_mask, solver, sizeof(error_mask));
|
|
||||||
if (error_mask & (1 << err->kind)) {
|
if (error_mask & (1 << err->kind)) {
|
||||||
lua_replace(L, 4);
|
lua_replace(L, 4);
|
||||||
lua_settop(L, 4);
|
lua_settop(L, 4);
|
||||||
@@ -1434,7 +1430,7 @@ static int lkiwi_solver_set_error_mask(lua_State* L) {
|
|||||||
error_mask = luaL_checkinteger(L, 2);
|
error_mask = luaL_checkinteger(L, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(solver, &error_mask, sizeof(error_mask));
|
solver->error_mask = error_mask;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1444,7 +1440,7 @@ static int lkiwi_solver_tostring(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lkiwi_solver_del(lua_State* L) {
|
static int lkiwi_solver_del(lua_State* L) {
|
||||||
kiwi_solver_del(get_solver(L, 1));
|
get_solver(L, 1)->~KiwiSolver();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1479,8 +1475,8 @@ static int lkiwi_solver_new_meth(lua_State* L) {
|
|||||||
error_mask = luaL_optinteger(L, 1, 0);
|
error_mask = luaL_optinteger(L, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
KiwiSolver** sp = (KiwiSolver**)lua_newuserdata(L, sizeof(KiwiSolver*));
|
KiwiSolver* sp = static_cast<KiwiSolver*>(lua_newuserdata(L, sizeof(KiwiSolver)));
|
||||||
*sp = kiwi_solver_new(error_mask);
|
new (sp) KiwiSolver {error_mask};
|
||||||
|
|
||||||
push_type(L, SOLVER);
|
push_type(L, SOLVER);
|
||||||
lua_setmetatable(L, -2);
|
lua_setmetatable(L, -2);
|
||||||
Reference in New Issue
Block a user