huge
This commit is contained in:
264
kiwi.lua
264
kiwi.lua
@@ -4,20 +4,48 @@ local ffi
|
||||
do
|
||||
local ffi_loader = package.preload["ffi"]
|
||||
if ffi_loader == nil then
|
||||
return require("ckiwi")
|
||||
return require("ljkiwi")
|
||||
end
|
||||
ffi = ffi_loader() --[[@as ffilib]]
|
||||
end
|
||||
|
||||
local kiwi = {}
|
||||
|
||||
local ckiwi
|
||||
local ljkiwi
|
||||
do
|
||||
local cpath, err = package.searchpath("ckiwi", package.cpath)
|
||||
local cpath, err = package.searchpath("ljkiwi", package.cpath)
|
||||
if cpath == nil then
|
||||
error("kiwi dynamic library 'ckiwi' not found\n" .. err)
|
||||
error("kiwi dynamic library 'ljkiwi' not found\n" .. err)
|
||||
end
|
||||
ckiwi = ffi.load(cpath)
|
||||
ljkiwi = ffi.load(cpath)
|
||||
end
|
||||
kiwi.ljkiwi = ljkiwi
|
||||
|
||||
ffi.cdef([[
|
||||
void free(void *);
|
||||
|
||||
typedef struct KiwiTypeInfo {
|
||||
unsigned size;
|
||||
unsigned align;
|
||||
} KiwiTypeInfo;
|
||||
|
||||
extern KiwiTypeInfo kiwi_ti_KiwiVar, kiwi_ti_KiwiConstraint, kiwi_ti_KiwiSolver;
|
||||
|
||||
]])
|
||||
|
||||
for _, t in ipairs({ "KiwiVar", "KiwiConstraint", "KiwiSolver" }) do
|
||||
local tinfo = ljkiwi[("kiwi_ti_%s"):format(t)] --[[@as any]]
|
||||
ffi.cdef(
|
||||
[[
|
||||
typedef struct $ {
|
||||
unsigned char b_[$];
|
||||
} __attribute__((aligned($))) $;
|
||||
]],
|
||||
t,
|
||||
tinfo.size,
|
||||
tinfo.align,
|
||||
t
|
||||
)
|
||||
end
|
||||
|
||||
ffi.cdef([[
|
||||
@@ -37,17 +65,15 @@ enum KiwiErrKind {
|
||||
|
||||
enum KiwiRelOp { LE, GE, 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;
|
||||
KiwiConstraint* owner;
|
||||
KiwiTerm terms_[?];
|
||||
} KiwiExpression;
|
||||
|
||||
@@ -57,49 +83,52 @@ typedef struct KiwiErr {
|
||||
bool must_free;
|
||||
} KiwiErr;
|
||||
|
||||
typedef struct KiwiSolver { unsigned error_mask_; } KiwiSolver;
|
||||
struct KiwiSolver;
|
||||
|
||||
KiwiVarRef kiwi_var_new(const char* name);
|
||||
void kiwi_var_del(KiwiVarRef var);
|
||||
KiwiVarRef kiwi_var_clone(KiwiVarRef var);
|
||||
void kiwi_var_construct(const char* name, void* mem);
|
||||
void kiwi_var_release(KiwiVar* var);
|
||||
void kiwi_var_retain(KiwiVar* var);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
void kiwi_expression_del_vars(KiwiExpression* expr);
|
||||
void kiwi_expression_retain(KiwiExpression* expr);
|
||||
void kiwi_expression_destroy(KiwiExpression* expr);
|
||||
|
||||
KiwiConstraintRef kiwi_constraint_new(
|
||||
void kiwi_constraint_construct(
|
||||
const KiwiExpression* lhs,
|
||||
const KiwiExpression* rhs,
|
||||
enum KiwiRelOp op,
|
||||
double strength
|
||||
double strength,
|
||||
void* mem
|
||||
);
|
||||
void kiwi_constraint_del(KiwiConstraintRef constraint);
|
||||
void kiwi_constraint_release(KiwiConstraint* c);
|
||||
void kiwi_constraint_retain(KiwiConstraint* c);
|
||||
|
||||
double kiwi_constraint_strength(KiwiConstraintRef constraint);
|
||||
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);
|
||||
|
||||
void free(void *);
|
||||
]])
|
||||
|
||||
local strformat = string.format
|
||||
@@ -159,7 +188,7 @@ do
|
||||
end
|
||||
end
|
||||
|
||||
local Var = ffi.typeof("struct KiwiVarRefType") --[[@as kiwi.Var]]
|
||||
local Var = ffi.typeof("struct KiwiVar") --[[@as kiwi.Var]]
|
||||
kiwi.Var = Var
|
||||
|
||||
function kiwi.is_var(o)
|
||||
@@ -173,14 +202,14 @@ function kiwi.is_term(o)
|
||||
return ffi_istype(Term, o)
|
||||
end
|
||||
|
||||
local Expression = ffi.typeof("struct KiwiExpression") --[[@as kiwi.Expression]]
|
||||
local Expression = ffi.typeof("KiwiExpression") --[[@as kiwi.Expression]]
|
||||
kiwi.Expression = Expression
|
||||
|
||||
function kiwi.is_expression(o)
|
||||
return ffi_istype(Expression, o)
|
||||
end
|
||||
|
||||
local Constraint = ffi.typeof("struct KiwiConstraintRefType") --[[@as kiwi.Constraint]]
|
||||
local Constraint = ffi.typeof("KiwiConstraint") --[[@as kiwi.Constraint]]
|
||||
kiwi.Constraint = Constraint
|
||||
|
||||
function kiwi.is_constraint(o)
|
||||
@@ -192,18 +221,19 @@ end
|
||||
---@param coeff number?
|
||||
---@nodiscard
|
||||
local function add_expr_term(expr, var, coeff)
|
||||
local ret = ffi_gc(ffi_new(Expression, expr.term_count + 1), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
||||
local ret = ffi_gc(ffi_new(Expression, expr.term_count + 1), ljkiwi.kiwi_expression_destroy) --[[@as kiwi.Expression]]
|
||||
for i = 0, expr.term_count - 1 do
|
||||
local st = expr.terms_[i] --[[@as kiwi.Term]]
|
||||
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
||||
dt.var = ckiwi.kiwi_var_clone(st.var)
|
||||
dt.var = st.var
|
||||
dt.coefficient = st.coefficient
|
||||
end
|
||||
local dt = ret.terms_[expr.term_count]
|
||||
dt.var = ckiwi.kiwi_var_clone(var)
|
||||
dt.var = var
|
||||
dt.coefficient = coeff or 1.0
|
||||
ret.constant = expr.constant
|
||||
ret.term_count = expr.term_count + 1
|
||||
ljkiwi.kiwi_expression_retain(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
@@ -212,12 +242,13 @@ end
|
||||
---@param coeff number?
|
||||
---@nodiscard
|
||||
local function new_expr_one(constant, var, coeff)
|
||||
local ret = ffi_gc(ffi_new(Expression, 1), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
||||
local ret = ffi_gc(ffi_new(Expression, 1), ljkiwi.kiwi_expression_destroy) --[[@as kiwi.Expression]]
|
||||
local dt = ret.terms_[0]
|
||||
dt.var = ckiwi.kiwi_var_clone(var)
|
||||
dt.var = var
|
||||
dt.coefficient = coeff or 1.0
|
||||
ret.constant = constant
|
||||
ret.term_count = 1
|
||||
ljkiwi.kiwi_var_retain(var)
|
||||
return ret
|
||||
end
|
||||
|
||||
@@ -228,15 +259,16 @@ end
|
||||
---@param coeff2 number?
|
||||
---@nodiscard
|
||||
local function new_expr_pair(constant, var1, var2, coeff1, coeff2)
|
||||
local ret = ffi_gc(ffi_new(Expression, 2), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
||||
local ret = ffi_gc(ffi_new(Expression, 2), ljkiwi.kiwi_expression_destroy) --[[@as kiwi.Expression]]
|
||||
local dt = ret.terms_[0]
|
||||
dt.var = ckiwi.kiwi_var_clone(var1)
|
||||
dt.var = var1
|
||||
dt.coefficient = coeff1 or 1.0
|
||||
dt = ret.terms_[1]
|
||||
dt.var = ckiwi.kiwi_var_clone(var2)
|
||||
dt.var = var2
|
||||
dt.coefficient = coeff2 or 1.0
|
||||
ret.constant = constant
|
||||
ret.term_count = 2
|
||||
ljkiwi.kiwi_expression_retain(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
@@ -311,7 +343,9 @@ local function rel(lhs, rhs, op, strength)
|
||||
op_error(lhs, rhs, OP_NAMES[op])
|
||||
end
|
||||
|
||||
return ffi_gc(ckiwi.kiwi_constraint_new(el, er, op, strength or REQUIRED), ckiwi.kiwi_constraint_del) --[[@as kiwi.Constraint]]
|
||||
local c = ffi_new(Constraint)
|
||||
ljkiwi.kiwi_constraint_construct(el, er, op, strength or REQUIRED, c)
|
||||
return ffi_gc(c, ljkiwi.kiwi_constraint_release) --[[@as kiwi.Constraint]]
|
||||
end
|
||||
|
||||
--- Define a constraint with expressions as `a <= b`.
|
||||
@@ -357,22 +391,22 @@ do
|
||||
|
||||
--- Change the name of the variable.
|
||||
---@type fun(self: kiwi.Var, name: string)
|
||||
set_name = ckiwi.kiwi_var_set_name,
|
||||
set_name = ljkiwi.kiwi_var_set_name,
|
||||
|
||||
--- Get the current value of the variable.
|
||||
---@type fun(self: kiwi.Var): number
|
||||
value = ckiwi.kiwi_var_value,
|
||||
value = ljkiwi.kiwi_var_value,
|
||||
|
||||
--- Set the value of the variable.
|
||||
---@type fun(self: kiwi.Var, value: number)
|
||||
set = ckiwi.kiwi_var_set_value,
|
||||
set = ljkiwi.kiwi_var_set_value,
|
||||
}
|
||||
|
||||
--- Get the name of the variable.
|
||||
---@return string
|
||||
---@nodiscard
|
||||
function Var_cls:name()
|
||||
return ffi_string(ckiwi.kiwi_var_name(self))
|
||||
return ffi_string(ljkiwi.kiwi_var_name(self))
|
||||
end
|
||||
|
||||
--- Create a term from this variable.
|
||||
@@ -397,7 +431,9 @@ do
|
||||
}
|
||||
|
||||
function Var_mt:__new(name)
|
||||
return ffi_gc(ckiwi.kiwi_var_new(name), ckiwi.kiwi_var_del)
|
||||
local v = ffi_new(self)
|
||||
ljkiwi.kiwi_var_construct(name, v)
|
||||
return ffi_gc(v, ljkiwi.kiwi_var_release)
|
||||
end
|
||||
|
||||
function Var_mt.__mul(a, b)
|
||||
@@ -441,6 +477,10 @@ do
|
||||
return a + -b
|
||||
end
|
||||
|
||||
function Var_mt:__eq(other)
|
||||
return ljkiwi.kiwi_var_eq(self, other)
|
||||
end
|
||||
|
||||
function Var_mt:__tostring()
|
||||
return self:name() .. "(" .. self:value() .. ")"
|
||||
end
|
||||
@@ -482,11 +522,13 @@ do
|
||||
local Term_mt = { __index = Term_cls }
|
||||
|
||||
local function term_gc(term)
|
||||
ckiwi.kiwi_var_del(term.var)
|
||||
ljkiwi.kiwi_var_release(term.var)
|
||||
end
|
||||
|
||||
function Term_mt.__new(T, var, coefficient)
|
||||
return ffi_gc(ffi_new(T, ckiwi.kiwi_var_clone(var), coefficient or 1.0), term_gc)
|
||||
local t = ffi_gc(ffi_new(T, var, coefficient or 1.0), term_gc)
|
||||
ljkiwi.kiwi_var_retain(var)
|
||||
return t
|
||||
end
|
||||
|
||||
function Term_mt.__mul(a, b)
|
||||
@@ -542,6 +584,7 @@ do
|
||||
---@class kiwi.Expression: ffi.cdata*
|
||||
---@overload fun(constant: number, ...: kiwi.Term): kiwi.Expression
|
||||
---@field constant number
|
||||
---@field package owner ffi.cdata*
|
||||
---@field package term_count number
|
||||
---@field package terms_ ffi.cdata*
|
||||
---@operator mul(number): kiwi.Expression
|
||||
@@ -559,15 +602,16 @@ do
|
||||
---@param constant number
|
||||
---@nodiscard
|
||||
local function mul_expr_coeff(expr, constant)
|
||||
local ret = ffi_gc(ffi_new(Expression, expr.term_count), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
||||
local ret = ffi_gc(ffi_new(Expression, expr.term_count), ljkiwi.kiwi_expression_destroy) --[[@as kiwi.Expression]]
|
||||
for i = 0, expr.term_count - 1 do
|
||||
local st = expr.terms_[i] --[[@as kiwi.Term]]
|
||||
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
||||
dt.var = ckiwi.kiwi_var_clone(st.var)
|
||||
dt.var = st.var
|
||||
dt.coefficient = st.coefficient * constant
|
||||
end
|
||||
ret.constant = expr.constant * constant
|
||||
ret.term_count = expr.term_count
|
||||
ljkiwi.kiwi_expression_retain(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
@@ -577,22 +621,23 @@ do
|
||||
local function add_expr_expr(a, b)
|
||||
local a_count = a.term_count
|
||||
local b_count = b.term_count
|
||||
local ret = ffi_gc(ffi_new(Expression, a_count + b_count), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
||||
local ret = ffi_gc(ffi_new(Expression, a_count + b_count), ljkiwi.kiwi_expression_destroy) --[[@as kiwi.Expression]]
|
||||
|
||||
for i = 0, a_count - 1 do
|
||||
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
||||
local st = a.terms_[i] --[[@as kiwi.Term]]
|
||||
dt.var = ckiwi.kiwi_var_clone(st.var)
|
||||
dt.var = st.var
|
||||
dt.coefficient = st.coefficient
|
||||
end
|
||||
for i = 0, b_count - 1 do
|
||||
local dt = ret.terms_[a_count + i] --[[@as kiwi.Term]]
|
||||
local st = b.terms_[i] --[[@as kiwi.Term]]
|
||||
dt.var = ckiwi.kiwi_var_clone(st.var)
|
||||
dt.var = st.var
|
||||
dt.coefficient = st.coefficient
|
||||
end
|
||||
ret.constant = a.constant + b.constant
|
||||
ret.term_count = a_count + b_count
|
||||
ljkiwi.kiwi_expression_retain(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
@@ -600,16 +645,17 @@ do
|
||||
---@param constant number
|
||||
---@nodiscard
|
||||
local function new_expr_constant(expr, constant)
|
||||
local ret = ffi_gc(ffi_new(Expression, expr.term_count), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
||||
local ret = ffi_gc(ffi_new(Expression, expr.term_count), ljkiwi.kiwi_expression_destroy) --[[@as kiwi.Expression]]
|
||||
|
||||
for i = 0, expr.term_count - 1 do
|
||||
local dt = ret.terms_[i] --[[@as kiwi.Term]]
|
||||
local st = expr.terms_[i] --[[@as kiwi.Term]]
|
||||
dt.var = ckiwi.kiwi_var_clone(st.var)
|
||||
dt.var = st.var
|
||||
dt.coefficient = st.coefficient
|
||||
end
|
||||
ret.constant = constant
|
||||
ret.term_count = expr.term_count
|
||||
ljkiwi.kiwi_expression_retain(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
@@ -645,17 +691,18 @@ do
|
||||
__index = Expression_cls,
|
||||
}
|
||||
|
||||
function Expression_mt.__new(T, constant, ...)
|
||||
function Expression_mt:__new(constant, ...)
|
||||
local term_count = select("#", ...)
|
||||
local e = ffi_gc(ffi_new(T, term_count), ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
||||
local e = ffi_gc(ffi_new(self, term_count), ljkiwi.kiwi_expression_destroy) --[[@as kiwi.Expression]]
|
||||
e.term_count = term_count
|
||||
e.constant = constant
|
||||
for i = 1, term_count do
|
||||
local t = select(i, ...)
|
||||
local dt = e.terms_[i - 1] --[[@as kiwi.Term]]
|
||||
dt.var = ckiwi.kiwi_var_clone(t.var)
|
||||
dt.var = t.var
|
||||
dt.coefficient = t.coefficient
|
||||
end
|
||||
ljkiwi.kiwi_expression_retain(e)
|
||||
return e
|
||||
end
|
||||
|
||||
@@ -722,29 +769,29 @@ do
|
||||
local Constraint_cls = {
|
||||
--- The strength of the constraint.
|
||||
---@type fun(self: kiwi.Constraint): number
|
||||
strength = ckiwi.kiwi_constraint_strength,
|
||||
strength = ljkiwi.kiwi_constraint_strength,
|
||||
|
||||
--- The relational operator of the constraint.
|
||||
---@type fun(self: kiwi.Constraint): kiwi.RelOp
|
||||
op = ckiwi.kiwi_constraint_op,
|
||||
op = ljkiwi.kiwi_constraint_op,
|
||||
|
||||
--- Whether the constraint is violated in the current solution.
|
||||
---@type fun(self: kiwi.Constraint): boolean
|
||||
violated = ckiwi.kiwi_constraint_violated,
|
||||
violated = ljkiwi.kiwi_constraint_violated,
|
||||
}
|
||||
|
||||
--- The reduced expression defining the constraint.
|
||||
---@return kiwi.Expression
|
||||
---@nodiscard
|
||||
function Constraint_cls:expression()
|
||||
local SZ = 7 -- 2**7 bytes on x64
|
||||
local SZ = 7
|
||||
local expr = ffi_new(Expression, SZ) --[[@as kiwi.Expression]]
|
||||
local n = ckiwi.kiwi_constraint_expression(self, expr, SZ)
|
||||
local n = ljkiwi.kiwi_constraint_expression(self, expr, SZ)
|
||||
if n > SZ then
|
||||
expr = ffi_new(Expression, n) --[[@as kiwi.Expression]]
|
||||
n = ckiwi.kiwi_constraint_expression(self, expr, n)
|
||||
n = ljkiwi.kiwi_constraint_expression(self, expr, n)
|
||||
end
|
||||
return ffi_gc(expr, ckiwi.kiwi_expression_del_vars) --[[@as kiwi.Expression]]
|
||||
return ffi_gc(expr, ljkiwi.kiwi_expression_destroy) --[[@as kiwi.Expression]]
|
||||
end
|
||||
|
||||
--- Add the constraint to the solver.
|
||||
@@ -773,10 +820,9 @@ do
|
||||
}
|
||||
|
||||
function Constraint_mt:__new(lhs, rhs, op, strength)
|
||||
return ffi_gc(
|
||||
ckiwi.kiwi_constraint_new(lhs, rhs, op or "EQ", strength or REQUIRED),
|
||||
ckiwi.kiwi_constraint_del
|
||||
)
|
||||
local c = ffi_new(self)
|
||||
ljkiwi.kiwi_constraint_construct(lhs, rhs, op or "EQ", strength or REQUIRED, c)
|
||||
return ffi_gc(c, ljkiwi.kiwi_constraint_release)
|
||||
end
|
||||
|
||||
local OPS = { [0] = "<=", ">=", "==" }
|
||||
@@ -822,10 +868,9 @@ do
|
||||
tmpexpr.constant = constant ~= nil and constant or 0
|
||||
tmpexpr.term_count = 2
|
||||
|
||||
return ffi_gc(
|
||||
ckiwi.kiwi_constraint_new(tmpexpr, nil, op or "EQ", strength or REQUIRED),
|
||||
ckiwi.kiwi_constraint_del
|
||||
) --[[@as kiwi.Constraint]]
|
||||
local c = ffi_new(Constraint)
|
||||
ljkiwi.kiwi_constraint_construct(tmpexpr, nil, op or "EQ", strength or REQUIRED, c)
|
||||
return ffi_gc(c, ljkiwi.kiwi_constraint_release) --[[@as kiwi.Constraint]]
|
||||
end
|
||||
|
||||
local pair_ratio = constraints.pair_ratio
|
||||
@@ -858,10 +903,10 @@ do
|
||||
local t = tmpexpr.terms_[0]
|
||||
t.var = var
|
||||
t.coefficient = 1.0
|
||||
return ffi_gc(
|
||||
ckiwi.kiwi_constraint_new(tmpexpr, nil, op or "EQ", strength or REQUIRED),
|
||||
ckiwi.kiwi_constraint_del
|
||||
) --[[@as kiwi.Constraint]]
|
||||
|
||||
local c = ffi_new(Constraint)
|
||||
ljkiwi.kiwi_constraint_construct(tmpexpr, nil, op or "EQ", strength or REQUIRED, c)
|
||||
return ffi_gc(c, ljkiwi.kiwi_constraint_release) --[[@as kiwi.Constraint]]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -947,7 +992,7 @@ do
|
||||
C.free(err)
|
||||
end
|
||||
local errdata = new_error(kind, message, solver, item)
|
||||
local error_mask = solver and solver.error_mask_ or 0
|
||||
local error_mask = ljkiwi.kiwi_solver_get_error_mask(solver)
|
||||
return item,
|
||||
band(error_mask, lshift(1, kind --[[@as integer]])) == 0 and error(errdata)
|
||||
or errdata
|
||||
@@ -955,20 +1000,19 @@ do
|
||||
return item
|
||||
end
|
||||
---@class kiwi.Solver: ffi.cdata*
|
||||
---@field package error_mask_ integer
|
||||
---@overload fun(error_mask: (integer|(kiwi.ErrKind|integer)[] )?): kiwi.Solver
|
||||
local Solver_cls = {
|
||||
--- Test whether a constraint is in the solver.
|
||||
---@type fun(self: kiwi.Solver, constraint: kiwi.Constraint): boolean
|
||||
has_constraint = ckiwi.kiwi_solver_has_constraint,
|
||||
has_constraint = ljkiwi.kiwi_solver_has_constraint,
|
||||
|
||||
--- Test whether an edit variable has been added to the solver.
|
||||
---@type fun(self: kiwi.Solver, var: kiwi.Var): boolean
|
||||
has_edit_var = ckiwi.kiwi_solver_has_edit_var,
|
||||
has_edit_var = ljkiwi.kiwi_solver_has_edit_var,
|
||||
|
||||
--- Update the values of the external solver variables.
|
||||
---@type fun(self: kiwi.Solver)
|
||||
update_vars = ckiwi.kiwi_solver_update_vars,
|
||||
update_vars = ljkiwi.kiwi_solver_update_vars,
|
||||
|
||||
--- Reset the solver to the empty starting conditions.
|
||||
---
|
||||
@@ -978,11 +1022,11 @@ do
|
||||
--- when the entire system must change, since it can avoid unecessary
|
||||
--- heap (de)allocations.
|
||||
---@type fun(self: kiwi.Solver)
|
||||
reset = ckiwi.kiwi_solver_reset,
|
||||
reset = ljkiwi.kiwi_solver_reset,
|
||||
|
||||
--- Dump a representation of the solver to stdout.
|
||||
---@type fun(self: kiwi.Solver)
|
||||
dump = ckiwi.kiwi_solver_dump,
|
||||
dump = ljkiwi.kiwi_solver_dump,
|
||||
}
|
||||
|
||||
--- Sets the error mask for the solver.
|
||||
@@ -992,7 +1036,7 @@ do
|
||||
if type(mask) == "table" then
|
||||
mask = kiwi.error_mask(mask, invert)
|
||||
end
|
||||
self.error_mask_ = mask
|
||||
ljkiwi.kiwi_solver_set_error_mask(self, mask)
|
||||
end
|
||||
|
||||
---@generic T
|
||||
@@ -1017,7 +1061,7 @@ do
|
||||
---@param constraint kiwi.Constraint
|
||||
---@return kiwi.Constraint constraint, kiwi.Error?
|
||||
function Solver_cls:add_constraint(constraint)
|
||||
return try_solver(ckiwi.kiwi_solver_add_constraint, self, constraint)
|
||||
return try_solver(ljkiwi.kiwi_solver_add_constraint, self, constraint)
|
||||
end
|
||||
|
||||
--- Add constraints to the solver.
|
||||
@@ -1027,7 +1071,7 @@ do
|
||||
---@param constraints kiwi.Constraint[]
|
||||
---@return kiwi.Constraint[] constraints, kiwi.Error?
|
||||
function Solver_cls:add_constraints(constraints)
|
||||
return add_remove_items(self, constraints, ckiwi.kiwi_solver_add_constraint)
|
||||
return add_remove_items(self, constraints, ljkiwi.kiwi_solver_add_constraint)
|
||||
end
|
||||
|
||||
--- Remove a constraint from the solver.
|
||||
@@ -1036,7 +1080,7 @@ do
|
||||
---@param constraint kiwi.Constraint
|
||||
---@return kiwi.Constraint constraint, kiwi.Error?
|
||||
function Solver_cls:remove_constraint(constraint)
|
||||
return try_solver(ckiwi.kiwi_solver_remove_constraint, self, constraint)
|
||||
return try_solver(ljkiwi.kiwi_solver_remove_constraint, self, constraint)
|
||||
end
|
||||
|
||||
--- Remove constraints from the solver.
|
||||
@@ -1045,7 +1089,7 @@ do
|
||||
---@param constraints kiwi.Constraint[]
|
||||
---@return kiwi.Constraint[] constraints, kiwi.Error?
|
||||
function Solver_cls:remove_constraints(constraints)
|
||||
return add_remove_items(self, constraints, ckiwi.kiwi_solver_remove_constraint)
|
||||
return add_remove_items(self, constraints, ljkiwi.kiwi_solver_remove_constraint)
|
||||
end
|
||||
|
||||
--- Add an edit variables to the solver.
|
||||
@@ -1059,7 +1103,7 @@ do
|
||||
---@param strength number the strength of the edit variable (must be less than `Strength.REQUIRED`)
|
||||
---@return kiwi.Var var, kiwi.Error?
|
||||
function Solver_cls:add_edit_var(var, strength)
|
||||
return try_solver(ckiwi.kiwi_solver_add_edit_var, self, var, strength)
|
||||
return try_solver(ljkiwi.kiwi_solver_add_edit_var, self, var, strength)
|
||||
end
|
||||
|
||||
--- Add edit variables to the solver.
|
||||
@@ -1073,7 +1117,7 @@ do
|
||||
---@param strength number the strength of the edit variables (must be less than `Strength.REQUIRED`)
|
||||
---@return kiwi.Var[] vars, kiwi.Error?
|
||||
function Solver_cls:add_edit_vars(vars, strength)
|
||||
return add_remove_items(self, vars, ckiwi.kiwi_solver_add_edit_var, strength)
|
||||
return add_remove_items(self, vars, ljkiwi.kiwi_solver_add_edit_var, strength)
|
||||
end
|
||||
|
||||
--- Remove an edit variable from the solver.
|
||||
@@ -1082,7 +1126,7 @@ do
|
||||
---@param var kiwi.Var the edit variable to remove
|
||||
---@return kiwi.Var var, kiwi.Error?
|
||||
function Solver_cls:remove_edit_var(var)
|
||||
return try_solver(ckiwi.kiwi_solver_remove_edit_var, self, var)
|
||||
return try_solver(ljkiwi.kiwi_solver_remove_edit_var, self, var)
|
||||
end
|
||||
|
||||
--- Removes edit variables from the solver.
|
||||
@@ -1091,7 +1135,7 @@ do
|
||||
---@param vars kiwi.Var[] the edit variables to remove
|
||||
---@return kiwi.Var[] vars, kiwi.Error?
|
||||
function Solver_cls:remove_edit_vars(vars)
|
||||
return add_remove_items(self, vars, ckiwi.kiwi_solver_remove_edit_var)
|
||||
return add_remove_items(self, vars, ljkiwi.kiwi_solver_remove_edit_var)
|
||||
end
|
||||
|
||||
--- Suggest a value for the given edit variable.
|
||||
@@ -1104,7 +1148,7 @@ do
|
||||
---@param value number the suggested value
|
||||
---@return kiwi.Var var, kiwi.Error?
|
||||
function Solver_cls:suggest_value(var, value)
|
||||
return try_solver(ckiwi.kiwi_solver_suggest_value, self, var, value)
|
||||
return try_solver(ljkiwi.kiwi_solver_suggest_value, self, var, value)
|
||||
end
|
||||
|
||||
--- Suggest values for the given edit variables.
|
||||
@@ -1116,7 +1160,7 @@ do
|
||||
---@return kiwi.Var[] vars, number[] values, kiwi.Error?
|
||||
function Solver_cls:suggest_values(vars, values)
|
||||
for i, var in ipairs(vars) do
|
||||
local _, err = try_solver(ckiwi.kiwi_solver_suggest_value, self, var, values[i])
|
||||
local _, err = try_solver(ljkiwi.kiwi_solver_suggest_value, self, var, values[i])
|
||||
if err ~= nil then
|
||||
return vars, values, err
|
||||
end
|
||||
@@ -1128,7 +1172,7 @@ do
|
||||
---@return string
|
||||
---@nodiscard
|
||||
function Solver_cls:dumps()
|
||||
local cs = ckiwi.kiwi_solver_dumps(self)
|
||||
local cs = ljkiwi.kiwi_solver_dumps(self)
|
||||
local s = ffi_string(cs)
|
||||
C.free(cs)
|
||||
return s
|
||||
@@ -1138,17 +1182,23 @@ do
|
||||
__index = Solver_cls,
|
||||
}
|
||||
|
||||
local Solver = ffi.typeof("struct KiwiSolver") --[[@as kiwi.Solver]]
|
||||
kiwi.Solver = Solver
|
||||
|
||||
function Solver_mt:__new(error_mask)
|
||||
if type(error_mask) == "table" then
|
||||
error_mask = kiwi.error_mask(error_mask)
|
||||
end
|
||||
return ffi_gc(ckiwi.kiwi_solver_new(error_mask or 0), ckiwi.kiwi_solver_del)
|
||||
|
||||
local s = ffi_new(Solver)
|
||||
ljkiwi.kiwi_solver_construct(error_mask or 0, s)
|
||||
return ffi_gc(s, ljkiwi.kiwi_solver_destroy) --[[@as kiwi.Constraint]]
|
||||
end
|
||||
|
||||
kiwi.Solver = ffi.metatype("struct KiwiSolver", Solver_mt) --[[@as kiwi.Solver]]
|
||||
kiwi.Solver = ffi.metatype(Solver, Solver_mt) --[[@as kiwi.Solver]]
|
||||
|
||||
function kiwi.is_solver(s)
|
||||
return ffi_istype(kiwi.Solver, s)
|
||||
return ffi_istype(Solver, s)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user