huge
This commit is contained in:
@@ -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
|
||||
416
ckiwi/ckiwi.cpp
416
ckiwi/ckiwi.cpp
@@ -1,3 +1,4 @@
|
||||
#include "ljkiwi.hpp"
|
||||
#include "ckiwi.h"
|
||||
|
||||
#include <kiwi/kiwi.h>
|
||||
@@ -5,99 +6,17 @@
|
||||
#include <cstdlib>
|
||||
#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 {
|
||||
|
||||
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>;
|
||||
using namespace kiwi;
|
||||
|
||||
const KiwiErr* new_error(const KiwiErr* base, const std::exception& ex) {
|
||||
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 {
|
||||
KiwiErrUnknown,
|
||||
"An unhandled C++ exception occurred."
|
||||
};
|
||||
"An unhandled C++ exception occurred."};
|
||||
|
||||
static const constexpr KiwiErr kKiwiErrNullObjectArg0 {
|
||||
KiwiErrNullObject,
|
||||
"null object passed as argument #0 (self)"
|
||||
};
|
||||
"null object passed as argument #0 (self)"};
|
||||
|
||||
static const constexpr KiwiErr kKiwiErrNullObjectArg1 {
|
||||
KiwiErrNullObject,
|
||||
"null object passed as argument #1"
|
||||
};
|
||||
"null object passed as argument #1"};
|
||||
|
||||
template<typename F>
|
||||
inline const KiwiErr* wrap_err(F&& f) {
|
||||
@@ -137,49 +53,42 @@ inline const KiwiErr* wrap_err(F&& f) {
|
||||
} catch (const UnsatisfiableConstraint& ex) {
|
||||
static const constexpr KiwiErr err {
|
||||
KiwiErrUnsatisfiableConstraint,
|
||||
"The constraint cannot be satisfied."
|
||||
};
|
||||
"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."
|
||||
};
|
||||
"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."
|
||||
};
|
||||
"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."
|
||||
};
|
||||
"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."
|
||||
};
|
||||
"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."
|
||||
};
|
||||
"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."
|
||||
};
|
||||
"An internal solver error occurred."};
|
||||
return new_error(&base, ex);
|
||||
} catch (std::bad_alloc&) {
|
||||
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>
|
||||
inline const KiwiErr* wrap_err(P ptr, F&& f) {
|
||||
if (!ptr) {
|
||||
inline const KiwiErr* wrap_err(P self, F&& f) {
|
||||
if (lk_unlikely(!self)) {
|
||||
return &kKiwiErrNullObjectArg0;
|
||||
}
|
||||
return wrap_err([&]() { f(ptr); });
|
||||
return wrap_err([&]() { f(self->solver); });
|
||||
}
|
||||
|
||||
template<typename P, typename R, typename F>
|
||||
inline const KiwiErr* wrap_err(P ptr, R ref, F&& f) {
|
||||
if (!ptr) {
|
||||
inline const KiwiErr* wrap_err(P self, R item, F&& f) {
|
||||
if (lk_unlikely(!self)) {
|
||||
return &kKiwiErrNullObjectArg0;
|
||||
} else if (!ref) {
|
||||
} else if (lk_unlikely(!item)) {
|
||||
return &kKiwiErrNullObjectArg1;
|
||||
}
|
||||
return wrap_err([&]() { f(ptr, ref); });
|
||||
return wrap_err([&]() { f(self->solver, *item); });
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
|
||||
KiwiVarRef kiwi_var_new(const char* name) {
|
||||
return make_var_cref(name ? name : "");
|
||||
KiwiTypeInfo kiwi_ti_KiwiVar = {sizeof(KiwiVar), alignof(KiwiVar)};
|
||||
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) {
|
||||
VariableRef(var).release();
|
||||
void kiwi_var_release(KiwiVar* var) {
|
||||
if (lk_likely(var))
|
||||
var->~KiwiVar();
|
||||
}
|
||||
|
||||
KiwiVarRef kiwi_var_clone(KiwiVarRef var) {
|
||||
return VariableRef(var).clone();
|
||||
}
|
||||
|
||||
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();
|
||||
void kiwi_var_retain(KiwiVar* var) {
|
||||
if (lk_likely(var)) {
|
||||
alignas(KiwiVar) unsigned char buf[sizeof(KiwiVar)];
|
||||
new (buf) KiwiVar(*var);
|
||||
}
|
||||
}
|
||||
|
||||
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* rhs,
|
||||
enum KiwiRelOp op,
|
||||
double strength
|
||||
double strength,
|
||||
void* mem
|
||||
) {
|
||||
if (strength < 0.0) {
|
||||
strength = kiwi::strength::required;
|
||||
@@ -278,69 +201,69 @@ KiwiConstraintRef kiwi_constraint_new(
|
||||
terms.reserve((lhs ? lhs->term_count : 0) + (rhs ? rhs->term_count : 0));
|
||||
|
||||
if (lhs) {
|
||||
for (auto* t = lhs->terms; t != lhs->terms + lhs->term_count; ++t) {
|
||||
ConstVariableRef var(t->var);
|
||||
if (var)
|
||||
terms.emplace_back(var.cref(), t->coefficient);
|
||||
for (auto* t = lhs->terms_; t != lhs->terms_ + lhs->term_count; ++t) {
|
||||
if (t->var)
|
||||
terms.emplace_back(*t->var, t->coefficient);
|
||||
}
|
||||
}
|
||||
if (rhs) {
|
||||
for (auto* t = rhs->terms; t != rhs->terms + rhs->term_count; ++t) {
|
||||
ConstVariableRef var(t->var);
|
||||
if (var)
|
||||
terms.emplace_back(var.cref(), -t->coefficient);
|
||||
for (auto* t = rhs->terms_; t != rhs->terms_ + rhs->term_count; ++t) {
|
||||
if (t->var)
|
||||
terms.emplace_back(*t->var, -t->coefficient);
|
||||
}
|
||||
}
|
||||
|
||||
return make_constraint_cref(
|
||||
new (mem) Constraint(
|
||||
Expression(std::move(terms), (lhs ? lhs->constant : 0.0) - (rhs ? rhs->constant : 0.0)),
|
||||
static_cast<RelationalOperator>(op),
|
||||
strength
|
||||
);
|
||||
}
|
||||
|
||||
void kiwi_constraint_del(KiwiConstraintRef constraint) {
|
||||
ConstraintRef(constraint).release();
|
||||
void kiwi_constraint_release(KiwiConstraint* c) {
|
||||
if (lk_likely(c))
|
||||
c->~KiwiConstraint();
|
||||
}
|
||||
|
||||
KiwiConstraintRef kiwi_constraint_clone(KiwiConstraintRef constraint) {
|
||||
return ConstraintRef(constraint).clone();
|
||||
}
|
||||
|
||||
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;
|
||||
void kiwi_constraint_retain(KiwiConstraint* c) {
|
||||
if (lk_likely(c)) {
|
||||
alignas(KiwiConstraint) unsigned char buf[sizeof(KiwiConstraint)];
|
||||
new (buf) KiwiConstraint(*c);
|
||||
}
|
||||
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 {
|
||||
@@ -348,79 +271,80 @@ struct KiwiSolver {
|
||||
Solver solver;
|
||||
};
|
||||
|
||||
KiwiSolver* kiwi_solver_new(unsigned error_mask) {
|
||||
return new KiwiSolver {error_mask};
|
||||
KiwiTypeInfo kiwi_ti_KiwiSolver = {sizeof(KiwiSolver), alignof(KiwiSolver)};
|
||||
|
||||
void kiwi_solver_construct(unsigned error_mask, void* mem) {
|
||||
new (mem) KiwiSolver {error_mask};
|
||||
}
|
||||
|
||||
void kiwi_solver_del(KiwiSolver* s) {
|
||||
if (s)
|
||||
delete s;
|
||||
void kiwi_solver_destroy(KiwiSolver* s) {
|
||||
if (lk_likely(s))
|
||||
s->~KiwiSolver();
|
||||
}
|
||||
|
||||
const KiwiErr* kiwi_solver_add_constraint(KiwiSolver* s, KiwiConstraintRef constraint) {
|
||||
return wrap_err(s, ConstraintRef(constraint), [](auto* s, const auto c) {
|
||||
s->solver.addConstraint(c);
|
||||
});
|
||||
unsigned kiwi_solver_get_error_mask(const KiwiSolver* s) {
|
||||
return lk_likely(s) ? s->error_mask : 0;
|
||||
}
|
||||
|
||||
const KiwiErr* kiwi_solver_remove_constraint(KiwiSolver* s, KiwiConstraintRef constraint) {
|
||||
return wrap_err(s, ConstraintRef(constraint), [](auto* s, const auto c) {
|
||||
s->solver.removeConstraint(c);
|
||||
});
|
||||
void kiwi_solver_set_error_mask(KiwiSolver* s, unsigned mask) {
|
||||
if (lk_likely(s))
|
||||
s->error_mask = mask;
|
||||
}
|
||||
|
||||
bool kiwi_solver_has_constraint(const KiwiSolver* s, KiwiConstraintRef constraint) {
|
||||
ConstraintRef c(constraint);
|
||||
if (!s || !c)
|
||||
const KiwiErr* kiwi_solver_add_constraint(KiwiSolver* s, const KiwiConstraint* constraint) {
|
||||
return wrap_err(s, constraint, [](auto& s, const auto& c) { s.addConstraint(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 s->solver.hasConstraint(c);
|
||||
return s->solver.hasConstraint(*constraint);
|
||||
}
|
||||
|
||||
const KiwiErr* kiwi_solver_add_edit_var(KiwiSolver* s, KiwiVarRef var, double strength) {
|
||||
return wrap_err(s, VariableRef(var), [strength](auto* s, const auto v) {
|
||||
s->solver.addEditVariable(v, strength);
|
||||
const KiwiErr* kiwi_solver_add_edit_var(KiwiSolver* s, const KiwiVar* var, double strength) {
|
||||
return wrap_err(s, var, [strength](auto& s, const auto& v) {
|
||||
s.addEditVariable(v, strength);
|
||||
});
|
||||
}
|
||||
|
||||
const KiwiErr* kiwi_solver_remove_edit_var(KiwiSolver* s, KiwiVarRef var) {
|
||||
return wrap_err(s, VariableRef(var), [](auto* s, const auto v) {
|
||||
s->solver.removeEditVariable(v);
|
||||
});
|
||||
const KiwiErr* kiwi_solver_remove_edit_var(KiwiSolver* s, const KiwiVar* var) {
|
||||
return wrap_err(s, var, [](auto& s, const auto& v) { s.removeEditVariable(v); });
|
||||
}
|
||||
|
||||
bool kiwi_solver_has_edit_var(const KiwiSolver* s, KiwiVarRef var) {
|
||||
VariableRef v(var);
|
||||
if (!s || !v)
|
||||
bool kiwi_solver_has_edit_var(const KiwiSolver* s, const KiwiVar* var) {
|
||||
if (lk_unlikely(!s || !var))
|
||||
return 0;
|
||||
return s->solver.hasEditVariable(v);
|
||||
return s->solver.hasEditVariable(*var);
|
||||
}
|
||||
|
||||
const KiwiErr* kiwi_solver_suggest_value(KiwiSolver* s, KiwiVarRef var, double value) {
|
||||
return wrap_err(s, VariableRef(var), [value](auto* s, const auto v) {
|
||||
s->solver.suggestValue(v, value);
|
||||
});
|
||||
const KiwiErr* kiwi_solver_suggest_value(KiwiSolver* s, const KiwiVar* var, double value) {
|
||||
return wrap_err(s, var, [value](auto& s, const auto& v) { s.suggestValue(v, value); });
|
||||
}
|
||||
|
||||
void kiwi_solver_update_vars(KiwiSolver* s) {
|
||||
if (s)
|
||||
if (lk_likely(s))
|
||||
s->solver.updateVariables();
|
||||
}
|
||||
|
||||
void kiwi_solver_reset(KiwiSolver* s) {
|
||||
if (s)
|
||||
if (lk_likely(s))
|
||||
s->solver.reset();
|
||||
}
|
||||
|
||||
void kiwi_solver_dump(const KiwiSolver* s) {
|
||||
if (s)
|
||||
if (lk_likely(s))
|
||||
s->solver.dump();
|
||||
}
|
||||
|
||||
char* kiwi_solver_dumps(const KiwiSolver* s) {
|
||||
if (!s)
|
||||
if (lk_unlikely(!s))
|
||||
return nullptr;
|
||||
|
||||
const auto str = s->solver.dumps(); // upstream library defect
|
||||
const auto& str = s->solver.dumps();
|
||||
const auto buf_size = str.size() + 1;
|
||||
auto* buf = static_cast<char*>(std::malloc(buf_size));
|
||||
if (!buf)
|
||||
|
||||
122
ckiwi/ckiwi.h
122
ckiwi/ckiwi.h
@@ -1,13 +1,38 @@
|
||||
#ifndef KIWI_CKIWI_H_
|
||||
#define KIWI_CKIWI_H_
|
||||
#ifndef LJKIWI_CKIWI_H_
|
||||
#define LJKIWI_CKIWI_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
#undef LJKIWI_USE_FAM_1
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#define LJKIWI_USE_FAM_1
|
||||
#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
|
||||
enum KiwiErrKind {
|
||||
@@ -26,18 +51,24 @@ enum KiwiErrKind {
|
||||
|
||||
enum KiwiRelOp { KIWI_OP_LE, KIWI_OP_GE, KIWI_OP_EQ };
|
||||
|
||||
typedef struct KiwiVarRefType* KiwiVarRef;
|
||||
typedef struct KiwiConstraintRefType* KiwiConstraintRef;
|
||||
|
||||
typedef struct KiwiTerm {
|
||||
KiwiVarRef var;
|
||||
KiwiVar* var;
|
||||
double coefficient;
|
||||
} KiwiTerm;
|
||||
|
||||
typedef struct KiwiExpression {
|
||||
double constant;
|
||||
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;
|
||||
|
||||
typedef struct KiwiErr {
|
||||
@@ -46,56 +77,63 @@ typedef struct KiwiErr {
|
||||
bool must_free;
|
||||
} KiwiErr;
|
||||
|
||||
typedef 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);
|
||||
struct KiwiSolver;
|
||||
|
||||
const char* kiwi_var_name(KiwiVarRef var);
|
||||
void kiwi_var_set_name(KiwiVarRef var, const char* name);
|
||||
double kiwi_var_value(KiwiVarRef var);
|
||||
void kiwi_var_set_value(KiwiVarRef var, double value);
|
||||
bool kiwi_var_eq(KiwiVarRef var, KiwiVarRef other);
|
||||
void kiwi_var_construct(const char* name, void* mem);
|
||||
void kiwi_var_release(KiwiVar* var);
|
||||
void kiwi_var_retain(KiwiVar* var);
|
||||
|
||||
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* rhs,
|
||||
enum KiwiRelOp op,
|
||||
double strength
|
||||
double strength,
|
||||
void* mem
|
||||
);
|
||||
void kiwi_constraint_del(KiwiConstraintRef constraint);
|
||||
KiwiConstraintRef kiwi_constraint_clone(KiwiConstraintRef constraint);
|
||||
void kiwi_constraint_release(KiwiConstraint* c);
|
||||
void kiwi_constraint_retain(KiwiConstraint* c);
|
||||
|
||||
double kiwi_constraint_strength(KiwiConstraintRef constraint);
|
||||
enum KiwiRelOp kiwi_constraint_op(KiwiConstraintRef constraint);
|
||||
bool kiwi_constraint_violated(KiwiConstraintRef constraint);
|
||||
int kiwi_constraint_expression(KiwiConstraintRef constraint, KiwiExpression* out, int out_size);
|
||||
double kiwi_constraint_strength(const KiwiConstraint* c);
|
||||
enum KiwiRelOp kiwi_constraint_op(const KiwiConstraint* c);
|
||||
bool kiwi_constraint_violated(const KiwiConstraint* c);
|
||||
int kiwi_constraint_expression(KiwiConstraint* c, KiwiExpression* out, int out_size);
|
||||
|
||||
KiwiSolver* kiwi_solver_new(unsigned error_mask);
|
||||
void kiwi_solver_del(KiwiSolver* s);
|
||||
void kiwi_solver_construct(unsigned error_mask, void* mem);
|
||||
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_remove_constraint(KiwiSolver* sp, KiwiConstraintRef constraint);
|
||||
bool kiwi_solver_has_constraint(const KiwiSolver* sp, KiwiConstraintRef constraint);
|
||||
const KiwiErr* kiwi_solver_add_edit_var(KiwiSolver* sp, KiwiVarRef var, double strength);
|
||||
const KiwiErr* kiwi_solver_remove_edit_var(KiwiSolver* sp, KiwiVarRef var);
|
||||
bool kiwi_solver_has_edit_var(const KiwiSolver* sp, KiwiVarRef var);
|
||||
const KiwiErr* kiwi_solver_suggest_value(KiwiSolver* sp, KiwiVarRef var, double value);
|
||||
const KiwiErr* kiwi_solver_add_constraint(KiwiSolver* s, const KiwiConstraint* constraint);
|
||||
const KiwiErr* kiwi_solver_remove_constraint(KiwiSolver* s, const KiwiConstraint* constraint);
|
||||
bool kiwi_solver_has_constraint(const KiwiSolver* s, const KiwiConstraint* constraint);
|
||||
const KiwiErr* kiwi_solver_add_edit_var(KiwiSolver* s, const KiwiVar* var, double strength);
|
||||
const KiwiErr* kiwi_solver_remove_edit_var(KiwiSolver* s, const KiwiVar* var);
|
||||
bool kiwi_solver_has_edit_var(const KiwiSolver* s, const KiwiVar* var);
|
||||
const KiwiErr* kiwi_solver_suggest_value(KiwiSolver* s, const KiwiVar* var, double value);
|
||||
void kiwi_solver_update_vars(KiwiSolver* sp);
|
||||
void kiwi_solver_reset(KiwiSolver* sp);
|
||||
void kiwi_solver_dump(const KiwiSolver* sp);
|
||||
char* kiwi_solver_dumps(const KiwiSolver* sp);
|
||||
|
||||
// LuaJIT end
|
||||
|
||||
#if __GNUC__
|
||||
#pragma GCC visibility pop
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
// mode: c++
|
||||
// End:
|
||||
#endif // KIWI_CKIWI_H_
|
||||
#endif // LJKIWI_CKIWI_H_
|
||||
|
||||
Reference in New Issue
Block a user