lib/osqp/solver.rb in osqp-0.1.3 vs lib/osqp/solver.rb in osqp-0.2.0

- old
+ new

@@ -2,21 +2,31 @@ class Solver def setup(p, q, a, l, u, **settings) # settings set = create_settings(settings) + # ensure bounds within OSQP infinity + l = l.map { |v| v < -FFI::OSQP_INFTY ? -FFI::OSQP_INFTY : v } + u = u.map { |v| v > FFI::OSQP_INFTY ? FFI::OSQP_INFTY : v } + # data - refs = [] + # do not assign directly to struct to keep refs m, n = shape(a) + p = csc_matrix(p, upper: true) + q = float_array(q) + a = csc_matrix(a) + l = float_array(l) + u = float_array(u) + data = FFI::Data.malloc data.n = n data.m = m - data.p = csc_matrix(p, refs, upper: true) - data.q = float_array(q, refs) - data.a = csc_matrix(a, refs) - data.l = float_array(l, refs) - data.u = float_array(u, refs) + data.p = p + data.q = q + data.a = a + data.l = l + data.u = u # work work = FFI::Workspace.malloc check_result FFI.osqp_setup(work.to_ptr.ref, data, set) @work = work @@ -102,22 +112,18 @@ raise Error, message end end - def float_array(arr, refs = nil) + def float_array(arr) # OSQP float = double - ptr = Fiddle::Pointer[arr.to_a.pack("d*")] - refs << ptr if refs - ptr + Fiddle::Pointer[arr.to_a.pack("d*")] end - def int_array(arr, refs = nil) + def int_array(arr) # OSQP int = long long - ptr = Fiddle::Pointer[arr.to_a.pack("q*")] - refs << ptr if refs - ptr + Fiddle::Pointer[arr.to_a.pack("q*")] end def read_float_array(ptr, size) # OSQP float = double ptr[0, size * Fiddle::SIZEOF_DOUBLE].unpack("d*") @@ -127,11 +133,11 @@ idx = char_ptr.index { |v| v == 0 } char_ptr[0, idx].map(&:chr).join end # TODO add support sparse matrices - def csc_matrix(mtx, refs, upper: false) + def csc_matrix(mtx, upper: false) mtx = mtx.to_a m, n = shape(mtx) cx = [] @@ -151,14 +157,17 @@ # cumulative column values cp << cx.size end nnz = cx.size - cx = float_array(cx, refs) - ci = int_array(ci, refs) - cp = int_array(cp, refs) + cx = float_array(cx) + ci = int_array(ci) + cp = int_array(cp) - FFI.csc_matrix(m, n, nnz, cx, ci, cp) + ptr = FFI.csc_matrix(m, n, nnz, cx, ci, cp) + # save refs + ptr.instance_variable_set(:@osqp_refs, [cx, ci, cp]) + ptr end def dimensions data = FFI::Data.new(@work.data) [data.m, data.n]