Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,25 @@ jobs:
test:
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ github.event_name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
version:
- 'min'
- 'lts'
- '1'
- 'pre'
os:
- ubuntu-latest
- macOS-latest
- windows-latest
arch:
- x64
steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
Expand Down
17 changes: 7 additions & 10 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
name = "FillArrays"
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
version = "1.14.0"
version = "1.15.0"

[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
PDMats = "90014a1f-27ba-587c-ab20-58faa44d9150"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[weakdeps]
PDMats = "90014a1f-27ba-587c-ab20-58faa44d9150"
Expand All @@ -22,16 +19,16 @@ FillArraysStatisticsExt = "Statistics"
Aqua = "0.8"
Documenter = "1"
Infinities = "0.1"
LinearAlgebra = "1.6"
LinearAlgebra = "1"
PDMats = "0.11.17"
Quaternions = "0.7"
Random = "1.6"
Random = "1"
ReverseDiff = "1"
SparseArrays = "1.6"
SparseArrays = "1"
StaticArrays = "1"
Statistics = "1.6"
Test = "1.6"
julia = "1.6"
Statistics = "1"
Test = "1"
julia = "1.10"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
Expand Down
7 changes: 1 addition & 6 deletions ext/FillArraysSparseArraysExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,6 @@ end
@deprecate kron(E1::RectDiagonalFill, E2::RectDiagonalFill) kron(sparse(E1), sparse(E2))

# Ambiguity. see #178
if VERSION >= v"1.8"
dot(x::AbstractFillVector, y::SparseVectorUnion) = _fill_dot(x, y)
else
dot(x::AbstractFillVector{<:Number}, y::SparseVectorUnion{<:Number}) = _fill_dot(x, y)
end

dot(x::AbstractFillVector, y::SparseVectorUnion) = _fill_dot(x, y)

end # module
55 changes: 15 additions & 40 deletions src/FillArrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,18 @@ Base.@propagate_inbounds getindex(F::AbstractFill{T, N}, kj::Vararg{Integer, N})

@inline function setindex!(F::AbstractFill, v, k::Integer)
@boundscheck checkbounds(F, k)
v == getindex_value(F) || throw(ArgumentError("Cannot setindex! to $v for an AbstractFill with value $(getindex_value(F))."))
v == getindex_value(F) || throw(ArgumentError(LazyString("Cannot setindex! to ", v, " for an AbstractFill with value ", getindex_value(F), ".")))
F
end

@inline function setindex!(F::AbstractFill{T, N}, v, kj::Vararg{Integer, N}) where {T, N}
@boundscheck checkbounds(F, kj...)
v == getindex_value(F) || throw(ArgumentError("Cannot setindex! to $v for an AbstractFill with value $(getindex_value(F))."))
v == getindex_value(F) || throw(ArgumentError(LazyString("Cannot setindex! to ", v, " for an AbstractFill with value ", getindex_value(F), ".")))
F
end

@inline function fill!(F::AbstractFill, v)
v == getindex_value(F) || throw(ArgumentError("Cannot fill! with $v an AbstractFill with value $(getindex_value(F))."))
v == getindex_value(F) || throw(ArgumentError(LazyString("Cannot fill! with ", v, " an AbstractFill with value ", getindex_value(F), ".")))
F
end

Expand All @@ -72,18 +72,10 @@ ishermitian(F::AbstractFillMatrix) = axes(F,1) == axes(F,2) && (isempty(F) || is
Base.IteratorSize(::Type{<:AbstractFill{T,N,Axes}}) where {T,N,Axes} = _IteratorSize(Axes)
_IteratorSize(::Type{Tuple{}}) = Base.HasShape{0}()
_IteratorSize(::Type{Tuple{T}}) where {T} = Base.IteratorSize(T)
# Julia Base has an optimized any for Tuples on versions >= v1.9
# On lower versions, a recursive implementation helps with type-inference
if VERSION >= v"1.9.0-beta3"
_any(f, t::Tuple) = any(f, t)
else
_any(f, ::Tuple{}) = false
_any(f, t::Tuple) = f(t[1]) || _any(f, Base.tail(t))
end
function _IteratorSize(::Type{T}) where {T<:Tuple}
N = fieldcount(T)
s = ntuple(i-> Base.IteratorSize(fieldtype(T, i)), N)
_any(x -> x isa Base.IsInfinite, s) ? Base.IsInfinite() : Base.HasShape{N}()
any(x -> x isa Base.IsInfinite, s) ? Base.IsInfinite() : Base.HasShape{N}()
end


Expand Down Expand Up @@ -190,7 +182,7 @@ function unique_value(arr::AbstractArray)
val = first(arr)
for x in arr
if x !== val
error("Input array contains both $x and $val. Cannot convert to Fill")
error(LazyString("Input array contains both ", x, " and ", val, ". Cannot convert to Fill"))
end
end
return val
Expand Down Expand Up @@ -263,12 +255,9 @@ end

svdvals!(a::AbstractFillMatrix) = [getindex_value(a)*sqrt(prod(size(a))); Zeros(min(size(a)...)-1)]

@noinline function _throw_dmrs(n, str, dims)
throw(DimensionMismatch("parent has $n elements, which is incompatible with $str $dims"))
end
function fill_reshape(parent, dims::Integer...)
n = length(parent)
prod(dims) == n || _throw_dmrs(n, "size", dims)
prod(dims) == n || throw(DimensionMismatch(LazyString("parent has ", n, " elements, which is incompatible with size ", dims)))
fillsimilar(parent, dims...)
end

Expand Down Expand Up @@ -347,10 +336,10 @@ for (AbsTyp, Typ, funcs, func) in ((:AbstractZeros, :Zeros, :zeros, :zero), (:Ab
convert(::Type{$Typ{T,N}}, A::$AbsTyp{V,N,Axes}) where {T,V,N,Axes} = convert($Typ{T,N,Axes}, A)
convert(::Type{$Typ{T}}, A::$AbsTyp{V,N,Axes}) where {T,V,N,Axes} = convert($Typ{T,N,Axes}, A)
function convert(::Type{Typ}, A::AbstractFill{V,N}) where {T,V,N,Axes,Typ<:$AbsTyp{T,N,Axes}}
axes(A) isa Axes || throw(ArgumentError("cannot convert, as axes of array are not $Axes"))
axes(A) isa Axes || throw(ArgumentError(LazyString("cannot convert, as axes of array are not ", Axes)))
val = getindex_value(A)
y = convert(T, val)
y == $func(T) || throw(ArgumentError(string("cannot convert an array containinig $val to ", $Typ)))
y == $func(T) || throw(ArgumentError(LazyString("cannot convert an array containinig ", val, " to ", Typ)))
Typ(axes(A))
end
function convert(::Type{$Typ{T,N}}, A::AbstractFill{<:Any,N}) where {T,N}
Expand Down Expand Up @@ -389,7 +378,7 @@ fillsimilar(a::AbstractFill, axes...) = Fill(getindex_value(a), axes...)
# functions
function Base.sqrt(a::AbstractFillMatrix{<:Union{Real, Complex}})
Base.require_one_based_indexing(a)
size(a,1) == size(a,2) || throw(DimensionMismatch("matrix is not square: dimensions are $(size(a))"))
size(a,1) == size(a,2) || throw(DimensionMismatch(LazyString("matrix is not square: dimensions are ", size(a))))
_sqrt(a)
end
_sqrt(a::AbstractZerosMatrix) = float(a)
Expand All @@ -401,7 +390,7 @@ function _sqrt(a::AbstractFillMatrix)
end
function Base.cbrt(a::AbstractFillMatrix{<:Real})
Base.require_one_based_indexing(a)
size(a,1) == size(a,2) || throw(DimensionMismatch("matrix is not square: dimensions are $(size(a))"))
size(a,1) == size(a,2) || throw(DimensionMismatch(LazyString("matrix is not square: dimensions are ", size(a))))
_cbrt(a)
end
_cbrt(a::AbstractZerosMatrix) = float(a)
Expand Down Expand Up @@ -460,7 +449,7 @@ function setindex!(rd::RectDiagonal, v, i::Integer, j::Integer)
if i == j
@inbounds rd.diag[i] = v
elseif !iszero(v)
throw(ArgumentError("cannot set off-diagonal entry ($i, $j) to a nonzero value ($v)"))
throw(ArgumentError(LazyString("cannot set off-diagonal entry (", i, ", ", j, ") to a nonzero value (", v, ")")))
end
return v
end
Expand Down Expand Up @@ -738,12 +727,6 @@ include("fillalgebra.jl")
include("fillbroadcast.jl")
include("trues.jl")

if !isdefined(Base, :get_extension)
include("../ext/FillArraysPDMatsExt.jl")
include("../ext/FillArraysSparseArraysExt.jl")
include("../ext/FillArraysStatisticsExt.jl")
end

##
# print
##
Expand All @@ -752,15 +735,9 @@ Base.replace_in_print_matrix(::AbstractZeros, ::Integer, ::Integer, s::AbstractS

# following support blocked fill array printing via
# BlockArrays.jl
if VERSION < v"1.8-"
axes_print_matrix_row(lay, io, X, A, i, cols, sep) =
Base.invoke(Base.print_matrix_row, Tuple{IO,AbstractVecOrMat,Vector,Integer,AbstractVector,AbstractString},
io, X, A, i, cols, sep)
else
axes_print_matrix_row(lay, io, X, A, i, cols, sep, idxlast::Integer=last(axes(X, 2))) =
Base.invoke(Base.print_matrix_row, Tuple{IO,AbstractVecOrMat,Vector,Integer,AbstractVector,AbstractString,Integer},
axes_print_matrix_row(lay, io, X, A, i, cols, sep, idxlast::Integer=last(axes(X, 2))) =
Base.invoke(Base.print_matrix_row, Tuple{IO,AbstractVecOrMat,Vector,Integer,AbstractVector,AbstractString,Integer},
io, X, A, i, cols, sep, idxlast)
end

Base.print_matrix_row(io::IO,
X::Union{AbstractFillVector,
Expand Down Expand Up @@ -871,11 +848,9 @@ end
function _repeat(A; inner=ntuple(x->1, ndims(A)), outer=ntuple(x->1, ndims(A)))
Base.require_one_based_indexing(A)
length(inner) >= ndims(A) ||
throw(ArgumentError("number of inner repetitions $(length(inner)) cannot be "*
"less than number of dimensions of input array $(ndims(A))"))
throw(ArgumentError(LazyString("number of inner repetitions ", length(inner), " cannot be less than number of dimensions of input array ", ndims(A))))
length(outer) >= ndims(A) ||
throw(ArgumentError("number of outer repetitions $(length(outer)) cannot be "*
"less than number of dimensions of input array $(ndims(A))"))
throw(ArgumentError(LazyString("number of outer repetitions ", length(outer), " cannot be less than number of dimensions of input array ", ndims(A))))
sz = _repeat_size(size(A), Tuple(inner), Tuple(outer))
fillsimilar(A, sz)
end
Expand Down
42 changes: 21 additions & 21 deletions src/fillalgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ end
function mult_axes(a, b)
Base.require_one_based_indexing(a, b)
size(a, 2) ≠ size(b, 1) &&
throw(DimensionMismatch("A has dimensions $(size(a)) but B has dimensions $(size(b))"))
throw(DimensionMismatch(LazyString("A has dimensions ", size(a), " but B has dimensions ", size(b))))
return (axes(a, 1), axes(b)[2:end]...)
end

Expand Down Expand Up @@ -115,11 +115,11 @@ function *(F::AbstractFillMatrix, v::AbstractVector)
end

function lmul_diag(a::Diagonal, b)
size(a,2) == size(b,1) || throw(DimensionMismatch("A has dimensions $(size(a)) but B has dimensions $(size(b))"))
size(a,2) == size(b,1) || throw(DimensionMismatch(LazyString("A has dimensions ", size(a), " but B has dimensions ", size(b))))
parent(a) .* b # use special broadcast
end
function rmul_diag(a, b::Diagonal)
size(a,2) == size(b,1) || throw(DimensionMismatch("A has dimensions $(size(a)) but B has dimensions $(size(b))"))
size(a,2) == size(b,1) || throw(DimensionMismatch(LazyString("A has dimensions ", size(a), " but B has dimensions ", size(b))))
a .* permutedims(parent(b)) # use special broadcast
end

Expand All @@ -132,26 +132,26 @@ end
@noinline function check_matmul_sizes(A::AbstractMatrix, x::AbstractVector)
Base.require_one_based_indexing(A, x)
size(A,2) == size(x,1) ||
throw(DimensionMismatch("second dimension of A, $(size(A,2)) does not match length of x $(length(x))"))
throw(DimensionMismatch(LazyString("second dimension of A, ", size(A,2), ", does not match length of x, ", length(x))))
end
@noinline function check_matmul_sizes(A::AbstractMatrix, B::AbstractMatrix)
Base.require_one_based_indexing(A, B)
size(A,2) == size(B,1) ||
throw(DimensionMismatch("second dimension of A, $(size(A,2)) does not match first dimension of B, $(size(B,1))"))
throw(DimensionMismatch(LazyString("second dimension of A, ", size(A,2), ", does not match first dimension of B, ", size(B,1))))
end
@noinline function check_matmul_sizes(y::AbstractVector, A::AbstractMatrix, x::AbstractVector)
Base.require_one_based_indexing(A, x, y)
size(A,2) == size(x,1) ||
throw(DimensionMismatch("second dimension of A, $(size(A,2)) does not match length of x $(length(x))"))
throw(DimensionMismatch(LazyString("second dimension of A, ", size(A,2), ", does not match length of x, ", length(x))))
size(y,1) == size(A,1) ||
throw(DimensionMismatch("first dimension of A, $(size(A,1)) does not match length of y $(length(y))"))
throw(DimensionMismatch(LazyString("first dimension of A, ", size(A,1), ", does not match length of y, ", length(y))))
end
@noinline function check_matmul_sizes(C::AbstractMatrix, A::AbstractMatrix, B::AbstractMatrix)
Base.require_one_based_indexing(A, B, C)
size(A,2) == size(B,1) ||
throw(DimensionMismatch("second dimension of A, $(size(A,2)) does not match first dimension of B, $(size(B,1))"))
throw(DimensionMismatch(LazyString("second dimension of A, ", size(A,2), ", does not match first dimension of B, ", size(B,1))))
size(C,1) == size(A,1) && size(C,2) == size(B,2) ||
throw(DimensionMismatch("A has size $(size(A)), B has size $(size(B)), C has size $(size(C))"))
throw(DimensionMismatch(LazyString("A has size ", size(A), ", B has size ", size(B), ", C has size ", size(C))))
end

function mul!(y::AbstractVector, A::AbstractFillMatrix, b::AbstractFillVector, alpha::Number, beta::Number)
Expand Down Expand Up @@ -314,7 +314,7 @@ end
function _adjvec_mul_zeros(a, b)
la, lb = length(a), length(b)
if la ≠ lb
throw(DimensionMismatch("dot product arguments have lengths $la and $lb"))
throw(DimensionMismatch(LazyString("dot product arguments have lengths ", la, " and ", lb)))
end
# ensure that all the elements of `a` are of the same size,
# so that ∑ᵢaᵢbᵢ = b₁∑ᵢaᵢ makes sense
Expand All @@ -324,7 +324,7 @@ function _adjvec_mul_zeros(a, b)
end
a1 = a[1]
sza1 = size(a1)
all(x -> size(x) == sza1, a) || throw(DimensionMismatch("not all elements of A are of size $sza1"))
all(x -> size(x) == sza1, a) || throw(DimensionMismatch(LazyString("not all elements of A are of size ", sza1)))
# we replace b₁∑ᵢaᵢ by b₁a₁, as we know that b₁ is zero.
# Each term in the summation is zero, so the sum is equal to the first term
return a1 * b[1]
Expand Down Expand Up @@ -365,7 +365,7 @@ end
*(a::TransposeAbsVec{<:Any,<:AbstractZerosVector}, D::Diagonal) = transpose(D*transpose(a))
function _triple_zeromul(x, D::Diagonal, y)
if !(length(x) == length(D.diag) == length(y))
throw(DimensionMismatch("x has length $(length(x)), D has size $(size(D)), and y has $(length(y))"))
throw(DimensionMismatch(LazyString("x has length ", length(x), ", D has size ", size(D), ", and y has ", length(y))))
end
zero(promote_type(eltype(x), eltype(D), eltype(y)))
end
Expand All @@ -381,7 +381,7 @@ end
function *(a::Transpose{T, <:AbstractVector}, b::AbstractZerosVector{T}) where T<:Real
la, lb = length(a), length(b)
if la ≠ lb
throw(DimensionMismatch("dot product arguments have lengths $la and $lb"))
throw(DimensionMismatch(LazyString("dot product arguments have lengths ", la, " and ", lb)))
end
return zero(T)
end
Expand All @@ -391,12 +391,12 @@ end
# infinite cases should be supported in InfiniteArrays.jl
# type issues of Bool dot are ignored at present.
function _fill_dot(a::AbstractFillVector{T}, b::AbstractVector{V}) where {T,V}
axes(a) == axes(b) || throw(DimensionMismatch("dot product arguments have lengths $(length(a)) and $(length(b))"))
axes(a) == axes(b) || throw(DimensionMismatch(LazyString("dot product arguments have lengths ", length(a), " and ", length(b))))
dot(getindex_value(a), sum(b))
end

function _fill_dot_rev(a::AbstractVector{T}, b::AbstractFillVector{V}) where {T,V}
axes(a) == axes(b) || throw(DimensionMismatch("dot product arguments have lengths $(length(a)) and $(length(b))"))
axes(a) == axes(b) || throw(DimensionMismatch(LazyString("dot product arguments have lengths ", length(a), " and ", length(b))))
dot(sum(a), getindex_value(b))
end

Expand All @@ -406,21 +406,21 @@ dot(a::AbstractVector, b::AbstractFillVector) = _fill_dot_rev(a, b)

function dot(u::AbstractVector, E::Eye, v::AbstractVector)
length(u) == size(E,1) && length(v) == size(E,2) ||
throw(DimensionMismatch("dot product arguments have dimensions $(length(u))×$(size(E))×$(length(v))"))
throw(DimensionMismatch(LazyString("dot product arguments have dimensions ", length(u), "×", size(E), "×", length(v))))
d = dot(u,v)
T = typeof(one(eltype(E)) * d)
convert(T, d)
end

function dot(u::AbstractVector, D::Diagonal{<:Any,<:Fill}, v::AbstractVector)
length(u) == size(D,1) && length(v) == size(D,2) ||
throw(DimensionMismatch("dot product arguments have dimensions $(length(u))×$(size(D))×$(length(v))"))
throw(DimensionMismatch(LazyString("dot product arguments have dimensions ", length(u), "×", size(D), "×", length(v))))
D.diag.value*dot(u, v)
end

function dot(u::AbstractVector{T}, D::Diagonal{U,<:Zeros}, v::AbstractVector{V}) where {T,U,V}
length(u) == size(D,1) && length(v) == size(D,2) ||
throw(DimensionMismatch("dot product arguments have dimensions $(length(u))×$(size(D))×$(length(v))"))
throw(DimensionMismatch(LazyString("dot product arguments have dimensions ", length(u), "×", size(D), "×", length(v))))
zero(promote_type(T,U,V))
end

Expand Down Expand Up @@ -510,21 +510,21 @@ function lmul!(x::Number, z::AbstractFill)
λ = getindex_value(z)
# Following check ensures consistency w/ lmul!(x, Array(z))
# for, e.g., lmul!(NaN, z)
x*λ == λ || throw(ArgumentError("Cannot scale by $x"))
x*λ == λ || throw(ArgumentError(LazyString("Cannot scale by ", x)))
z
end

function rmul!(z::AbstractFill, x::Number)
λ = getindex_value(z)
# Following check ensures consistency w/ lmul!(x, Array(z))
# for, e.g., lmul!(NaN, z)
λ*x == λ || throw(ArgumentError("Cannot scale by $x"))
λ*x == λ || throw(ArgumentError(LazyString("Cannot scale by ", x)))
z
end

fillzero(::Type{Fill{T,N,AXIS}}, n, m) where {T,N,AXIS} = Fill{T,N,AXIS}(zero(T), (n, m))
fillzero(::Type{<:AbstractZeros{T,N,AXIS}}, n, m) where {T,N,AXIS} = Zeros{T,N,AXIS}((n, m))
fillzero(::Type{F}, n, m) where F = throw(ArgumentError("Cannot create a zero array of type $F"))
fillzero(::Type{F}, n, m) where F = throw(ArgumentError(LazyString("Cannot create a zero array of type ", F)))

diagzero(D::Diagonal{F}, i, j) where F<:AbstractFill = fillzero(F, axes(D.diag[i], 1), axes(D.diag[j], 2))

Expand Down
Loading
Loading