Refactors to produce slightly less garbage
This commit is contained in:
@@ -99,7 +99,7 @@ using ConstraintRef = SharedRef<Constraint, KiwiConstraintRef>;
|
|||||||
using VariableRef = SharedRef<Variable, KiwiVarRef>;
|
using VariableRef = SharedRef<Variable, KiwiVarRef>;
|
||||||
using ConstVariableRef = const SharedRef<const Variable, const KiwiVarRef>;
|
using ConstVariableRef = const SharedRef<const Variable, const KiwiVarRef>;
|
||||||
|
|
||||||
KiwiErrPtr new_error(KiwiErrPtr base, const std::exception& ex) {
|
const KiwiErr* new_error(const KiwiErr* base, const std::exception& ex) {
|
||||||
if (!std::strcmp(ex.what(), base->message))
|
if (!std::strcmp(ex.what(), base->message))
|
||||||
return base;
|
return base;
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ static const constexpr KiwiErr kKiwiErrNullObjectArg1 {
|
|||||||
"null object passed as argument #1"};
|
"null object passed as argument #1"};
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
inline KiwiErrPtr wrap_err(F&& f) {
|
inline const KiwiErr* wrap_err(F&& f) {
|
||||||
try {
|
try {
|
||||||
f();
|
f();
|
||||||
} catch (const UnsatisfiableConstraint& ex) {
|
} catch (const UnsatisfiableConstraint& ex) {
|
||||||
@@ -183,7 +183,7 @@ inline KiwiErrPtr wrap_err(F&& f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename P, typename R, typename F>
|
template<typename P, typename R, typename F>
|
||||||
inline KiwiErrPtr wrap_err(P ptr, F&& f) {
|
inline const KiwiErr* wrap_err(P ptr, F&& f) {
|
||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
return &kKiwiErrNullObjectArg0;
|
return &kKiwiErrNullObjectArg0;
|
||||||
}
|
}
|
||||||
@@ -191,7 +191,7 @@ inline KiwiErrPtr wrap_err(P ptr, F&& f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename P, typename R, typename F>
|
template<typename P, typename R, typename F>
|
||||||
inline KiwiErrPtr wrap_err(P ptr, R ref, F&& f) {
|
inline const KiwiErr* wrap_err(P ptr, R ref, F&& f) {
|
||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
return &kKiwiErrNullObjectArg0;
|
return &kKiwiErrNullObjectArg0;
|
||||||
} else if (!ref) {
|
} else if (!ref) {
|
||||||
@@ -245,23 +245,45 @@ int kiwi_var_eq(KiwiVarRef var, KiwiVarRef other) {
|
|||||||
return self && other_ref && self->equals(other_ref);
|
return self && other_ref && self->equals(other_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
KiwiConstraintRef
|
void kiwi_expression_del_vars(KiwiExpression* expr) {
|
||||||
kiwi_constraint_new(KiwiExpressionConstPtr expression, enum KiwiRelOp op, double strength) {
|
if (!expr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (auto* t = expr->terms; t != expr->terms + expr->term_count; ++t) {
|
||||||
|
VariableRef(t->var).release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KiwiConstraintRef kiwi_constraint_new(
|
||||||
|
const KiwiExpression* lhs,
|
||||||
|
const KiwiExpression* rhs,
|
||||||
|
enum KiwiRelOp op,
|
||||||
|
double strength
|
||||||
|
) {
|
||||||
if (strength < 0.0) {
|
if (strength < 0.0) {
|
||||||
strength = kiwi::strength::required;
|
strength = kiwi::strength::required;
|
||||||
}
|
}
|
||||||
std::vector<Term> terms;
|
|
||||||
if (expression) {
|
|
||||||
terms.reserve(expression->term_count);
|
|
||||||
|
|
||||||
for (auto* t = expression->terms; t != expression->terms + expression->term_count; ++t) {
|
std::vector<Term> terms;
|
||||||
|
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);
|
ConstVariableRef var(t->var);
|
||||||
if (var)
|
if (var)
|
||||||
terms.emplace_back(var.cref(), t->coefficient);
|
terms.emplace_back(var.cref(), 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return make_constraint_cref(
|
return make_constraint_cref(
|
||||||
Expression(std::move(terms), expression->constant),
|
Expression(std::move(terms), (lhs ? lhs->constant : 0.0) - (rhs ? rhs->constant : 0.0)),
|
||||||
static_cast<RelationalOperator>(op),
|
static_cast<RelationalOperator>(op),
|
||||||
strength
|
strength
|
||||||
);
|
);
|
||||||
@@ -311,17 +333,17 @@ int kiwi_constraint_expression(KiwiConstraintRef constraint, KiwiExpression* out
|
|||||||
return n_terms;
|
return n_terms;
|
||||||
}
|
}
|
||||||
|
|
||||||
KiwiSolverPtr kiwi_solver_new() {
|
KiwiSolver* kiwi_solver_new() {
|
||||||
return reinterpret_cast<KiwiSolverPtr>(new (std::nothrow) Solver());
|
return reinterpret_cast<KiwiSolver*>(new Solver());
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiwi_solver_del(KiwiSolverPtr sp) {
|
void kiwi_solver_del(KiwiSolver* sp) {
|
||||||
auto* solver = reinterpret_cast<Solver*>(sp);
|
auto* solver = reinterpret_cast<Solver*>(sp);
|
||||||
if (solver)
|
if (solver)
|
||||||
delete solver;
|
delete solver;
|
||||||
}
|
}
|
||||||
|
|
||||||
KiwiErrPtr kiwi_solver_add_constraint(KiwiSolverPtr s, KiwiConstraintRef constraint) {
|
const KiwiErr* kiwi_solver_add_constraint(KiwiSolver* s, KiwiConstraintRef constraint) {
|
||||||
return wrap_err(
|
return wrap_err(
|
||||||
reinterpret_cast<Solver*>(s),
|
reinterpret_cast<Solver*>(s),
|
||||||
ConstraintRef(constraint),
|
ConstraintRef(constraint),
|
||||||
@@ -329,7 +351,7 @@ KiwiErrPtr kiwi_solver_add_constraint(KiwiSolverPtr s, KiwiConstraintRef constra
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
KiwiErrPtr kiwi_solver_remove_constraint(KiwiSolverPtr s, KiwiConstraintRef constraint) {
|
const KiwiErr* kiwi_solver_remove_constraint(KiwiSolver* s, KiwiConstraintRef constraint) {
|
||||||
return wrap_err(
|
return wrap_err(
|
||||||
reinterpret_cast<Solver*>(s),
|
reinterpret_cast<Solver*>(s),
|
||||||
ConstraintRef(constraint),
|
ConstraintRef(constraint),
|
||||||
@@ -337,15 +359,15 @@ KiwiErrPtr kiwi_solver_remove_constraint(KiwiSolverPtr s, KiwiConstraintRef cons
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool kiwi_solver_has_constraint(KiwiSolverPtr s, KiwiConstraintRef constraint) {
|
bool kiwi_solver_has_constraint(const KiwiSolver* s, KiwiConstraintRef constraint) {
|
||||||
const auto* solver = reinterpret_cast<Solver*>(s);
|
const auto* solver = reinterpret_cast<const Solver*>(s);
|
||||||
ConstraintRef c(constraint);
|
ConstraintRef c(constraint);
|
||||||
if (!solver || !c)
|
if (!solver || !c)
|
||||||
return 0;
|
return 0;
|
||||||
return solver->hasConstraint(c);
|
return solver->hasConstraint(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
KiwiErrPtr kiwi_solver_add_edit_var(KiwiSolverPtr s, KiwiVarRef var, double strength) {
|
const KiwiErr* kiwi_solver_add_edit_var(KiwiSolver* s, KiwiVarRef var, double strength) {
|
||||||
return wrap_err(
|
return wrap_err(
|
||||||
reinterpret_cast<Solver*>(s),
|
reinterpret_cast<Solver*>(s),
|
||||||
VariableRef(var),
|
VariableRef(var),
|
||||||
@@ -353,21 +375,21 @@ KiwiErrPtr kiwi_solver_add_edit_var(KiwiSolverPtr s, KiwiVarRef var, double stre
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
KiwiErrPtr kiwi_solver_remove_edit_var(KiwiSolverPtr s, KiwiVarRef var) {
|
const KiwiErr* kiwi_solver_remove_edit_var(KiwiSolver* s, KiwiVarRef var) {
|
||||||
return wrap_err(reinterpret_cast<Solver*>(s), VariableRef(var), [](auto solver, const auto v) {
|
return wrap_err(reinterpret_cast<Solver*>(s), VariableRef(var), [](auto solver, const auto v) {
|
||||||
solver->removeEditVariable(v);
|
solver->removeEditVariable(v);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool kiwi_solver_has_edit_var(KiwiSolverPtr s, KiwiVarRef var) {
|
bool kiwi_solver_has_edit_var(const KiwiSolver* s, KiwiVarRef var) {
|
||||||
const auto* solver = reinterpret_cast<Solver*>(s);
|
const auto* solver = reinterpret_cast<const Solver*>(s);
|
||||||
VariableRef v(var);
|
VariableRef v(var);
|
||||||
if (!solver || !v)
|
if (!solver || !v)
|
||||||
return 0;
|
return 0;
|
||||||
return solver->hasEditVariable(v);
|
return solver->hasEditVariable(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
KiwiErrPtr kiwi_solver_suggest_value(KiwiSolverPtr s, KiwiVarRef var, double value) {
|
const KiwiErr* kiwi_solver_suggest_value(KiwiSolver* s, KiwiVarRef var, double value) {
|
||||||
return wrap_err(
|
return wrap_err(
|
||||||
reinterpret_cast<Solver*>(s),
|
reinterpret_cast<Solver*>(s),
|
||||||
VariableRef(var),
|
VariableRef(var),
|
||||||
@@ -376,30 +398,30 @@ KiwiErrPtr kiwi_solver_suggest_value(KiwiSolverPtr s, KiwiVarRef var, double val
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiwi_solver_update_vars(KiwiSolverPtr s) {
|
void kiwi_solver_update_vars(KiwiSolver* s) {
|
||||||
auto* solver = reinterpret_cast<Solver*>(s);
|
auto* solver = reinterpret_cast<Solver*>(s);
|
||||||
if (solver)
|
if (solver)
|
||||||
solver->updateVariables();
|
solver->updateVariables();
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiwi_solver_reset(KiwiSolverPtr s) {
|
void kiwi_solver_reset(KiwiSolver* s) {
|
||||||
auto* solver = reinterpret_cast<Solver*>(s);
|
auto* solver = reinterpret_cast<Solver*>(s);
|
||||||
if (solver)
|
if (solver)
|
||||||
solver->reset();
|
solver->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiwi_solver_dump(KiwiSolverPtr s) {
|
void kiwi_solver_dump(const KiwiSolver* s) {
|
||||||
auto* solver = reinterpret_cast<Solver*>(s);
|
auto* solver = reinterpret_cast<const Solver*>(s);
|
||||||
if (solver)
|
if (solver)
|
||||||
solver->dump();
|
const_cast<Solver*>(solver)->dump(); // upstream library defect
|
||||||
}
|
}
|
||||||
|
|
||||||
char* kiwi_solver_dumps(KiwiSolverPtr s) {
|
char* kiwi_solver_dumps(const KiwiSolver* s) {
|
||||||
auto* solver = reinterpret_cast<Solver*>(s);
|
auto* solver = reinterpret_cast<const Solver*>(s);
|
||||||
if (!solver)
|
if (!solver)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
const auto str = solver->dumps();
|
const auto str = const_cast<Solver*>(solver)->dumps(); // upstream library defect
|
||||||
const auto buf_size = str.size() + 1;
|
const auto buf_size = str.size() + 1;
|
||||||
auto* buf = static_cast<char*>(std::malloc(buf_size));
|
auto* buf = static_cast<char*>(std::malloc(buf_size));
|
||||||
if (!buf)
|
if (!buf)
|
||||||
|
|||||||
@@ -26,33 +26,27 @@ enum KiwiErrKind {
|
|||||||
|
|
||||||
enum KiwiRelOp { KIWI_OP_LE, KIWI_OP_GE, KIWI_OP_EQ };
|
enum KiwiRelOp { KIWI_OP_LE, KIWI_OP_GE, KIWI_OP_EQ };
|
||||||
|
|
||||||
struct KiwiVarRefType;
|
|
||||||
struct KiwiConstraintRefType;
|
|
||||||
|
|
||||||
typedef struct KiwiVarRefType* KiwiVarRef;
|
typedef struct KiwiVarRefType* KiwiVarRef;
|
||||||
typedef struct KiwiConstraintRefType* KiwiConstraintRef;
|
typedef struct KiwiConstraintRefType* KiwiConstraintRef;
|
||||||
|
|
||||||
struct KiwiTerm {
|
typedef struct KiwiTerm {
|
||||||
KiwiVarRef var;
|
KiwiVarRef var;
|
||||||
double coefficient;
|
double coefficient;
|
||||||
};
|
} KiwiTerm;
|
||||||
|
|
||||||
typedef struct KiwiExpression {
|
typedef struct KiwiExpression {
|
||||||
double constant;
|
double constant;
|
||||||
int term_count;
|
int term_count;
|
||||||
struct KiwiTerm terms[1]; // LuaJIT: struct KiwiTerm terms_[?];
|
KiwiTerm terms[1]; // LuaJIT: struct KiwiTerm terms_[?];
|
||||||
}* KiwiExpressionPtr;
|
} KiwiExpression;
|
||||||
|
|
||||||
typedef const struct KiwiExpression* KiwiExpressionConstPtr;
|
|
||||||
|
|
||||||
typedef struct KiwiErr {
|
typedef struct KiwiErr {
|
||||||
enum KiwiErrKind kind;
|
enum KiwiErrKind kind;
|
||||||
const char* message;
|
const char* message;
|
||||||
bool must_free;
|
bool must_free;
|
||||||
} const* KiwiErrPtr;
|
} KiwiErr;
|
||||||
|
|
||||||
struct KiwiSolver;
|
typedef struct KiwiSolver KiwiSolver;
|
||||||
typedef struct KiwiSolver* KiwiSolverPtr;
|
|
||||||
|
|
||||||
KiwiVarRef kiwi_var_new(const char* name);
|
KiwiVarRef kiwi_var_new(const char* name);
|
||||||
void kiwi_var_del(KiwiVarRef var);
|
void kiwi_var_del(KiwiVarRef var);
|
||||||
@@ -64,32 +58,37 @@ double kiwi_var_value(KiwiVarRef var);
|
|||||||
void kiwi_var_set_value(KiwiVarRef var, double value);
|
void kiwi_var_set_value(KiwiVarRef var, double value);
|
||||||
int kiwi_var_eq(KiwiVarRef var, KiwiVarRef other);
|
int kiwi_var_eq(KiwiVarRef var, KiwiVarRef other);
|
||||||
|
|
||||||
KiwiConstraintRef
|
void kiwi_expression_del_vars(KiwiExpression* expr);
|
||||||
kiwi_constraint_new(KiwiExpressionConstPtr expression, enum KiwiRelOp op, double strength);
|
|
||||||
|
KiwiConstraintRef kiwi_constraint_new(
|
||||||
|
const KiwiExpression* lhs,
|
||||||
|
const KiwiExpression* rhs,
|
||||||
|
enum KiwiRelOp op,
|
||||||
|
double strength
|
||||||
|
);
|
||||||
void kiwi_constraint_del(KiwiConstraintRef constraint);
|
void kiwi_constraint_del(KiwiConstraintRef constraint);
|
||||||
KiwiConstraintRef kiwi_constraint_clone(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);
|
||||||
|
|
||||||
bool kiwi_constraint_violated(KiwiConstraintRef constraint);
|
bool kiwi_constraint_violated(KiwiConstraintRef constraint);
|
||||||
int kiwi_constraint_expression(KiwiConstraintRef constraint, KiwiExpressionPtr out, int out_size);
|
int kiwi_constraint_expression(KiwiConstraintRef constraint, KiwiExpression* out, int out_size);
|
||||||
|
|
||||||
KiwiErrPtr kiwi_solver_add_constraint(KiwiSolverPtr sp, KiwiConstraintRef constraint);
|
KiwiSolver* kiwi_solver_new();
|
||||||
KiwiErrPtr kiwi_solver_remove_constraint(KiwiSolverPtr sp, KiwiConstraintRef constraint);
|
void kiwi_solver_del(KiwiSolver* sp);
|
||||||
bool kiwi_solver_has_constraint(KiwiSolverPtr sp, KiwiConstraintRef constraint);
|
|
||||||
KiwiErrPtr kiwi_solver_add_edit_var(KiwiSolverPtr sp, KiwiVarRef var, double strength);
|
const KiwiErr* kiwi_solver_add_constraint(KiwiSolver* sp, KiwiConstraintRef constraint);
|
||||||
KiwiErrPtr kiwi_solver_remove_edit_var(KiwiSolverPtr sp, KiwiVarRef var);
|
const KiwiErr* kiwi_solver_remove_constraint(KiwiSolver* sp, KiwiConstraintRef constraint);
|
||||||
bool kiwi_solver_has_edit_var(KiwiSolverPtr sp, KiwiVarRef var);
|
bool kiwi_solver_has_constraint(const KiwiSolver* sp, KiwiConstraintRef constraint);
|
||||||
KiwiErrPtr kiwi_solver_suggest_value(KiwiSolverPtr sp, KiwiVarRef var, double value);
|
const KiwiErr* kiwi_solver_add_edit_var(KiwiSolver* sp, KiwiVarRef var, double strength);
|
||||||
void kiwi_solver_update_vars(KiwiSolverPtr sp);
|
const KiwiErr* kiwi_solver_remove_edit_var(KiwiSolver* sp, KiwiVarRef var);
|
||||||
void kiwi_solver_reset(KiwiSolverPtr sp);
|
bool kiwi_solver_has_edit_var(const KiwiSolver* sp, KiwiVarRef var);
|
||||||
void kiwi_solver_dump(KiwiSolverPtr sp);
|
const KiwiErr* kiwi_solver_suggest_value(KiwiSolver* sp, KiwiVarRef var, double value);
|
||||||
char* kiwi_solver_dumps(KiwiSolverPtr sp);
|
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);
|
||||||
|
|
||||||
KiwiSolverPtr kiwi_solver_new();
|
|
||||||
void kiwi_solver_del(KiwiSolverPtr sp);
|
|
||||||
// LuaJIT end
|
// LuaJIT end
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
239
kiwi.lua
239
kiwi.lua
@@ -28,33 +28,27 @@ enum KiwiErrKind {
|
|||||||
|
|
||||||
enum KiwiRelOp { LE, GE, EQ };
|
enum KiwiRelOp { LE, GE, EQ };
|
||||||
|
|
||||||
struct KiwiVarRefType;
|
|
||||||
struct KiwiConstraintRefType;
|
|
||||||
|
|
||||||
typedef struct KiwiVarRefType* KiwiVarRef;
|
typedef struct KiwiVarRefType* KiwiVarRef;
|
||||||
typedef struct KiwiConstraintRefType* KiwiConstraintRef;
|
typedef struct KiwiConstraintRefType* KiwiConstraintRef;
|
||||||
|
|
||||||
struct KiwiTerm {
|
typedef struct KiwiTerm {
|
||||||
KiwiVarRef var;
|
KiwiVarRef var;
|
||||||
double coefficient;
|
double coefficient;
|
||||||
};
|
} KiwiTerm;
|
||||||
|
|
||||||
typedef struct KiwiExpression {
|
typedef struct KiwiExpression {
|
||||||
double constant;
|
double constant;
|
||||||
int term_count;
|
int term_count;
|
||||||
struct KiwiTerm terms_[?];
|
KiwiTerm terms_[?];
|
||||||
}* KiwiExpressionPtr;
|
} KiwiExpression;
|
||||||
|
|
||||||
typedef const struct KiwiExpression* KiwiExpressionConstPtr;
|
|
||||||
|
|
||||||
typedef struct KiwiErr {
|
typedef struct KiwiErr {
|
||||||
enum KiwiErrKind kind;
|
enum KiwiErrKind kind;
|
||||||
const char* message;
|
const char* message;
|
||||||
bool must_free;
|
bool must_free;
|
||||||
} const* KiwiErrPtr;
|
} KiwiErr;
|
||||||
|
|
||||||
struct KiwiSolver;
|
typedef struct KiwiSolver KiwiSolver;
|
||||||
typedef struct KiwiSolver* KiwiSolverPtr;
|
|
||||||
|
|
||||||
KiwiVarRef kiwi_var_new(const char* name);
|
KiwiVarRef kiwi_var_new(const char* name);
|
||||||
void kiwi_var_del(KiwiVarRef var);
|
void kiwi_var_del(KiwiVarRef var);
|
||||||
@@ -66,38 +60,42 @@ double kiwi_var_value(KiwiVarRef var);
|
|||||||
void kiwi_var_set_value(KiwiVarRef var, double value);
|
void kiwi_var_set_value(KiwiVarRef var, double value);
|
||||||
int kiwi_var_eq(KiwiVarRef var, KiwiVarRef other);
|
int kiwi_var_eq(KiwiVarRef var, KiwiVarRef other);
|
||||||
|
|
||||||
KiwiConstraintRef
|
void kiwi_expression_del_vars(KiwiExpression* expr);
|
||||||
kiwi_constraint_new(KiwiExpressionConstPtr expression, enum KiwiRelOp op, double strength);
|
|
||||||
|
KiwiConstraintRef kiwi_constraint_new(
|
||||||
|
const KiwiExpression* lhs,
|
||||||
|
const KiwiExpression* rhs,
|
||||||
|
enum KiwiRelOp op,
|
||||||
|
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);
|
||||||
|
|
||||||
bool kiwi_constraint_violated(KiwiConstraintRef constraint);
|
bool kiwi_constraint_violated(KiwiConstraintRef constraint);
|
||||||
int kiwi_constraint_expression(KiwiConstraintRef constraint, KiwiExpressionPtr out, int out_size);
|
int kiwi_constraint_expression(KiwiConstraintRef constraint, KiwiExpression* out, int out_size);
|
||||||
|
|
||||||
KiwiErrPtr kiwi_solver_add_constraint(KiwiSolverPtr sp, KiwiConstraintRef constraint);
|
KiwiSolver* kiwi_solver_new();
|
||||||
KiwiErrPtr kiwi_solver_remove_constraint(KiwiSolverPtr sp, KiwiConstraintRef constraint);
|
void kiwi_solver_del(KiwiSolver* sp);
|
||||||
bool kiwi_solver_has_constraint(KiwiSolverPtr sp, KiwiConstraintRef constraint);
|
|
||||||
KiwiErrPtr kiwi_solver_add_edit_var(KiwiSolverPtr sp, KiwiVarRef var, double strength);
|
|
||||||
KiwiErrPtr kiwi_solver_remove_edit_var(KiwiSolverPtr sp, KiwiVarRef var);
|
|
||||||
bool kiwi_solver_has_edit_var(KiwiSolverPtr sp, KiwiVarRef var);
|
|
||||||
KiwiErrPtr kiwi_solver_suggest_value(KiwiSolverPtr sp, KiwiVarRef var, double value);
|
|
||||||
void kiwi_solver_update_vars(KiwiSolverPtr sp);
|
|
||||||
void kiwi_solver_reset(KiwiSolverPtr sp);
|
|
||||||
void kiwi_solver_dump(KiwiSolverPtr sp);
|
|
||||||
char* kiwi_solver_dumps(KiwiSolverPtr sp);
|
|
||||||
|
|
||||||
KiwiSolverPtr kiwi_solver_new();
|
const KiwiErr* kiwi_solver_add_constraint(KiwiSolver* sp, KiwiConstraintRef constraint);
|
||||||
void kiwi_solver_del(KiwiSolverPtr sp);
|
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);
|
||||||
|
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);
|
||||||
|
|
||||||
void free(void *);
|
void free(void *);
|
||||||
]])
|
]])
|
||||||
|
|
||||||
local strformat = string.format
|
local strformat = string.format
|
||||||
local ffi_cast, ffi_gc, ffi_istype, ffi_new, ffi_string =
|
local ffi_gc, ffi_istype, ffi_new, ffi_string = ffi.gc, ffi.istype, ffi.new, ffi.string
|
||||||
ffi.cast, ffi.gc, ffi.istype, ffi.new, ffi.string
|
|
||||||
|
|
||||||
local concat = table.concat
|
local concat = table.concat
|
||||||
local has_table_new, new_tab = pcall(require, "table.new")
|
local has_table_new, new_tab = pcall(require, "table.new")
|
||||||
@@ -161,46 +159,12 @@ kiwi.Expression = Expression
|
|||||||
local Constraint = ffi.typeof("struct KiwiConstraintRefType") --[[@as kiwi.Constraint]]
|
local Constraint = ffi.typeof("struct KiwiConstraintRefType") --[[@as kiwi.Constraint]]
|
||||||
kiwi.Constraint = Constraint
|
kiwi.Constraint = Constraint
|
||||||
|
|
||||||
--- Define a constraint with expressions as `a <= b`.
|
|
||||||
---@param a kiwi.Expression|kiwi.Term|kiwi.Var|number
|
|
||||||
---@param b kiwi.Expression|kiwi.Term|kiwi.Var|number
|
|
||||||
---@param strength? number
|
|
||||||
---@return kiwi.Constraint
|
|
||||||
function kiwi.le(a, b, strength)
|
|
||||||
return Constraint(a - b, "LE", strength)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Define a constraint with expressions as `a >= b`.
|
|
||||||
---@param a kiwi.Expression|kiwi.Term|kiwi.Var|number
|
|
||||||
---@param b kiwi.Expression|kiwi.Term|kiwi.Var|number
|
|
||||||
---@param strength? number
|
|
||||||
---@return kiwi.Constraint
|
|
||||||
function kiwi.ge(a, b, strength)
|
|
||||||
return Constraint(a - b, "GE", strength)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Define a constraint with expressions as `a == b`.
|
|
||||||
---@param a kiwi.Expression|kiwi.Term|kiwi.Var|number
|
|
||||||
---@param b kiwi.Expression|kiwi.Term|kiwi.Var|number
|
|
||||||
---@param strength? number
|
|
||||||
---@return kiwi.Constraint
|
|
||||||
function kiwi.eq(a, b, strength)
|
|
||||||
return Constraint(a - b, "EQ", strength)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function expr_gc(expr)
|
|
||||||
local terms_ = expr.terms_
|
|
||||||
for i = 0, expr.term_count - 1 do
|
|
||||||
ckiwi.kiwi_var_del(terms_[i].var)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param expr kiwi.Expression
|
---@param expr kiwi.Expression
|
||||||
---@param var kiwi.Var
|
---@param var kiwi.Var
|
||||||
---@param coeff number?
|
---@param coeff number?
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
local function add_expr_term(expr, var, coeff)
|
local function add_expr_term(expr, var, coeff)
|
||||||
local ret = ffi_gc(ffi_new(Expression, expr.term_count + 1), expr_gc) --[[@as kiwi.Expression]]
|
local ret = ffi_gc(ffi_new(Expression, expr.term_count + 1), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
||||||
for i = 0, expr.term_count - 1 do
|
for i = 0, expr.term_count - 1 do
|
||||||
local st = expr.terms_[i] --[[@as kiwi.Term]]
|
local st = expr.terms_[i] --[[@as kiwi.Term]]
|
||||||
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
||||||
@@ -219,8 +183,8 @@ end
|
|||||||
---@param var kiwi.Var
|
---@param var kiwi.Var
|
||||||
---@param coeff number?
|
---@param coeff number?
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
local function new_expr_one(constant, var, coeff)
|
local function new_expr_one_temp(constant, var, coeff)
|
||||||
local ret = ffi_gc(ffi_new(Expression, 1), expr_gc) --[[@as kiwi.Expression]]
|
local ret = ffi_new(Expression, 1) --[[@as kiwi.Expression]]
|
||||||
local dt = ret.terms_[0]
|
local dt = ret.terms_[0]
|
||||||
dt.var = ckiwi.kiwi_var_clone(var)
|
dt.var = ckiwi.kiwi_var_clone(var)
|
||||||
dt.coefficient = coeff or 1.0
|
dt.coefficient = coeff or 1.0
|
||||||
@@ -229,6 +193,14 @@ local function new_expr_one(constant, var, coeff)
|
|||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param constant number
|
||||||
|
---@param var kiwi.Var
|
||||||
|
---@param coeff number?
|
||||||
|
---@nodiscard
|
||||||
|
local function new_expr_one(constant, var, coeff)
|
||||||
|
return ffi_gc(new_expr_one_temp(constant, var, coeff), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]] ---@diagnostic disable-line: param-type-mismatch
|
||||||
|
end
|
||||||
|
|
||||||
---@param constant number
|
---@param constant number
|
||||||
---@param var1 kiwi.Var
|
---@param var1 kiwi.Var
|
||||||
---@param var2 kiwi.Var
|
---@param var2 kiwi.Var
|
||||||
@@ -236,7 +208,7 @@ end
|
|||||||
---@param coeff2 number?
|
---@param coeff2 number?
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
local function new_expr_pair(constant, var1, var2, coeff1, coeff2)
|
local function new_expr_pair(constant, var1, var2, coeff1, coeff2)
|
||||||
local ret = ffi_gc(ffi_new(Expression, 2), expr_gc) --[[@as kiwi.Expression]]
|
local ret = ffi_gc(ffi_new(Expression, 2), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
||||||
local dt = ret.terms_[0]
|
local dt = ret.terms_[0]
|
||||||
dt.var = ckiwi.kiwi_var_clone(var1)
|
dt.var = ckiwi.kiwi_var_clone(var1)
|
||||||
dt.coefficient = coeff1 or 1.0
|
dt.coefficient = coeff1 or 1.0
|
||||||
@@ -248,6 +220,73 @@ local function new_expr_pair(constant, var1, var2, coeff1, coeff2)
|
|||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local Strength = kiwi.Strength
|
||||||
|
local REQUIRED = Strength.REQUIRED
|
||||||
|
|
||||||
|
---@param lhs kiwi.Expression|kiwi.Term|kiwi.Var|number
|
||||||
|
---@param rhs kiwi.Expression|kiwi.Term|kiwi.Var|number
|
||||||
|
---@param op kiwi.RelOp
|
||||||
|
---@param strength? number
|
||||||
|
local function rel(lhs, rhs, op, strength)
|
||||||
|
local function to_expr(o)
|
||||||
|
if ffi_istype(Expression, o) then
|
||||||
|
return o --[[@as kiwi.Expression]]
|
||||||
|
elseif type(o) == "number" then
|
||||||
|
if o == 0 then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local ret = ffi_new(Expression, 0) --[[@as kiwi.Expression]]
|
||||||
|
ret.constant = o
|
||||||
|
ret.term_count = 0
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
local var
|
||||||
|
local coeff = 1.0
|
||||||
|
|
||||||
|
if ffi_istype(Var, o) then
|
||||||
|
var = o --[[@as kiwi.Var]]
|
||||||
|
elseif ffi_istype(Term, o) then
|
||||||
|
var = o.var
|
||||||
|
coeff = o.coefficient
|
||||||
|
else
|
||||||
|
error("Expected Expression|Term|Var|number, got " .. type(o) .. " instead")
|
||||||
|
end
|
||||||
|
return new_expr_one_temp(0.0, var, coeff)
|
||||||
|
end
|
||||||
|
|
||||||
|
return ffi_gc(
|
||||||
|
ckiwi.kiwi_constraint_new(to_expr(lhs), to_expr(rhs), op, strength or REQUIRED),
|
||||||
|
ckiwi.kiwi_constraint_del
|
||||||
|
) --[[@as kiwi.Constraint]]
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Define a constraint with expressions as `a <= b`.
|
||||||
|
---@param lhs kiwi.Expression|kiwi.Term|kiwi.Var|number
|
||||||
|
---@param rhs kiwi.Expression|kiwi.Term|kiwi.Var|number
|
||||||
|
---@param strength? number
|
||||||
|
---@return kiwi.Constraint
|
||||||
|
function kiwi.le(lhs, rhs, strength)
|
||||||
|
return rel(lhs, rhs, "LE", strength)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Define a constraint with expressions as `a >= b`.
|
||||||
|
---@param lhs kiwi.Expression|kiwi.Term|kiwi.Var|number
|
||||||
|
---@param rhs kiwi.Expression|kiwi.Term|kiwi.Var|number
|
||||||
|
---@param strength? number
|
||||||
|
---@return kiwi.Constraint
|
||||||
|
function kiwi.ge(lhs, rhs, strength)
|
||||||
|
return rel(lhs, rhs, "GE", strength)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Define a constraint with expressions as `a == b`.
|
||||||
|
---@param lhs kiwi.Expression|kiwi.Term|kiwi.Var|number
|
||||||
|
---@param rhs kiwi.Expression|kiwi.Term|kiwi.Var|number
|
||||||
|
---@param strength? number
|
||||||
|
---@return kiwi.Constraint
|
||||||
|
function kiwi.eq(lhs, rhs, strength)
|
||||||
|
return rel(lhs, rhs, "EQ", strength)
|
||||||
|
end
|
||||||
|
|
||||||
--- Variables are the values the constraint solver calculates.
|
--- Variables are the values the constraint solver calculates.
|
||||||
---@class kiwi.Var: ffi.ctype*
|
---@class kiwi.Var: ffi.ctype*
|
||||||
---@overload fun(name: string): kiwi.Var
|
---@overload fun(name: string): kiwi.Var
|
||||||
@@ -287,13 +326,20 @@ function Var_cls:toterm(coefficient)
|
|||||||
return Term(self, coefficient or 1.0)
|
return Term(self, coefficient or 1.0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Create a term from this variable.
|
||||||
|
---@param coefficient number?
|
||||||
|
---@param constant number?
|
||||||
|
---@return kiwi.Expression
|
||||||
|
function Var_cls:toexpr(coefficient, constant)
|
||||||
|
return new_expr_one(constant or 0.0, self, coefficient)
|
||||||
|
end
|
||||||
|
|
||||||
ffi.metatype(Var, {
|
ffi.metatype(Var, {
|
||||||
__index = Var_cls,
|
__index = Var_cls,
|
||||||
|
|
||||||
__new = function(_, name)
|
__new = function(_, name)
|
||||||
return ffi_gc(ckiwi.kiwi_var_new(name), ckiwi.kiwi_var_del)
|
return ffi_gc(ckiwi.kiwi_var_new(name), ckiwi.kiwi_var_del)
|
||||||
end,
|
end,
|
||||||
__gc = ckiwi.kiwi_var_del,
|
|
||||||
|
|
||||||
__mul = function(a, b)
|
__mul = function(a, b)
|
||||||
if type(a) == "number" then
|
if type(a) == "number" then
|
||||||
@@ -426,7 +472,7 @@ do
|
|||||||
---@param constant number
|
---@param constant number
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
local function mul_expr_constant(expr, constant)
|
local function mul_expr_constant(expr, constant)
|
||||||
local ret = ffi_gc(ffi_new(Expression, expr.term_count), expr_gc) --[[@as kiwi.Expression]]
|
local ret = ffi_gc(ffi_new(Expression, expr.term_count), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
||||||
for i = 0, expr.term_count - 1 do
|
for i = 0, expr.term_count - 1 do
|
||||||
local st = expr.terms_[i] --[[@as kiwi.Term]]
|
local st = expr.terms_[i] --[[@as kiwi.Term]]
|
||||||
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
||||||
@@ -444,7 +490,7 @@ do
|
|||||||
local function add_expr_expr(a, b)
|
local function add_expr_expr(a, b)
|
||||||
local a_count = a.term_count
|
local a_count = a.term_count
|
||||||
local b_count = b.term_count
|
local b_count = b.term_count
|
||||||
local ret = ffi_gc(ffi_new(Expression, a_count + b_count), expr_gc) --[[@as kiwi.Expression]]
|
local ret = ffi_gc(ffi_new(Expression, a_count + b_count), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
||||||
|
|
||||||
for i = 0, a_count - 1 do
|
for i = 0, a_count - 1 do
|
||||||
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
||||||
@@ -467,7 +513,7 @@ do
|
|||||||
---@param constant number
|
---@param constant number
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
local function new_expr_constant(expr, constant)
|
local function new_expr_constant(expr, constant)
|
||||||
local ret = ffi_gc(ffi_new(Expression, expr.term_count), expr_gc) --[[@as kiwi.Expression]]
|
local ret = ffi_gc(ffi_new(Expression, expr.term_count), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
||||||
|
|
||||||
for i = 0, expr.term_count - 1 do
|
for i = 0, expr.term_count - 1 do
|
||||||
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
||||||
@@ -528,7 +574,7 @@ do
|
|||||||
__index = Expression_cls,
|
__index = Expression_cls,
|
||||||
|
|
||||||
__new = function(_, terms, constant)
|
__new = function(_, terms, constant)
|
||||||
local e = ffi_gc(ffi_new(Expression, #terms), expr_gc) --[[@as kiwi.Expression]]
|
local e = ffi_gc(ffi_new(Expression, #terms), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
||||||
for i, t in ipairs(terms) do
|
for i, t in ipairs(terms) do
|
||||||
local dt = e.terms_[i - 1] --[[@as kiwi.Term]]
|
local dt = e.terms_[i - 1] --[[@as kiwi.Term]]
|
||||||
dt.var = ckiwi.kiwi_var_clone(t.var)
|
dt.var = ckiwi.kiwi_var_clone(t.var)
|
||||||
@@ -593,7 +639,7 @@ end
|
|||||||
--- Constraints can be built with arbitrary left and right hand expressions. But
|
--- Constraints can be built with arbitrary left and right hand expressions. But
|
||||||
--- ultimately they all have the form `expression [op] 0`.
|
--- ultimately they all have the form `expression [op] 0`.
|
||||||
---@class kiwi.Constraint: ffi.ctype*
|
---@class kiwi.Constraint: ffi.ctype*
|
||||||
---@overload fun(expr: kiwi.Expression, op: kiwi.RelOp?, strength: number?): kiwi.Constraint
|
---@overload fun(lhs: kiwi.Expression, rhs: kiwi.Expression?, op: kiwi.RelOp?, strength: number?): kiwi.Constraint
|
||||||
local Constraint_cls = {
|
local Constraint_cls = {
|
||||||
--- The strength of the constraint.
|
--- The strength of the constraint.
|
||||||
---@type fun(self: kiwi.Constraint): number
|
---@type fun(self: kiwi.Constraint): number
|
||||||
@@ -619,7 +665,7 @@ function Constraint_cls:expression()
|
|||||||
expr = ffi_new(Expression, n) --[[@as kiwi.Expression]]
|
expr = ffi_new(Expression, n) --[[@as kiwi.Expression]]
|
||||||
n = ckiwi.kiwi_constraint_expression(self, expr, n)
|
n = ckiwi.kiwi_constraint_expression(self, expr, n)
|
||||||
end
|
end
|
||||||
return ffi_gc(expr, expr_gc) --[[@as kiwi.Expression]] ---@diagnostic disable-line: param-type-mismatch
|
return ffi_gc(expr, ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]] ---@diagnostic disable-line: param-type-mismatch
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Create a constraint between a pair of variables with ratio.
|
--- Create a constraint between a pair of variables with ratio.
|
||||||
@@ -634,9 +680,20 @@ end
|
|||||||
---@nodiscard
|
---@nodiscard
|
||||||
function kiwi.new_pair_ratio_constraint(left, coeff, right, constant, op, strength)
|
function kiwi.new_pair_ratio_constraint(left, coeff, right, constant, op, strength)
|
||||||
assert(ffi_istype(Var, left) and ffi_istype(Var, right))
|
assert(ffi_istype(Var, left) and ffi_istype(Var, right))
|
||||||
return Constraint(new_expr_pair(-(constant or 0.0), right, left, -coeff), op, strength)
|
local lhs = ffi_new(Expression, 2) --[[@as kiwi.Expression]]
|
||||||
|
local dt = lhs.terms_[0]
|
||||||
|
dt.var = left
|
||||||
|
dt.coefficient = 1.0
|
||||||
|
dt = lhs.terms_[1]
|
||||||
|
dt.var = right
|
||||||
|
dt.coefficient = -coeff
|
||||||
|
lhs.constant = -(constant or 0.0)
|
||||||
|
lhs.term_count = 2
|
||||||
|
return Constraint(lhs, nil, op, strength)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local new_pair_ratio_constraint = kiwi.new_pair_ratio_constraint
|
||||||
|
|
||||||
--- Create a constraint between a pair of variables with ratio.
|
--- Create a constraint between a pair of variables with ratio.
|
||||||
--- The constraint is of the form `left [op|==] right + [constant|0.0]`.
|
--- The constraint is of the form `left [op|==] right + [constant|0.0]`.
|
||||||
---@param left kiwi.Var
|
---@param left kiwi.Var
|
||||||
@@ -647,8 +704,7 @@ end
|
|||||||
---@return kiwi.Constraint
|
---@return kiwi.Constraint
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function kiwi.new_pair_constraint(left, right, constant, op, strength)
|
function kiwi.new_pair_constraint(left, right, constant, op, strength)
|
||||||
assert(ffi_istype(Var, left) and ffi_istype(Var, right))
|
return new_pair_ratio_constraint(left, 1.0, right, constant, op, strength)
|
||||||
return Constraint(new_expr_pair(-(constant or 0.0), right, left, -1.0), op, strength)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Create a single term constraint
|
--- Create a single term constraint
|
||||||
@@ -661,18 +717,21 @@ end
|
|||||||
---@nodiscard
|
---@nodiscard
|
||||||
function kiwi.new_single_constraint(var, constant, op, strength)
|
function kiwi.new_single_constraint(var, constant, op, strength)
|
||||||
assert(ffi_istype(Var, var))
|
assert(ffi_istype(Var, var))
|
||||||
return Constraint(new_expr_one(-(constant or 0.0), var), op, strength)
|
local lhs = ffi_new(Expression, 1) --[[@as kiwi.Expression]]
|
||||||
|
local dt = lhs.terms_[0]
|
||||||
|
dt.var = var
|
||||||
|
dt.coefficient = 1.0
|
||||||
|
lhs.constant = -(constant or 0.0)
|
||||||
|
lhs.term_count = 1
|
||||||
|
return Constraint(lhs, nil, op, strength)
|
||||||
end
|
end
|
||||||
|
|
||||||
local Strength = kiwi.Strength
|
|
||||||
local REQUIRED = Strength.REQUIRED
|
|
||||||
|
|
||||||
ffi.metatype(Constraint, {
|
ffi.metatype(Constraint, {
|
||||||
__index = Constraint_cls,
|
__index = Constraint_cls,
|
||||||
|
|
||||||
__new = function(_, expr, op, strength)
|
__new = function(_, lhs, rhs, op, strength)
|
||||||
return ffi_gc(
|
return ffi_gc(
|
||||||
ckiwi.kiwi_constraint_new(expr, op or "EQ", strength or REQUIRED),
|
ckiwi.kiwi_constraint_new(lhs, rhs, op or "EQ", strength or REQUIRED),
|
||||||
ckiwi.kiwi_constraint_del
|
ckiwi.kiwi_constraint_del
|
||||||
)
|
)
|
||||||
end,
|
end,
|
||||||
@@ -692,7 +751,7 @@ ffi.metatype(Constraint, {
|
|||||||
local strength = self:strength()
|
local strength = self:strength()
|
||||||
return strformat(
|
return strformat(
|
||||||
"%s %s 0 | %s",
|
"%s %s 0 | %s",
|
||||||
self:expression(),
|
tostring(self:expression()),
|
||||||
ops[tonumber(self:op())],
|
ops[tonumber(self:op())],
|
||||||
strengths[strength] or tostring(strength)
|
strengths[strength] or tostring(strength)
|
||||||
)
|
)
|
||||||
@@ -731,7 +790,7 @@ local C = ffi.C
|
|||||||
---@field package must_free boolean
|
---@field package must_free boolean
|
||||||
---@overload fun(): kiwi.KiwiErr
|
---@overload fun(): kiwi.KiwiErr
|
||||||
local KiwiErr = ffi.typeof("struct KiwiErr") --[[@as kiwi.KiwiErr]]
|
local KiwiErr = ffi.typeof("struct KiwiErr") --[[@as kiwi.KiwiErr]]
|
||||||
--
|
|
||||||
---@param f fun(solver: kiwi.Solver, item: any, ...): kiwi.KiwiErr?
|
---@param f fun(solver: kiwi.Solver, item: any, ...): kiwi.KiwiErr?
|
||||||
---@param solver kiwi.Solver
|
---@param solver kiwi.Solver
|
||||||
---@param item any
|
---@param item any
|
||||||
@@ -842,10 +901,6 @@ kiwi.Solver = ffi.metatype("struct KiwiSolver", {
|
|||||||
__new = function(_)
|
__new = function(_)
|
||||||
return ffi_gc(ckiwi.kiwi_solver_new(), ckiwi.kiwi_solver_del)
|
return ffi_gc(ckiwi.kiwi_solver_new(), ckiwi.kiwi_solver_del)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
__tostring = function(self)
|
|
||||||
return strformat("kiwi.Solver(0x%X)", ffi_cast("intptr_t", ffi_cast("void*", self)))
|
|
||||||
end,
|
|
||||||
}) --[[@as kiwi.Solver]]
|
}) --[[@as kiwi.Solver]]
|
||||||
|
|
||||||
return kiwi
|
return kiwi
|
||||||
|
|||||||
Reference in New Issue
Block a user