diff --git a/Project.toml b/Project.toml index aaec436..8eef7f1 100644 --- a/Project.toml +++ b/Project.toml @@ -11,8 +11,8 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [compat] -NLPModels = "0.21" -NLPModelsModifiers = "0.7" +NLPModels = "0.22" +NLPModelsModifiers = "0.8" julia = "^1.6" [extras] diff --git a/src/allocs_model.jl b/src/allocs_model.jl index 8e571b4..0fd43b7 100644 --- a/src/allocs_model.jl +++ b/src/allocs_model.jl @@ -139,24 +139,39 @@ function test_allocs_nlpmodels(nlp::AbstractNLPModel; linear_api = false, exclud x = get_x0(nlp) vals = Vector{eltype(x)}(undef, nnzj) fun = Symbol(:jac_, type, :_coord!) - eval(fun)(nlp, x, vals) - nlp_allocations[fun] = @allocated eval(fun)(nlp, x, vals) + if type == :lin + eval(fun)(nlp, vals) + nlp_allocations[fun] = @allocated eval(fun)(nlp, vals) + else + eval(fun)(nlp, x, vals) + nlp_allocations[fun] = @allocated eval(fun)(nlp, x, vals) + end end if !(jprod in exclude) x = get_x0(nlp) v = copy(x) Jv = Vector{eltype(x)}(undef, nn) fun = Symbol(:jprod_, type, :!) - eval(fun)(nlp, x, v, Jv) - nlp_allocations[fun] = @allocated eval(fun)(nlp, x, v, Jv) + if type == :lin + eval(fun)(nlp, v, Jv) + nlp_allocations[fun] = @allocated eval(fun)(nlp, v, Jv) + else + eval(fun)(nlp, x, v, Jv) + nlp_allocations[fun] = @allocated eval(fun)(nlp, x, v, Jv) + end end if !(jtprod in exclude) x = get_x0(nlp) v = copy(get_y0(nlp)[1:nn]) Jtv = similar(x) fun = Symbol(:jtprod_, type, :!) - eval(fun)(nlp, x, v, Jtv) - nlp_allocations[fun] = @allocated eval(fun)(nlp, x, v, Jtv) + if type == :lin + eval(fun)(nlp, v, Jtv) + nlp_allocations[fun] = @allocated eval(fun)(nlp, v, Jtv) + else + eval(fun)(nlp, x, v, Jtv) + nlp_allocations[fun] = @allocated eval(fun)(nlp, x, v, Jtv) + end end if !(jac_op in exclude) x = get_x0(nlp) @@ -167,7 +182,7 @@ function test_allocs_nlpmodels(nlp::AbstractNLPModel; linear_api = false, exclud w = randn(eltype(x), nn) fun = Symbol(:jac_, type, :_op!) if type == :lin - J = jac_lin_op!(nlp, x, Jv, Jtv) + J = jac_lin_op!(nlp, Jv, Jtv) mul!(Jv, J, v) nlp_allocations[Symbol(:jac_lin_op_prod!)] = @allocated mul!(Jv, J, v) Jt = J' diff --git a/src/nlp/check-dimensions.jl b/src/nlp/check-dimensions.jl index 9a6256f..93943ce 100644 --- a/src/nlp/check-dimensions.jl +++ b/src/nlp/check-dimensions.jl @@ -138,7 +138,6 @@ function check_nlp_dimensions( end if jac ∉ exclude @test_throws DimensionError jac(nlp, badx) - linear_api && nlp.meta.nlin > 0 && @test_throws DimensionError jac_lin(nlp, badx) linear_api && nlp.meta.nnln > 0 && @test_throws DimensionError jac_nln(nlp, badx) end if jprod ∉ exclude @@ -149,11 +148,9 @@ function check_nlp_dimensions( @test_throws DimensionError jprod!(nlp, x, v, badJv) if linear_api && nlp.meta.nlin > 0 - @test_throws DimensionError jprod_lin(nlp, badx, v) - @test_throws DimensionError jprod_lin(nlp, x, badv) - @test_throws DimensionError jprod_lin!(nlp, badx, v, Jv_lin) - @test_throws DimensionError jprod_lin!(nlp, x, badv, Jv_lin) - @test_throws DimensionError jprod_lin!(nlp, x, v, badJv_lin) + @test_throws DimensionError jprod_lin(nlp, badv) + @test_throws DimensionError jprod_lin!(nlp, badv, Jv_lin) + @test_throws DimensionError jprod_lin!(nlp, v, badJv_lin) end if linear_api && nlp.meta.nnln > 0 @@ -172,11 +169,9 @@ function check_nlp_dimensions( @test_throws DimensionError jtprod!(nlp, x, w, badJtw) if linear_api && nlp.meta.nlin > 0 - @test_throws DimensionError jtprod_lin(nlp, badx, w_lin) - @test_throws DimensionError jtprod_lin(nlp, x, badw_lin) - @test_throws DimensionError jtprod_lin!(nlp, badx, w_lin, Jtw) - @test_throws DimensionError jtprod_lin!(nlp, x, badw_lin, Jtw) - @test_throws DimensionError jtprod_lin!(nlp, x, w_lin, badJtw) + @test_throws DimensionError jtprod_lin(nlp, badw_lin) + @test_throws DimensionError jtprod_lin!(nlp, badw_lin, Jtw) + @test_throws DimensionError jtprod_lin!(nlp, w_lin, badJtw) end if linear_api && nlp.meta.nnln > 0 @@ -197,9 +192,7 @@ function check_nlp_dimensions( if linear_api && nlp.meta.nlin > 0 @test_throws DimensionError jac_lin_structure!(nlp, badjrows_lin, jcols_lin) @test_throws DimensionError jac_lin_structure!(nlp, jrows_lin, badjcols_lin) - @test_throws DimensionError jac_lin_coord(nlp, badx) - @test_throws DimensionError jac_lin_coord!(nlp, badx, jvals_lin) - @test_throws DimensionError jac_lin_coord!(nlp, x, badjvals_lin) + @test_throws DimensionError jac_lin_coord!(nlp, badjvals_lin) end if linear_api && nlp.meta.nnln > 0 @@ -222,10 +215,8 @@ function check_nlp_dimensions( @test_throws DimensionError jac_op!(nlp, jrows, jcols, jvals, Jv, badJtw) if linear_api && nlp.meta.nlin > 0 - @test_throws DimensionError jac_lin_op(nlp, badx) - @test_throws DimensionError jac_lin_op!(nlp, badx, Jv_lin, Jtw) - @test_throws DimensionError jac_lin_op!(nlp, x, badJv_lin, Jtw) - @test_throws DimensionError jac_lin_op!(nlp, x, Jv_lin, badJtw) + @test_throws DimensionError jac_lin_op!(nlp, badJv_lin, Jtw) + @test_throws DimensionError jac_lin_op!(nlp, Jv_lin, badJtw) @test_throws DimensionError jac_lin_op!( nlp, badjrows_lin, diff --git a/src/nlp/consistency.jl b/src/nlp/consistency.jl index 78b91db..72012dc 100644 --- a/src/nlp/consistency.jl +++ b/src/nlp/consistency.jl @@ -395,14 +395,14 @@ function consistent_functions(nlps; linear_api = false, rtol = 1.0e-8, exclude = end if (intersect([jac, jac_coord], exclude) == []) && test_lin - Js = [jac_lin(nlp, x) for nlp in nlps] + Js = [jac_lin(nlp) for nlp in nlps] Jmin = minimum(map(norm, Js)) for i = 1:N vi = norm(Js[i]) for j = (i + 1):N @test isapprox(vi, norm(Js[j]), atol = rtol * max(Jmin, 1.0)) end - V = jac_lin_coord(nlps[i], x) + V = jac_lin_coord(nlps[i]) I, J = jac_lin_structure(nlps[i]) @test length(I) == length(J) == length(V) == nlps[i].meta.lin_nnzj @test isapprox(sparse(I, J, V, mlin, n), Js[i], atol = rtol * max(Jmin, 1.0)) @@ -411,7 +411,7 @@ function consistent_functions(nlps; linear_api = false, rtol = 1.0e-8, exclude = @test IS == I @test JS == J tmp_V = zeros(nlps[i].meta.lin_nnzj) - jac_lin_coord!(nlps[i], x, tmp_V) + jac_lin_coord!(nlps[i], tmp_V) @test tmp_V == V end end @@ -470,26 +470,26 @@ function consistent_functions(nlps; linear_api = false, rtol = 1.0e-8, exclude = end if (!(jprod in exclude)) && test_lin - Jlinops = Any[jac_lin_op(nlp, x) for nlp in nlps] - Jps = Any[jprod_lin(nlp, x, v) for nlp in nlps] + Jlinops = Any[jac_lin_op(nlp) for nlp in nlps] + Jps = Any[jprod_lin(nlp, v) for nlp in nlps] for i = 1:N @test isapprox(Jps[i], Jlinops[i] * v, atol = rtol * max(Jmin, 1.0)) vi = norm(Jps[i]) for j = (i + 1):N @test isapprox(vi, norm(Jps[j]), atol = rtol * max(Jmin, 1.0)) end - tmpjv = jprod_lin!(nlps[i], x, v, tmp_mlin) + tmpjv = jprod_lin!(nlps[i], v, tmp_mlin) @test isapprox(tmpjv, tmp_mlin, atol = rtol * max(Jmin, 1.0)) @test isapprox(Jps[i], tmp_mlin, atol = rtol * max(Jmin, 1.0)) fill!(tmp_mlin, 0) - J = jac_lin_op!(nlps[i], x, tmp_mlin, tmp_n) + J = jac_lin_op!(nlps[i], tmp_mlin, tmp_n) res = J * v @test isapprox(res, Jps[i], atol = rtol * max(Jmin, 1.0)) @test isapprox(res, tmp_mlin, atol = rtol * max(Jmin, 1.0)) if !(jac_coord in exclude) rows, cols = jac_lin_structure(nlps[i]) - vals = jac_lin_coord(nlps[i], x) + vals = jac_lin_coord(nlps[i]) jprod_lin!(nlps[i], rows, cols, vals, v, tmp_mlin) @test isapprox(Jps[i], tmp_mlin, atol = rtol * max(Jmin, 1.0)) @@ -564,25 +564,25 @@ function consistent_functions(nlps; linear_api = false, rtol = 1.0e-8, exclude = if (!(jtprod in exclude)) && test_lin w = 10 * [-(-1.0)^i for i = 1:mlin] - Jtps = Any[jtprod_lin(nlp, x, w) for nlp in nlps] + Jtps = Any[jtprod_lin(nlp, w) for nlp in nlps] for i = 1:N @test isapprox(Jtps[i], Jlinops[i]' * w, atol = rtol * max(Jmin, 1.0)) vi = norm(Jtps[i]) for j = (i + 1):N @test isapprox(vi, norm(Jtps[j]), atol = rtol * max(Jmin, 1.0)) end - tmpjtv = jtprod_lin!(nlps[i], x, w, tmp_n) + tmpjtv = jtprod_lin!(nlps[i], w, tmp_n) @test isapprox(Jtps[i], tmp_n, atol = rtol * max(Jmin, 1.0)) @test isapprox(tmpjtv, tmp_n, atol = rtol * max(Jmin, 1.0)) fill!(tmp_n, 0) - J = jac_lin_op!(nlps[i], x, tmp_mlin, tmp_n) + J = jac_lin_op!(nlps[i], tmp_mlin, tmp_n) res = J' * w @test isapprox(res, Jtps[i], atol = rtol * max(Jmin, 1.0)) @test isapprox(res, tmp_n, atol = rtol * max(Jmin, 1.0)) if !(jac_coord in exclude) rows, cols = jac_lin_structure(nlps[i]) - vals = jac_lin_coord(nlps[i], x) + vals = jac_lin_coord(nlps[i]) jtprod_lin!(nlps[i], rows, cols, vals, w, tmp_n) @test isapprox(Jtps[i], tmp_n, atol = rtol * max(Jmin, 1.0)) diff --git a/src/nlp/coord-memory.jl b/src/nlp/coord-memory.jl index b72b4e9..99385f8 100644 --- a/src/nlp/coord-memory.jl +++ b/src/nlp/coord-memory.jl @@ -48,11 +48,11 @@ function coord_memory_nlp(nlp::AbstractNLPModel; linear_api = false, exclude = [ al2 = @allocated jac_coord!(nlp, x, vals) @test (al2 < al1) | (al2 == 0) if linear_api && nlp.meta.nlin > 0 - vals = jac_lin_coord(nlp, x) - al1 = @allocated vals = jac_lin_coord(nlp, x) + vals = jac_lin_coord(nlp) + al1 = @allocated vals = jac_lin_coord(nlp) V = zeros(nlp.meta.lin_nnzj) - jac_lin_coord!(nlp, x, vals) - al2 = @allocated jac_lin_coord!(nlp, x, vals) + jac_lin_coord!(nlp, vals) + al2 = @allocated jac_lin_coord!(nlp, vals) @test (al2 < al1) | (al2 == 0) end if linear_api && nlp.meta.nnln > 0 diff --git a/src/nlp/multiple-precision.jl b/src/nlp/multiple-precision.jl index befa746..6dbd8ae 100644 --- a/src/nlp/multiple-precision.jl +++ b/src/nlp/multiple-precision.jl @@ -74,8 +74,8 @@ function multiple_precision_nlp( end if linear_api && nlp.meta.nlin > 0 @test cons ∈ exclude || typeof(cons_lin(nlp, x)) == S - @test jac ∈ exclude || eltype(jac_lin(nlp, x)) == T - @test jac_op ∈ exclude || eltype(jac_lin_op(nlp, x)) == T + @test jac ∈ exclude || eltype(jac_lin(nlp)) == T + @test jac_op ∈ exclude || eltype(jac_lin_op(nlp)) == T end if jac_coord ∉ exclude && jac_op ∉ exclude rows, cols = jac_structure(nlp) @@ -94,7 +94,7 @@ function multiple_precision_nlp( end if linear_api && nlp.meta.nlin > 0 rows, cols = jac_lin_structure(nlp) - vals = jac_lin_coord(nlp, x) + vals = jac_lin_coord(nlp) @test typeof(vals) == S Av = fill!(S(undef, nlp.meta.nlin), T(0)) Atv = fill!(S(undef, nlp.meta.nvar), T(0)) diff --git a/src/nlp/problems/hs14.jl b/src/nlp/problems/hs14.jl index 682e709..cae8340 100644 --- a/src/nlp/problems/hs14.jl +++ b/src/nlp/problems/hs14.jl @@ -161,10 +161,10 @@ function NLPModels.jac_nln_structure!( return rows, cols end -function NLPModels.jac_lin_coord!(nlp::HS14, x::AbstractVector{T}, vals::AbstractVector) where {T} - @lencheck 2 x +function NLPModels.jac_lin_coord!(nlp::HS14, vals::AbstractVector) @lencheck 2 vals increment!(nlp, :neval_jac_lin) + T = eltype(vals) vals[1] = T(1) vals[2] = T(-2) return vals @@ -179,9 +179,9 @@ function NLPModels.jac_nln_coord!(nlp::HS14, x::AbstractVector, vals::AbstractVe return vals end -function NLPModels.jprod_lin!(nlp::HS14, x::AbstractVector, v::AbstractVector, Jv::AbstractVector) +function NLPModels.jprod_lin!(nlp::HS14, v::AbstractVector, Jv::AbstractVector) @lencheck 1 Jv - @lencheck 2 x v + @lencheck 2 v increment!(nlp, :neval_jprod_lin) Jv[1] = v[1] - 2 * v[2] return Jv @@ -204,8 +204,8 @@ function NLPModels.jtprod!(nlp::HS14, x::AbstractVector, v::AbstractVector, Jtv: return Jtv end -function NLPModels.jtprod_lin!(nlp::HS14, x::AbstractVector, v::AbstractVector, Jtv::AbstractVector) - @lencheck 2 x Jtv +function NLPModels.jtprod_lin!(nlp::HS14, v::AbstractVector, Jtv::AbstractVector) + @lencheck 2 Jtv @lencheck 1 v increment!(nlp, :neval_jtprod_lin) Jtv[1] = v[1] diff --git a/src/nlp/problems/lincon.jl b/src/nlp/problems/lincon.jl index 41e2da0..ada32a4 100644 --- a/src/nlp/problems/lincon.jl +++ b/src/nlp/problems/lincon.jl @@ -197,10 +197,10 @@ function NLPModels.jac_lin_structure!( return rows, cols end -function NLPModels.jac_lin_coord!(nlp::LINCON, x::AbstractVector{T}, vals::AbstractVector) where {T} - @lencheck 15 x +function NLPModels.jac_lin_coord!(nlp::LINCON, vals::AbstractVector) @lencheck 17 vals increment!(nlp, :neval_jac_lin) + T = eltype(vals) vals[1] = T(15) vals[2] = T(1) vals[3] = T(2) @@ -221,8 +221,8 @@ function NLPModels.jac_lin_coord!(nlp::LINCON, x::AbstractVector{T}, vals::Abstr return vals end -function NLPModels.jprod_lin!(nlp::LINCON, x::AbstractVector, v::AbstractVector, Jv::AbstractVector) - @lencheck 15 x v +function NLPModels.jprod_lin!(nlp::LINCON, v::AbstractVector, Jv::AbstractVector) + @lencheck 15 v @lencheck 11 Jv increment!(nlp, :neval_jprod_lin) Jv[1] = 15 * v[15] @@ -241,11 +241,10 @@ end function NLPModels.jtprod_lin!( nlp::LINCON, - x::AbstractVector, v::AbstractVector, Jtv::AbstractVector, ) - @lencheck 15 x Jtv + @lencheck 15 Jtv @lencheck 11 v increment!(nlp, :neval_jtprod_lin) Jtv[1] = 1 * v[7] + 3 * v[8] diff --git a/src/nlp/problems/linsv.jl b/src/nlp/problems/linsv.jl index a20ddac..de60316 100644 --- a/src/nlp/problems/linsv.jl +++ b/src/nlp/problems/linsv.jl @@ -135,18 +135,18 @@ function NLPModels.jac_lin_structure!( return rows, cols end -function NLPModels.jac_lin_coord!(nlp::LINSV, x::AbstractVector{T}, vals::AbstractVector) where {T} - @lencheck 2 x +function NLPModels.jac_lin_coord!(nlp::LINSV, vals::AbstractVector) @lencheck 3 vals increment!(nlp, :neval_jac_lin) + T = eltype(vals) vals[1] = T(1) vals[2] = T(1) vals[3] = T(1) return vals end -function NLPModels.jprod_lin!(nlp::LINSV, x::AbstractVector, v::AbstractVector, Jv::AbstractVector) - @lencheck 2 x v Jv +function NLPModels.jprod_lin!(nlp::LINSV, v::AbstractVector, Jv::AbstractVector) + @lencheck 2 v Jv increment!(nlp, :neval_jprod_lin) Jv[1] = v[1] + v[2] Jv[2] = v[2] @@ -155,11 +155,10 @@ end function NLPModels.jtprod_lin!( nlp::LINSV, - x::AbstractVector, v::AbstractVector, Jtv::AbstractVector, ) - @lencheck 2 x v Jtv + @lencheck 2 v Jtv increment!(nlp, :neval_jtprod_lin) Jtv[1] = v[1] Jtv[2] = v[1] + v[2] diff --git a/src/nlp/problems/mgh01feas.jl b/src/nlp/problems/mgh01feas.jl index fb87b62..550566c 100644 --- a/src/nlp/problems/mgh01feas.jl +++ b/src/nlp/problems/mgh01feas.jl @@ -101,12 +101,11 @@ end function NLPModels.jac_lin_coord!( nls::MGH01Feas, - x::AbstractVector{T}, vals::AbstractVector, -) where {T} - @lencheck 2 x +) @lencheck 1 vals increment!(nls, :neval_jac_lin) + T = eltype(vals) vals .= T(1) return vals end @@ -126,11 +125,10 @@ end function NLPModels.jprod_lin!( nls::MGH01Feas, - x::AbstractVector, v::AbstractVector, Jv::AbstractVector, ) - @lencheck 2 x v + @lencheck 2 v @lencheck 1 Jv increment!(nls, :neval_jprod_lin) Jv[1] = v[1] @@ -166,11 +164,10 @@ end function NLPModels.jtprod_lin!( nls::MGH01Feas, - x::AbstractVector{T}, v::AbstractVector, - Jtv::AbstractVector, + Jtv::AbstractVector{T}, ) where {T} - @lencheck 2 x Jtv + @lencheck 2 Jtv @lencheck 1 v increment!(nls, :neval_jtprod_lin) Jtv[1] = v[1] diff --git a/src/nls/multiple-precision.jl b/src/nls/multiple-precision.jl index 76fea08..dda735a 100644 --- a/src/nls/multiple-precision.jl +++ b/src/nls/multiple-precision.jl @@ -87,8 +87,8 @@ function multiple_precision_nls( end if linear_api && nls.meta.nlin > 0 @test cons ∈ exclude || typeof(cons_lin(nls, x)) == S - @test jac ∈ exclude || eltype(jac_lin(nls, x)) == T - @test jac_op ∈ exclude || eltype(jac_lin_op(nls, x)) == T + @test jac ∈ exclude || eltype(jac_lin(nls)) == T + @test jac_op ∈ exclude || eltype(jac_lin_op(nls)) == T end if jac_coord ∉ exclude && jac_op ∉ exclude rows, cols = jac_structure(nls) @@ -109,7 +109,7 @@ function multiple_precision_nls( end if linear_api && nls.meta.nlin > 0 rows, cols = jac_lin_structure(nls) - vals = jac_lin_coord(nls, x) + vals = jac_lin_coord(nls) @test typeof(vals) == S Av = fill!(S(undef, nls.meta.nlin), T(0)) Atv = fill!(S(undef, nls.meta.nvar), T(0)) diff --git a/src/nls/problems/lls.jl b/src/nls/problems/lls.jl index 4921d8a..641bfa0 100644 --- a/src/nls/problems/lls.jl +++ b/src/nls/problems/lls.jl @@ -180,23 +180,24 @@ function NLPModels.jac_lin_structure!( return rows, cols end -function NLPModels.jac_lin_coord!(nls::LLS, x::AbstractVector{T}, vals::AbstractVector) where {T} - @lencheck 2 x vals +function NLPModels.jac_lin_coord!(nls::LLS, vals::AbstractVector) + @lencheck 2 vals increment!(nls, :neval_jac_lin) + T = eltype(vals) vals .= T(1) return vals end -function NLPModels.jprod_lin!(nls::LLS, x::AbstractVector, v::AbstractVector, Jv::AbstractVector) - @lencheck 2 x v +function NLPModels.jprod_lin!(nls::LLS, v::AbstractVector, Jv::AbstractVector) + @lencheck 2 v @lencheck 1 Jv increment!(nls, :neval_jprod_lin) Jv[1] = v[1] + v[2] return Jv end -function NLPModels.jtprod_lin!(nls::LLS, x::AbstractVector, v::AbstractVector, Jtv::AbstractVector) - @lencheck 2 x Jtv +function NLPModels.jtprod_lin!(nls::LLS, v::AbstractVector, Jtv::AbstractVector) + @lencheck 2 Jtv @lencheck 1 v increment!(nls, :neval_jtprod_lin) Jtv .= v diff --git a/src/nls/problems/nlslc.jl b/src/nls/problems/nlslc.jl index ba3b94e..7af2a2f 100644 --- a/src/nls/problems/nlslc.jl +++ b/src/nls/problems/nlslc.jl @@ -222,10 +222,10 @@ function NLPModels.jac_lin_structure!( return rows, cols end -function NLPModels.jac_lin_coord!(nls::NLSLC, x::AbstractVector{T}, vals::AbstractVector) where {T} - @lencheck 15 x +function NLPModels.jac_lin_coord!(nls::NLSLC, vals::AbstractVector) @lencheck 17 vals increment!(nls, :neval_jac_lin) + T = eltype(vals) vals[1] = T(15) vals[2] = T(1) vals[3] = T(2) @@ -246,8 +246,8 @@ function NLPModels.jac_lin_coord!(nls::NLSLC, x::AbstractVector{T}, vals::Abstra return vals end -function NLPModels.jprod_lin!(nls::NLSLC, x::AbstractVector, v::AbstractVector, Jv::AbstractVector) - @lencheck 15 x v +function NLPModels.jprod_lin!(nls::NLSLC, v::AbstractVector, Jv::AbstractVector) + @lencheck 15 v @lencheck 11 Jv increment!(nls, :neval_jprod_lin) Jv[1] = 15 * v[15] @@ -266,11 +266,10 @@ end function NLPModels.jtprod_lin!( nls::NLSLC, - x::AbstractVector, v::AbstractVector, Jtv::AbstractVector, ) - @lencheck 15 x Jtv + @lencheck 15 Jtv @lencheck 11 v increment!(nls, :neval_jtprod_lin) Jtv[1] = 1 * v[7] + 3 * v[8]