From 08e9bf08e702f14de5690f91195d49b4c4f25a50 Mon Sep 17 00:00:00 2001 From: "John K. Luebs" Date: Tue, 27 Feb 2024 21:59:10 -0600 Subject: [PATCH] Initial implementation of tuple demonstration This allows allocating a buffer of double pointers pointing to the memory location in a bunch of variables. It is not particularly ergonomic as is, and it seems unlikely the real world performance benefit will exist. --- Makefile | 2 +- ckiwi/ckiwi.cpp | 28 ++++++++++++++++++++++++++++ ckiwi/ckiwi.h | 16 +++++++++++++++- kiwi.lua | 23 +++++++++++++++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f4b92af..78cc223 100644 --- a/Makefile +++ b/Makefile @@ -93,7 +93,7 @@ else endif override CPPFLAGS += -I$(SRCDIR) -I$(SRCDIR)/kiwi -I"$(LUA_INCDIR)" -override CXXFLAGS += -std=c++14 -fno-rtti $(CCFLAGS) +override CXXFLAGS += -std=c++17 -fno-rtti $(CCFLAGS) ifeq ($(OS),Windows_NT) override CPPFLAGS += -DLUA_BUILD_AS_DLL diff --git a/ckiwi/ckiwi.cpp b/ckiwi/ckiwi.cpp index 410656a..7ed5d5f 100644 --- a/ckiwi/ckiwi.cpp +++ b/ckiwi/ckiwi.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -373,4 +374,31 @@ char* kiwi_solver_dumps(const KiwiSolver* s) { return buf; } +void kiwi_tuple_init(KiwiTuple* tuple, int count, ...) { + if (lk_unlikely(!tuple)) + return; + + va_list args; + va_start(args, count); + for (int i = 0; i < count; ++i) { + auto* var = va_arg(args, KiwiVar*); + retain_unmanaged(var); + tuple->values[i] = &var->m_value; + } + tuple->count = count; + va_end(args); +} + +void kiwi_tuple_destroy(KiwiTuple* tuple) { + if (lk_unlikely(!tuple)) + return; + + for (int i = 0; i < tuple->count; ++i) { + auto* value = const_cast(tuple->values[i]); + release_unmanaged( + reinterpret_cast(reinterpret_cast(value) - offsetof(KiwiVar, m_value)) + ); + } +} + } // extern "C" diff --git a/ckiwi/ckiwi.h b/ckiwi/ckiwi.h index 7d3a201..86cb369 100644 --- a/ckiwi/ckiwi.h +++ b/ckiwi/ckiwi.h @@ -61,7 +61,7 @@ typedef struct KiwiExpression { #if defined(LJKIWI_LUAJIT_DEF) KiwiTerm terms_[?]; #elif defined(LJKIWI_USE_FAM_1) - KiwiTerm terms_[1]; // LuaJIT: struct KiwiTerm terms_[?]; + KiwiTerm terms_[1]; #else KiwiTerm terms_[]; #endif @@ -74,8 +74,22 @@ typedef struct KiwiErr { bool must_free; } KiwiErr; +typedef struct KiwiTuple { + int count; +#if defined(LJKIWI_LUAJIT_DEF) + const double* values[?]; +#elif defined(LJKIWI_USE_FAM_1) + const double* values[1]; +#else + const double* values[]; +#endif +} KiwiTuple; + struct KiwiSolver; +LJKIWI_EXP void kiwi_tuple_init(KiwiTuple* tuple, int count, ...); +LJKIWI_EXP void kiwi_tuple_destroy(KiwiTuple* tuple); + LJKIWI_EXP KiwiVar* kiwi_var_construct(const char* name); LJKIWI_EXP void kiwi_var_release(KiwiVar* var); LJKIWI_EXP void kiwi_var_retain(KiwiVar* var); diff --git a/kiwi.lua b/kiwi.lua index 68f62f5..ce5c7aa 100644 --- a/kiwi.lua +++ b/kiwi.lua @@ -64,8 +64,16 @@ typedef struct KiwiErr { bool must_free; } KiwiErr; +typedef struct KiwiTuple { + int count; + const double* values[?]; +} KiwiTuple; + struct KiwiSolver; +void kiwi_tuple_init(KiwiTuple* tuple, int count, ...); +void kiwi_tuple_destroy(KiwiTuple* tuple); + KiwiVar* kiwi_var_construct(const char* name); void kiwi_var_release(KiwiVar* var); void kiwi_var_retain(KiwiVar* var); @@ -196,6 +204,21 @@ function kiwi.is_constraint(o) return ffi_istype(Constraint, o) end +local Tuple = ffi.typeof("struct KiwiTuple") --[[@as kiwi.Tuple]] +kiwi.Tuple = Tuple + +---@class kiwi.Tuple: ffi.cdata* +---@field values ffi.cdata* +---@field count integer +---@overload fun(vars: kiwi.Var[]): kiwi.Tuple +ffi.metatype(Tuple, { + __new = function(self, vars) + local t = ffi_new(self, #vars) + ljkiwi.kiwi_tuple_init(t, #vars, unpack(vars)) + return ffi_gc(t, ljkiwi.kiwi_tuple_destroy) + end, +}) + ---@param expr kiwi.Expression ---@param var kiwi.Var ---@param coeff number?