diff --git a/src/c_wrapper.jl b/src/c_wrapper.jl index c9b468a..944b30d 100644 --- a/src/c_wrapper.jl +++ b/src/c_wrapper.jl @@ -156,29 +156,26 @@ struct _ScsDataWrapper{S,T} dual::Vector{Cdouble} slack::Vector{Cdouble} settings::ScsSettings{T} - options::Dict{Symbol,Union{String,T,Cdouble}} end -function _sanitize_options(::Type{T}, options) where {T} - option_dict = Dict{Symbol,Union{String,T,Cdouble}}() +function _load_settings!(settings::ScsSettings{T}, options) where {T} for (key, value) in options if key == :linear_solver continue elseif !hasfield(ScsSettings, key) msg = "Unrecognized option passed to SCS solver: $(key)" throw(ArgumentError(msg)) - elseif value isa Integer - option_dict[key] = convert(T, value) - elseif value isa AbstractFloat - option_dict[key] = convert(Cdouble, value) - elseif value isa AbstractString - option_dict[key] = convert(String, value) + end + if value isa AbstractString + GC.@preserve value begin + c_value = Base.cconvert(String, value) + c_str = Base.unsafe_convert(Cstring, c_value) + setproperty!(settings, key, c_str) + end else - msg = "Option with unsupported type: $key=>$(repr(value))" - throw(ArgumentError(msg)) + setproperty!(settings, key, value) end end - return option_dict end function raw_status(info::ScsInfo) @@ -353,8 +350,9 @@ function scs_solve( m, n, z, l, ep, ed = T(m), T(n), T(z), T(l), T(ep), T(ed) Avalues, Arowval, Acolptr = _to_sparse(T, A) Pvalues, Prowval, Pcolptr = _to_sparse(T, P) - option_dict = _sanitize_options(T, options) - option_dict[:warm_start] = convert(T, warm_start) + settings = ScsSettings(linear_solver) + _load_settings!(settings, options) + settings.warm_start = warm_start model = _ScsDataWrapper( linear_solver, m, @@ -388,8 +386,7 @@ function scs_solve( primal_sol, dual_sol, slack, - ScsSettings(linear_solver), - option_dict, + settings, ) Base.GC.@preserve model begin return _unsafe_scs_solve(model) @@ -432,17 +429,6 @@ function _unsafe_scs_solve(model::_ScsDataWrapper{S,T}) where {S,T} pointer(model.b), pointer(model.c), ) - for (key, value) in model.options - if value isa String - GC.@preserve value begin - c_value = Base.cconvert(String, value) - c_str = Base.unsafe_convert(Cstring, c_value) - setproperty!(model.settings, key, c_str) - end - else - setproperty!(model.settings, key, value) - end - end scs_work = scs_init(model.linear_solver, scs_data, scs_cone, model.settings) scs_solution = ScsSolution( pointer(model.primal), @@ -455,7 +441,7 @@ function _unsafe_scs_solve(model::_ScsDataWrapper{S,T}) where {S,T} scs_work, scs_solution, scs_info, - model.options[:warm_start]::T, + model.settings.warm_start, ) scs_finish(model.linear_solver, scs_work) # SCS does not flush stdout on exit, and the C stdout is not the same as diff --git a/test/test_problems.jl b/test/test_problems.jl index 9a86857..444662b 100644 --- a/test/test_problems.jl +++ b/test/test_problems.jl @@ -807,10 +807,6 @@ function test_options(T) ArgumentError("Unrecognized option passed to SCS solver: eps"), SCS.scs_solve(T, args...; eps_abs = 1e-12, eps = 1e-12), ) - @test_throws( - ArgumentError("Option with unsupported type: eps_abs=>:abc"), - SCS.scs_solve(T, args...; eps_abs = :abc), - ) tmpf = tempname() @test !isfile(tmpf) SCS.scs_solve(T, args...; eps_abs = 1e-12, write_data_filename = tmpf)