Skip to content

Commit

Permalink
Add Rust LuaJIT FFI library
Browse files Browse the repository at this point in the history
  • Loading branch information
jkl1337 committed Mar 8, 2024
1 parent 8328fe6 commit 7a09429
Show file tree
Hide file tree
Showing 15 changed files with 866 additions and 10 deletions.
14 changes: 4 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,8 @@ ifdef FLTO
CCFLAGS += $(LTO_FLAGS)
endif

ifneq ($(is_gcc),)
#PCH := ljkiwi.hpp.gch
else
ifneq ($(is_clang),)
override CXXFLAGS += -pedantic -Wno-c99-extensions
#PCH := ljkiwi.hpp.pch
endif
ifneq ($(is_clang),)
override CXXFLAGS += -pedantic -Wno-c99-extensions
endif

override CPPFLAGS += -I$(SRCDIR) -I$(SRCDIR)/kiwi -I"$(LUA_INCDIR)"
Expand Down Expand Up @@ -136,9 +131,8 @@ mostlyclean:
clean: mostlyclean
$(RM) -f $(PCH)

ckiwi.o: $(PCH) ckiwi.cpp ckiwi.h $(kiwi_lib_srcs)
luakiwi.o: $(PCH) luakiwi-int.h luacompat.h $(kiwi_lib_srcs)
$(PCH): $(kiwi_lib_srcs)
ckiwi.o: ckiwi.cpp ckiwi.h $(kiwi_lib_srcs)
luakiwi.o: luakiwi-int.h luacompat.h $(kiwi_lib_srcs)

ljkiwi.$(LIB_EXT): $(objs)
$(CXX) $(CCFLAGS) $(LIBFLAG) -o $@ $(objs)
Expand Down
3 changes: 3 additions & 0 deletions kiwi.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ if not _G["KIWI_CKIWI"] then
local libpath = package.searchpath("rjkiwi", package.cpath)
if libpath then
RUST, ljkiwi = pcall(ffi.load, libpath)
if not RUST then
ljkiwi = nil
end
end
end

Expand Down
1 change: 1 addition & 0 deletions rjkiwi/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
8 changes: 8 additions & 0 deletions rjkiwi/.idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions rjkiwi/.idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions rjkiwi/.idea/rjkiwi.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions rjkiwi/.idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

82 changes: 82 additions & 0 deletions rjkiwi/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions rjkiwi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "rjkiwi"
version = "0.1.1"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[features]
default = ["mimalloc"]

[dependencies]
casuarius = "0.1.1"

[target.'cfg(not(target_os = "linux"))'.dependencies]
mimalloc = { version = "0.1", optional = true }

[target.'cfg(target_os = "linux")'.dependencies]
mimalloc = { version = "0.1", features = ["local_dynamic_tls"], optional = true }
169 changes: 169 additions & 0 deletions rjkiwi/src/constraint.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
use std::{
ffi::{c_double, c_int, c_uint, c_void},
ptr::{self, drop_in_place},
};

use casuarius::{Constraint, Expression, RelationalOperator, Term};

use crate::{
expr::{KiwiExpression, KiwiExpressionPtr},
util::*,
var::SolverVariable,
};

pub type KiwiConstraint = Constraint<SolverVariable>;

#[repr(C)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub enum KiwiRelOp {
LE,
GE,
EQ,
}

#[no_mangle]
pub unsafe extern "C" fn kiwi_constraint_type_info(sz_align: *mut c_uint) {
*sz_align.offset(0) = std::mem::size_of::<KiwiConstraint>() as c_uint;
*sz_align.offset(1) = std::mem::align_of::<KiwiConstraint>() as c_uint;
}

#[no_mangle]
pub unsafe extern "C" fn kiwi_constraint_init(
c: *mut KiwiConstraint,
lhs: *const KiwiExpressionPtr,
rhs: *const KiwiExpressionPtr,
op: KiwiRelOp,
strength: f64,
) {
let term_count = (if !lhs.is_null() {
(*lhs).term_count.max(0)
} else {
0
} + if !rhs.is_null() {
(*rhs).term_count.max(0)
} else {
0
}) as usize;

let mut terms = Vec::<Term<SolverVariable>>::new();
terms.reserve(term_count);

let mut constant = 0.0;

if !lhs.is_null() {
let lhs = KiwiExpression::from_raw(lhs);
terms.extend(
lhs.terms
.iter()
.filter_map(|t| match SolverVariable::try_from_raw(t.var) {
Some(var) => Some(Term::new(var, t.coefficient)),
None => None,
}),
);
constant += lhs.constant;
}
if !rhs.is_null() {
let rhs = KiwiExpression::from_raw(rhs);
terms.extend(
rhs.terms
.iter()
.filter_map(|t| match SolverVariable::try_from_raw(t.var) {
Some(var) => Some(Term::new(var, -t.coefficient)),
None => None,
}),
);
constant -= rhs.constant;
}

ptr::write(
c,
Constraint::new(
Expression::new(terms, constant),
match op {
KiwiRelOp::LE => RelationalOperator::LessOrEqual,
KiwiRelOp::GE => RelationalOperator::GreaterOrEqual,
KiwiRelOp::EQ => RelationalOperator::Equal,
},
strength,
),
);
}

#[no_mangle]
pub unsafe extern "C" fn kiwi_constraint_destroy(c: *mut KiwiConstraint) {
if let Some(c) = not_null_mut(c) {
drop_in_place(c);
}
}

#[no_mangle]
pub unsafe extern "C" fn kiwi_constraint_strength(c: *const KiwiConstraint) -> c_double {
match not_null_ref(c) {
Some(c) => c.strength(),
None => c_double::NAN,
}
}

#[no_mangle]
pub unsafe extern "C" fn kiwi_constraint_op(c: *const KiwiConstraint) -> KiwiRelOp {
match not_null_ref(c) {
Some(c) => match c.op() {
RelationalOperator::LessOrEqual => KiwiRelOp::LE,
RelationalOperator::GreaterOrEqual => KiwiRelOp::GE,
RelationalOperator::Equal => KiwiRelOp::EQ,
},
None => KiwiRelOp::EQ,
}
}

#[no_mangle]
pub unsafe extern "C" fn kiwi_constraint_violated(c: *const KiwiConstraint) -> bool {
const EPSILON: f64 = 1.0e-8;

match not_null_ref(c) {
Some(c) => {
let e = c.expr();
let value = e
.terms
.iter()
.map(|t| t.variable.get_value() * t.coefficient.into_inner())
.sum::<f64>()
+ e.constant.into_inner();
match c.op() {
RelationalOperator::LessOrEqual => value > EPSILON,
RelationalOperator::GreaterOrEqual => value < EPSILON,
RelationalOperator::Equal => value.abs() > EPSILON,
}
}
None => false,
}
}

#[no_mangle]
pub unsafe extern "C" fn kiwi_constraint_expression(
c: *const KiwiConstraint,
out: *mut KiwiExpressionPtr,
out_size: c_int,
) -> c_int {
match not_null_ref(c) {
Some(c) => {
let expr = c.expr();
let n_terms = expr.terms.len().min(c_int::MAX as usize) as c_int;
if out.is_null() || out_size < n_terms {
return n_terms;
}
let out = core::slice::from_raw_parts_mut(out as *mut (), n_terms as usize)
as *mut [()] as *mut KiwiExpression;

(*out).owner = out as *mut c_void;
(*out).term_count = n_terms;
(*out).constant = expr.constant.into();
for (o, i) in (*out).terms.iter_mut().zip(expr.terms.iter()) {
o.var = i.variable.retain_raw();
o.coefficient = i.coefficient.into();
}
n_terms
}
None => 0,
}
}
Loading

0 comments on commit 7a09429

Please sign in to comment.