diff --git a/src/gram_covers.jl b/src/gram_covers.jl index bc98725..1900fa4 100644 --- a/src/gram_covers.jl +++ b/src/gram_covers.jl @@ -203,7 +203,7 @@ function gramcover!(s::AbstractVector, a::AbstractVector, b::AbstractVector, sc: _check_gramcover_ab(a, b, sc) _check_gramcover_s(s, sc) eachindex(w) == sc.rowax || - throw(DimensionMismatch("`w` holds one weight per support row: eachindex(w) must be $(sc.rowax), got $(eachindex(w))")) + throw(DimensionMismatch("`w` holds one weight per support row: eachindex(w) must be $(string(sc.rowax)), got $(string(eachindex(w)))")) m = zeros(typeof(_gc_term(a, w)), ncomponents(sc)) n = zeros(Int, ncomponents(sc)) for i in sc.rowax @@ -223,7 +223,7 @@ function gramcover!(s::AbstractVector, a::AbstractVector, b::AbstractVector, sc: _check_gramcover_ab(a, b, sc) _check_gramcover_s(s, sc) axes(W) == (sc.rowax, sc.rowax) || - throw(DimensionMismatch("`W` couples support rows, so it must be square on the row axis: axes(W) must be $((sc.rowax, sc.rowax)), got $(axes(W))")) + throw(DimensionMismatch("`W` couples support rows, so it must be square on the row axis: axes(W) must be $(string((sc.rowax, sc.rowax))), got $(string(axes(W)))")) ncomp = ncomponents(sc) # Union-find over the component ids of `sc`: merge two of them whenever a @@ -320,15 +320,15 @@ end function _check_gramcover_ab(a::AbstractVector, b::AbstractVector, sc::SupportComponents) eachindex(a) == sc.rowax || - throw(DimensionMismatch("`a` holds one scale per support row: eachindex(a) must be $(sc.rowax), got $(eachindex(a))")) + throw(DimensionMismatch("`a` holds one scale per support row: eachindex(a) must be $(string(sc.rowax)), got $(string(eachindex(a)))")) eachindex(b) == sc.colax || - throw(DimensionMismatch("`b` holds one scale per support column: eachindex(b) must be $(sc.colax), got $(eachindex(b))")) + throw(DimensionMismatch("`b` holds one scale per support column: eachindex(b) must be $(string(sc.colax)), got $(string(eachindex(b)))")) return nothing end function _check_gramcover_s(s::AbstractVector, sc::SupportComponents) eachindex(s) == sc.colax || - throw(DimensionMismatch("`s` holds one Gram scale per support column: eachindex(s) must be $(sc.colax), got $(eachindex(s))")) + throw(DimensionMismatch("`s` holds one Gram scale per support column: eachindex(s) must be $(string(sc.colax)), got $(string(eachindex(s)))")) return nothing end diff --git a/src/heuristic_covers.jl b/src/heuristic_covers.jl index 772a3b3..dc5ee0a 100644 --- a/src/heuristic_covers.jl +++ b/src/heuristic_covers.jl @@ -67,7 +67,7 @@ function symcover!(a::AbstractVector, A::AbstractMatrix; kwargs...) ax = axes(A, 1) axes(A, 2) == ax || throw(ArgumentError("symcover! requires a square matrix")) require_abs_symmetric(A, :symcover!) - eachindex(a) == ax || throw(DimensionMismatch("indices of `a` must match the indexing of `A`, got eachindex(a)=$(eachindex(a)), axes(A, 1)=$ax")) + eachindex(a) == ax || throw(DimensionMismatch("indices of `a` must match the indexing of `A`, got eachindex(a)=$(string(eachindex(a))), axes(A, 1)=$(string(ax))")) unconstrained_min!(AbsLog{2}(), a, A) boost_feasible!(a, A) return tighten_cover!(a, A; kwargs...) @@ -144,8 +144,8 @@ cover!(ϕ::AbstractCoverPenalty, a::AbstractVector, b::AbstractVector, A::Abstra cover!(a, b, A; kwargs...) function cover!(a::AbstractVector, b::AbstractVector, A::AbstractMatrix; kwargs...) - axes(A, 1) == eachindex(a) || throw(DimensionMismatch("indices of `a` must match row-indexing of `A`, got eachindex(a)=$(eachindex(a)), axes(A, 1)=$(axes(A, 1))")) - axes(A, 2) == eachindex(b) || throw(DimensionMismatch("indices of `b` must match column-indexing of `A`, got eachindex(b)=$(eachindex(b)), axes(A, 2)=$(axes(A, 2))")) + axes(A, 1) == eachindex(a) || throw(DimensionMismatch("indices of `a` must match row-indexing of `A`, got eachindex(a)=$(string(eachindex(a))), axes(A, 1)=$(string(axes(A, 1)))")) + axes(A, 2) == eachindex(b) || throw(DimensionMismatch("indices of `b` must match column-indexing of `A`, got eachindex(b)=$(string(eachindex(b))), axes(A, 2)=$(string(axes(A, 2)))")) unconstrained_min!(AbsLog{2}(), a, b, A) boost_feasible!(a, b, A) tighten_cover!(a, b, A; kwargs...) @@ -240,7 +240,7 @@ end # This is the "rank-1 solution" described in manuscript section 5.2. function unconstrained_min!(::AbsLog{2}, a::AbstractVector{T}, A::AbstractMatrix) where T ax = eachindex(a) - axes(A) == (ax, ax) || throw(DimensionMismatch("`unconstrained_min!(ϕ, a, A)` requires a square matrix with matching axes to `a` (got axes(A)=$(axes(A)), axes(a)=$(axes(a))")) + axes(A) == (ax, ax) || throw(DimensionMismatch("`unconstrained_min!(ϕ, a, A)` requires a square matrix with matching axes to `a` (got axes(A)=$(string(axes(A))), axes(a)=$(string(axes(a)))")) loga = fill!(similar(a), zero(T)) nza = zeros(Int, ax) foreach_support_sym(A) do i, j, v @@ -265,8 +265,8 @@ end function unconstrained_min!(::AbsLog{2}, a::AbstractVector, b::AbstractVector, A::AbstractMatrix) T = float(promote_type(eltype(a), eltype(b))) - axes(A, 1) == eachindex(a) || throw(DimensionMismatch("`unconstrained_min!(ϕ, a, b, A)` requires row indices of `A` to match `a`, got axes(A, 1)=$(axes(A, 1)), axes(a)=$(axes(a))")) - axes(A, 2) == eachindex(b) || throw(DimensionMismatch("`unconstrained_min!(ϕ, a, b, A)` requires column indices of `A` to match `b`, got axes(A, 2)=$(axes(A, 2)), axes(b)=$(axes(b))")) + axes(A, 1) == eachindex(a) || throw(DimensionMismatch("`unconstrained_min!(ϕ, a, b, A)` requires row indices of `A` to match `a`, got axes(A, 1)=$(string(axes(A, 1))), axes(a)=$(string(axes(a)))")) + axes(A, 2) == eachindex(b) || throw(DimensionMismatch("`unconstrained_min!(ϕ, a, b, A)` requires column indices of `A` to match `b`, got axes(A, 2)=$(string(axes(A, 2))), axes(b)=$(string(axes(b)))")) loga = fill!(similar(a, T), zero(T)) logb = fill!(similar(b, T), zero(T)) nza = zeros(Int, axes(A, 1)) @@ -301,7 +301,7 @@ end # a scale for it (see `boost_feasible_seq!`). function init_feasible_diag!(a::AbstractVector{T}, A::AbstractMatrix) where T ax = eachindex(a) - axes(A) == (ax, ax) || throw(DimensionMismatch("`init_feasible_diag!(a, A)` requires a square matrix with matching axes to `a` (got axes(A)=$(axes(A)), axes(a)=$(axes(a)))")) + axes(A) == (ax, ax) || throw(DimensionMismatch("`init_feasible_diag!(a, A)` requires a square matrix with matching axes to `a` (got axes(A)=$(string(axes(A))), axes(a)=$(string(axes(a))))")) # A diagonal entry the traversal skips is zero, which is the "not yet resolved" # value `boost_feasible_seq!` expects. fill!(a, zero(T)) @@ -575,7 +575,7 @@ end # initialization, a heuristic guaranteed to be O(n^2) seems reasonable. function boost_feasible_seq!(a::AbstractVector{T}, A::AbstractMatrix) where T ax = eachindex(a) - axes(A) == (ax, ax) || throw(DimensionMismatch("`boost_feasible_seq!(a, A)` requires a square matrix with matching axes to `a` (got axes(A)=$(axes(A)), axes(a)=$(axes(a)))")) + axes(A) == (ax, ax) || throw(DimensionMismatch("`boost_feasible_seq!(a, A)` requires a square matrix with matching axes to `a` (got axes(A)=$(string(axes(A))), axes(a)=$(string(axes(a))))")) I = eltype(ax) # The support gathered as off-diagonal pairs, ordered by increasing offset and diff --git a/src/initializers.jl b/src/initializers.jl index 14655b8..8768efc 100644 --- a/src/initializers.jl +++ b/src/initializers.jl @@ -84,7 +84,7 @@ function initialize_symcover!(a::AbstractVector, A::AbstractMatrix; ax = axes(A, 1) axes(A, 2) == ax || throw(ArgumentError("initialize_symcover! requires a square matrix")) require_abs_symmetric(A, :initialize_symcover!) - eachindex(a) == ax || throw(DimensionMismatch("indices of `a` must match the indexing of `A`, got eachindex(a)=$(eachindex(a)), axes(A, 1)=$ax")) + eachindex(a) == ax || throw(DimensionMismatch("indices of `a` must match the indexing of `A`, got eachindex(a)=$(string(eachindex(a))), axes(A, 1)=$(string(ax))")) _initialize_symcover!(a, A, strategy, feasible; kwargs...) || throw(ArgumentError("strategy=:leaveout requires a support entry that can be dropped without emptying a row")) return a @@ -131,8 +131,8 @@ See also: [`initialize_cover`](@ref). """ function initialize_cover!(a::AbstractVector, b::AbstractVector, A::AbstractMatrix; strategy::Symbol=:hardcover, feasible::Symbol=:inflate, kwargs...) - axes(A, 1) == eachindex(a) || throw(DimensionMismatch("indices of `a` must match row-indexing of `A`, got eachindex(a)=$(eachindex(a)), axes(A, 1)=$(axes(A, 1))")) - axes(A, 2) == eachindex(b) || throw(DimensionMismatch("indices of `b` must match column-indexing of `A`, got eachindex(b)=$(eachindex(b)), axes(A, 2)=$(axes(A, 2))")) + axes(A, 1) == eachindex(a) || throw(DimensionMismatch("indices of `a` must match row-indexing of `A`, got eachindex(a)=$(string(eachindex(a))), axes(A, 1)=$(string(axes(A, 1)))")) + axes(A, 2) == eachindex(b) || throw(DimensionMismatch("indices of `b` must match column-indexing of `A`, got eachindex(b)=$(string(eachindex(b))), axes(A, 2)=$(string(axes(A, 2)))")) if strategy === :hardcover cover!(a, b, A; kwargs...) elseif strategy === :geomean @@ -200,7 +200,7 @@ end # which start was built. function _reject_kwargs(strategy::Symbol, kwargs) isempty(kwargs) && return nothing - throw(ArgumentError("strategy=:$strategy accepts no further keyword arguments, got $(join(keys(kwargs), ", "))")) + throw(ArgumentError("strategy=:$strategy accepts no further keyword arguments, got $(string(join(keys(kwargs), ", ")))")) end # Leave-one-out geometric mean. The geometric mean weights every nonzero entry equally, so @@ -228,7 +228,7 @@ end # would empty some row's support. function _leaveout_logmean_init!(a::AbstractVector{T}, A::AbstractMatrix) where T ax = eachindex(a) - axes(A) == (ax, ax) || throw(DimensionMismatch("`_leaveout_logmean_init!(a, A)` requires a square matrix with matching axes to `a` (got axes(A)=$(axes(A)), axes(a)=$(axes(a)))")) + axes(A) == (ax, ax) || throw(DimensionMismatch("`_leaveout_logmean_init!(a, A)` requires a square matrix with matching axes to `a` (got axes(A)=$(string(axes(A))), axes(a)=$(string(axes(a))))")) nza = unconstrained_min!(AbsLog{2}(), a, A) sum(nza) == 0 && return false # One gather serves all three passes below: the two pair scans read the `j >= i` diff --git a/src/iscover.jl b/src/iscover.jl index 252015d..db871b0 100644 --- a/src/iscover.jl +++ b/src/iscover.jl @@ -41,9 +41,9 @@ false """ function iscover(a::AbstractVector, b::AbstractVector, A::AbstractMatrix; rtol=0, atol=0) eachindex(a) == axes(A, 1) || - throw(DimensionMismatch("indices of `a` must match row-indexing of `A`, got eachindex(a)=$(eachindex(a)), axes(A, 1)=$(axes(A, 1))")) + throw(DimensionMismatch("indices of `a` must match row-indexing of `A`, got eachindex(a)=$(string(eachindex(a))), axes(A, 1)=$(string(axes(A, 1)))")) eachindex(b) == axes(A, 2) || - throw(DimensionMismatch("indices of `b` must match column-indexing of `A`, got eachindex(b)=$(eachindex(b)), axes(A, 2)=$(axes(A, 2))")) + throw(DimensionMismatch("indices of `b` must match column-indexing of `A`, got eachindex(b)=$(string(eachindex(b))), axes(A, 2)=$(string(axes(A, 2)))")) _require_nonneg(a, "a") _require_nonneg(b, "b") # Zero entries of `A` are skipped by `foreach_support`, and need no check: they demand @@ -57,7 +57,7 @@ end function iscover(a::AbstractVector, A::AbstractMatrix; kwargs...) axes(A, 1) == axes(A, 2) || - throw(DimensionMismatch("iscover(a, A) requires a square matrix, got axes $(axes(A))")) + throw(DimensionMismatch("iscover(a, A) requires a square matrix, got axes $(string(axes(A)))")) return iscover(a, a, A; kwargs...) end @@ -69,7 +69,7 @@ function _require_nonneg(x::AbstractVector, name::String) # value, and `zero(Quantity{Float64})` is undefined. Also rejects NaN, which fails # every comparison. x[i] >= zero(x[i]) || - throw(ArgumentError("iscover requires nonnegative scales, got $name[$i] = $(x[i])")) + throw(ArgumentError("iscover requires nonnegative scales, got $name[$(string(i))] = $(string(x[i]))")) end return nothing end diff --git a/src/minimal_covers.jl b/src/minimal_covers.jl index b0f672a..9b56887 100644 --- a/src/minimal_covers.jl +++ b/src/minimal_covers.jl @@ -220,7 +220,7 @@ function symcover_min(ϕ::AbsLinear, A::AbstractMatrix; strategies=SYMCOVER_MIN_ built = [_initialize_symcover!(a, A, strategy, :inflate) for (a, strategy) in zip(starts, strategies)] covers = [symcover_min!(ϕ, a, A) for (a, ok) in zip(starts, built) if ok] isempty(covers) && - throw(ArgumentError("symcover_min: no strategy in $strategies yields a starting cover of `A`")) + throw(ArgumentError("symcover_min: no strategy in $(string(strategies)) yields a starting cover of `A`")) return covers[_multistart_select([cover_objective(ϕ, a, A) for a in covers])] end @@ -256,7 +256,7 @@ function _prepare_symcover_start!(a::AbstractVector, A::AbstractMatrix, fname=:s ax = axes(A, 1) axes(A, 2) == ax || throw(ArgumentError("$fname requires a square matrix")) require_abs_symmetric(A, fname) - eachindex(a) == ax || throw(DimensionMismatch("indices of `a` must match the indexing of `A`, got eachindex(a)=$(eachindex(a)), axes(A, 1)=$ax")) + eachindex(a) == ax || throw(DimensionMismatch("indices of `a` must match the indexing of `A`, got eachindex(a)=$(string(eachindex(a))), axes(A, 1)=$(string(ax))")) T = float(eltype(a)) supp = fill!(similar(a, Bool), false) foreach_support_sym(A) do i, j, v @@ -268,12 +268,12 @@ function _prepare_symcover_start!(a::AbstractVector, A::AbstractMatrix, fname=:s end foreach_support_sym(A) do i, j, v (isfinite(a[i]) && a[i] > zero(a[i])) || - throw(ArgumentError("symcover_min! requires a start with finite positive scale on every supported row, got a[$i] = $(a[i])")) + throw(ArgumentError("symcover_min! requires a start with finite positive scale on every supported row, got a[$(string(i))] = $(string(a[i]))")) (isfinite(a[j]) && a[j] > zero(a[j])) || - throw(ArgumentError("symcover_min! requires a start with finite positive scale on every supported row, got a[$j] = $(a[j])")) + throw(ArgumentError("symcover_min! requires a start with finite positive scale on every supported row, got a[$(string(j))] = $(string(a[j]))")) lv, li, lj = log(T(v)), log(T(a[i])), log(T(a[j])) lv - li - lj <= _start_slack(lv, li, lj) || - throw(ArgumentError("symcover_min! requires a start that covers `A`, but a[$i]*a[$j] = $(a[i] * a[j]) < $v = abs(A[$i,$j]); see initialize_symcover")) + throw(ArgumentError("symcover_min! requires a start that covers `A`, but a[$(string(i))]*a[$(string(j))] = $(string(a[i] * a[j])) < $(string(v)) = abs(A[$(string(i)),$(string(j))]); see initialize_symcover")) end return inflate_feasible!(a, A) end @@ -283,8 +283,8 @@ end # convention (imposed within each connected component of the support), so the # refiners read it only up to the per-component row/column gauge. function _prepare_cover_start!(a::AbstractVector, b::AbstractVector, A::AbstractMatrix) - axes(A, 1) == eachindex(a) || throw(DimensionMismatch("indices of `a` must match row-indexing of `A`, got eachindex(a)=$(eachindex(a)), axes(A, 1)=$(axes(A, 1))")) - axes(A, 2) == eachindex(b) || throw(DimensionMismatch("indices of `b` must match column-indexing of `A`, got eachindex(b)=$(eachindex(b)), axes(A, 2)=$(axes(A, 2))")) + axes(A, 1) == eachindex(a) || throw(DimensionMismatch("indices of `a` must match row-indexing of `A`, got eachindex(a)=$(string(eachindex(a))), axes(A, 1)=$(string(axes(A, 1)))")) + axes(A, 2) == eachindex(b) || throw(DimensionMismatch("indices of `b` must match column-indexing of `A`, got eachindex(b)=$(string(eachindex(b))), axes(A, 2)=$(string(axes(A, 2)))")) T = float(promote_type(eltype(a), eltype(b))) suppa = fill!(similar(a, Bool), false) suppb = fill!(similar(b, Bool), false) @@ -300,12 +300,12 @@ function _prepare_cover_start!(a::AbstractVector, b::AbstractVector, A::Abstract end foreach_support(A) do i, j, v (isfinite(a[i]) && a[i] > zero(a[i])) || - throw(ArgumentError("cover_min! requires a start with finite positive scale on every supported row, got a[$i] = $(a[i])")) + throw(ArgumentError("cover_min! requires a start with finite positive scale on every supported row, got a[$(string(i))] = $(string(a[i]))")) (isfinite(b[j]) && b[j] > zero(b[j])) || - throw(ArgumentError("cover_min! requires a start with finite positive scale on every supported column, got b[$j] = $(b[j])")) + throw(ArgumentError("cover_min! requires a start with finite positive scale on every supported column, got b[$(string(j))] = $(string(b[j]))")) lv, li, lj = log(T(v)), log(T(a[i])), log(T(b[j])) lv - li - lj <= _start_slack(lv, li, lj) || - throw(ArgumentError("cover_min! requires a start that covers `A`, but a[$i]*b[$j] = $(a[i] * b[j]) < $v = abs(A[$i,$j]); see initialize_cover")) + throw(ArgumentError("cover_min! requires a start that covers `A`, but a[$(string(i))]*b[$(string(j))] = $(string(a[i] * b[j])) < $(string(v)) = abs(A[$(string(i)),$(string(j))]); see initialize_cover")) end _balance_cover!(a, b, A) return inflate_feasible!(a, b, A) diff --git a/src/penalties.jl b/src/penalties.jl index 67d0b47..ce799ab 100644 --- a/src/penalties.jl +++ b/src/penalties.jl @@ -129,9 +129,9 @@ See also: """ function cover_objective(ϕ, a, b, A) eachindex(a) == axes(A, 1) || - throw(DimensionMismatch("indices of `a` must match row-indexing of `A`, got eachindex(a)=$(eachindex(a)), axes(A, 1)=$(axes(A, 1))")) + throw(DimensionMismatch("indices of `a` must match row-indexing of `A`, got eachindex(a)=$(string(eachindex(a))), axes(A, 1)=$(string(axes(A, 1)))")) eachindex(b) == axes(A, 2) || - throw(DimensionMismatch("indices of `b` must match column-indexing of `A`, got eachindex(b)=$(eachindex(b)), axes(A, 2)=$(axes(A, 2))")) + throw(DimensionMismatch("indices of `b` must match column-indexing of `A`, got eachindex(b)=$(string(eachindex(b))), axes(A, 2)=$(string(axes(A, 2)))")) T = promote_type(objective_type(A), objective_type(a), objective_type(b)) s = Ref(zero(T)) nsupport = Ref(0) diff --git a/src/soft_covers.jl b/src/soft_covers.jl index 816e474..65f2627 100644 --- a/src/soft_covers.jl +++ b/src/soft_covers.jl @@ -349,7 +349,7 @@ function soft_symcover_min(ϕ::AbsLinear, A::AbstractMatrix; strategies=SYMCOVER built = [_initialize_symcover!(a, A, strategy, :none) for (a, strategy) in zip(starts, strategies)] covers = [soft_symcover_min!(ϕ, a, A) for (a, ok) in zip(starts, built) if ok] isempty(covers) && - throw(ArgumentError("soft_symcover_min: no strategy in $strategies yields a starting cover of `A`")) + throw(ArgumentError("soft_symcover_min: no strategy in $(string(strategies)) yields a starting cover of `A`")) return covers[_multistart_select([cover_objective(ϕ, a, A) for a in covers])] end @@ -394,7 +394,7 @@ function _prepare_soft_symcover_start!(a::AbstractVector, A::AbstractMatrix, fna ax = axes(A, 1) axes(A, 2) == ax || throw(ArgumentError("$fname requires a square matrix")) require_abs_symmetric(A, fname) - eachindex(a) == ax || throw(DimensionMismatch("indices of `a` must match the indexing of `A`, got eachindex(a)=$(eachindex(a)), axes(A, 1)=$ax")) + eachindex(a) == ax || throw(DimensionMismatch("indices of `a` must match the indexing of `A`, got eachindex(a)=$(string(eachindex(a))), axes(A, 1)=$(string(ax))")) supp = fill!(similar(a, Bool), false) foreach_support_sym(A) do i, j, v supp[i] = true @@ -406,7 +406,7 @@ function _prepare_soft_symcover_start!(a::AbstractVector, A::AbstractMatrix, fna for i in ax supp[i] || continue (isfinite(a[i]) && a[i] > zero(a[i])) || - throw(ArgumentError("$fname requires a start with finite positive scale on every supported row, got a[$i] = $(a[i])")) + throw(ArgumentError("$fname requires a start with finite positive scale on every supported row, got a[$(string(i))] = $(string(a[i]))")) end return a end @@ -508,8 +508,8 @@ end # actually called. function _prepare_soft_cover_start!(a::AbstractVector, b::AbstractVector, A::AbstractMatrix, fname::Symbol=:soft_cover_min!) - axes(A, 1) == eachindex(a) || throw(DimensionMismatch("indices of `a` must match row-indexing of `A`, got eachindex(a)=$(eachindex(a)), axes(A, 1)=$(axes(A, 1))")) - axes(A, 2) == eachindex(b) || throw(DimensionMismatch("indices of `b` must match column-indexing of `A`, got eachindex(b)=$(eachindex(b)), axes(A, 2)=$(axes(A, 2))")) + axes(A, 1) == eachindex(a) || throw(DimensionMismatch("indices of `a` must match row-indexing of `A`, got eachindex(a)=$(string(eachindex(a))), axes(A, 1)=$(string(axes(A, 1)))")) + axes(A, 2) == eachindex(b) || throw(DimensionMismatch("indices of `b` must match column-indexing of `A`, got eachindex(b)=$(string(eachindex(b))), axes(A, 2)=$(string(axes(A, 2)))")) suppa = fill!(similar(a, Bool), false) suppb = fill!(similar(b, Bool), false) foreach_support(A) do i, j, v @@ -525,12 +525,12 @@ function _prepare_soft_cover_start!(a::AbstractVector, b::AbstractVector, A::Abs for i in eachindex(a) suppa[i] || continue (isfinite(a[i]) && a[i] > zero(a[i])) || - throw(ArgumentError("$fname requires a start with finite positive scale on every supported row, got a[$i] = $(a[i])")) + throw(ArgumentError("$fname requires a start with finite positive scale on every supported row, got a[$(string(i))] = $(string(a[i]))")) end for j in eachindex(b) suppb[j] || continue (isfinite(b[j]) && b[j] > zero(b[j])) || - throw(ArgumentError("$fname requires a start with finite positive scale on every supported column, got b[$j] = $(b[j])")) + throw(ArgumentError("$fname requires a start with finite positive scale on every supported column, got b[$(string(j))] = $(string(b[j]))")) end return _balance_cover!(a, b, A) end @@ -550,7 +550,7 @@ function _resolve_alias(primary, alias, default, primary_name::Symbol, alias_nam primary === nothing && return alias === nothing ? default : alias alias === nothing && return primary primary == alias || - throw(ArgumentError("both `$primary_name` and `$alias_name` were given with different values ($primary vs $alias); specify only one")) + throw(ArgumentError("both `$primary_name` and `$alias_name` were given with different values ($(string(primary)) vs $(string(alias))); specify only one")) return primary end @@ -676,7 +676,7 @@ end # multistart selection stays covariant. function _abslinear2_iter!(a::AbstractVector{T}, A::AbstractMatrix, iter::Int; tol::Real=50_000_000 * eps(T)) where T ax = eachindex(a) - ax == axes(A, 1) || throw(DimensionMismatch("row indices of `A` must match `a`, got $(axes(A, 1)) vs $(ax)")) + ax == axes(A, 1) || throw(DimensionMismatch("row indices of `A` must match `a`, got $(string(axes(A, 1))) vs $(string(ax))")) S = _sym_support(A, T) for _ in 1:iter maxres = zero(T) @@ -765,7 +765,7 @@ end # restarts of a rescaled problem exit on the same sweep. function _abslinear1_iter!(a::AbstractVector{T}, A::AbstractMatrix, iter::Int; tol::Real=5000 * eps(T)) where T ax = eachindex(a) - ax == axes(A, 1) || throw(DimensionMismatch("row indices of `A` must match `a`, got $(axes(A, 1)) vs $(ax)")) + ax == axes(A, 1) || throw(DimensionMismatch("row indices of `A` must match `a`, got $(string(axes(A, 1))) vs $(string(ax))")) S = _sym_support(A, T) buf = Vector{T}(undef, length(ax)) # reusable buffer for c_j values for _ in 1:iter @@ -824,7 +824,7 @@ end # sweep. function _abslog1_iter!(a::AbstractVector{T}, A::AbstractMatrix, iter::Int; tol::Real=5000 * eps(T)) where T ax = eachindex(a) - ax == axes(A, 1) || throw(DimensionMismatch("row indices of `A` must match `a`, got $(axes(A, 1)) vs $(ax)")) + ax == axes(A, 1) || throw(DimensionMismatch("row indices of `A` must match `a`, got $(string(axes(A, 1))) vs $(string(ax))")) S = _sym_support(A, T) buf = Vector{T}(undef, 2 * length(ax) + 1) # off-diagonals (×1) + diagonal (×2) for _ in 1:iter @@ -879,8 +879,8 @@ function _abslog1_iter_asym!(a::AbstractVector, b::AbstractVector, A::AbstractMa T = float(promote_type(eltype(a), eltype(b))) rtol = tol === nothing ? 5000 * eps(T) : T(tol) axr, axc = axes(A, 1), axes(A, 2) - eachindex(a) == axr || throw(DimensionMismatch("row indices of `A` must match `a`, got $(axr) vs $(eachindex(a))")) - eachindex(b) == axc || throw(DimensionMismatch("column indices of `A` must match `b`, got $(axc) vs $(eachindex(b))")) + eachindex(a) == axr || throw(DimensionMismatch("row indices of `A` must match `a`, got $(string(axr)) vs $(string(eachindex(a)))")) + eachindex(b) == axc || throw(DimensionMismatch("column indices of `A` must match `b`, got $(string(axc)) vs $(string(eachindex(b)))")) R, C = _row_support(A, T), _col_support(A, T) bufc = Vector{T}(undef, length(axc)) # log-points for an a-row update bufr = Vector{T}(undef, length(axr)) # log-points for a b-column update @@ -993,8 +993,8 @@ end function _msmc_als!(a::AbstractVector, b::AbstractVector, A::AbstractMatrix, iter::Int; tol=nothing) axr, axc = axes(A, 1), axes(A, 2) - eachindex(a) == axr || throw(DimensionMismatch("row indices of `A` must match `a`, got $(axr) vs $(eachindex(a))")) - eachindex(b) == axc || throw(DimensionMismatch("column indices of `A` must match `b`, got $(axc) vs $(eachindex(b))")) + eachindex(a) == axr || throw(DimensionMismatch("row indices of `A` must match `a`, got $(string(axr)) vs $(string(eachindex(a)))")) + eachindex(b) == axc || throw(DimensionMismatch("column indices of `A` must match `b`, got $(string(axc)) vs $(string(eachindex(b)))")) T = float(promote_type(eltype(a), eltype(b), real(eltype(A)))) # The convergence test is on a relative movement, so its floor is set by the # precision of `T`: a fixed Float64-scaled literal can never be reached in @@ -1077,8 +1077,8 @@ function _abslinear1_iter_asym!(a::AbstractVector, b::AbstractVector, A::Abstrac T = float(promote_type(eltype(a), eltype(b))) rtol = tol === nothing ? 5000 * eps(T) : T(tol) axr, axc = axes(A, 1), axes(A, 2) - eachindex(a) == axr || throw(DimensionMismatch("row indices of `A` must match `a`, got $(axr) vs $(eachindex(a))")) - eachindex(b) == axc || throw(DimensionMismatch("column indices of `A` must match `b`, got $(axc) vs $(eachindex(b))")) + eachindex(a) == axr || throw(DimensionMismatch("row indices of `A` must match `a`, got $(string(axr)) vs $(string(eachindex(a)))")) + eachindex(b) == axc || throw(DimensionMismatch("column indices of `A` must match `b`, got $(string(axc)) vs $(string(eachindex(b)))")) R, C = _row_support(A, T), _col_support(A, T) bufc = Vector{T}(undef, length(axc)) # c_j buffer for an a-row update bufr = Vector{T}(undef, length(axr)) # c_i buffer for a b-column update diff --git a/src/support.jl b/src/support.jl index 67a819c..15189ab 100644 --- a/src/support.jl +++ b/src/support.jl @@ -96,7 +96,7 @@ See also: [`foreach_support`](@ref). """ function foreach_support_sym(f, A::AbstractMatrix) ax = axes(A, 1) - axes(A, 2) == ax || throw(DimensionMismatch("foreach_support_sym requires a square matrix, got axes $(axes(A))")) + axes(A, 2) == ax || throw(DimensionMismatch("foreach_support_sym requires a square matrix, got axes $(string(axes(A)))")) for j in ax for i in first(ax):j v = abs(A[i, j]) @@ -131,13 +131,13 @@ the traversal reads and what admits a complex `Hermitian`. function require_abs_symmetric(A::AbstractMatrix, fname) ax = axes(A, 1) axes(A, 2) == ax || - throw(DimensionMismatch("$fname requires a square matrix, got axes $(axes(A))")) + throw(DimensionMismatch("$fname requires a square matrix, got axes $(string(axes(A)))")) foreach_support(A) do i, j, v w = abs(A[j, i]) m = max(v, w) abs(v - w) <= ASYMMETRY_ULPS * eps(float(real(typeof(m)))) * m || throw(ArgumentError(""" - $fname requires `abs.(A)` to be symmetric, but abs(A[$i,$j]) = $v and \ - abs(A[$j,$i]) = $w. Wrap `A` in `Symmetric` (or `Hermitian`) to name the \ + $fname requires `abs.(A)` to be symmetric, but abs(A[$(string(i)),$(string(j))]) = $(string(v)) and \ + abs(A[$(string(j)),$(string(i))]) = $(string(w)). Wrap `A` in `Symmetric` (or `Hermitian`) to name the \ triangle to read; that also skips this check.""")) end return nothing