From e130fc04f488820d6c9a11135be54cc08761e1ce Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Thu, 4 Apr 2024 23:23:22 +0530 Subject: [PATCH 1/2] Add convenience constructors for OneElement --- src/oneelement.jl | 98 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 85 insertions(+), 13 deletions(-) diff --git a/src/oneelement.jl b/src/oneelement.jl index f1e2fd8e..0498f154 100644 --- a/src/oneelement.jl +++ b/src/oneelement.jl @@ -17,28 +17,87 @@ const OneElementVector{T,I,A} = OneElement{T,1,I,A} const OneElementMatrix{T,I,A} = OneElement{T,2,I,A} const OneElementVecOrMat{T,I,A} = Union{OneElementVector{T,I,A}, OneElementMatrix{T,I,A}} +""" + OneElement(val, inds::NTuple{N,Int}, sz::NTuple{N,Integer}) + +Create an array with size `sz` where the index `ind` is set to `val`, and all other entries are zero. + +# Examples +```jldoctest +julia> OneElement(3, (1,2), (2,2)) +2×2 OneElement{Int64, 2, Tuple{Int64, Int64}, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}: + ⋅ 3 + ⋅ ⋅ +``` +""" OneElement(val, inds::NTuple{N,Int}, sz::NTuple{N,Integer}) where N = OneElement(val, inds, oneto.(sz)) + """ OneElement(val, ind::Int, n::Int) -Creates a length `n` vector where the `ind` entry is equal to `val`, and all other entries are zero. +Create a length-`n` vector where the index `ind` is set to `val`, and all other entries are zero. + +# Examples +```jldoctest +julia> OneElement(5, 2, 3) +3-element OneElement{Int64, 1, Tuple{Int64}, Tuple{Base.OneTo{Int64}}}: + ⋅ + 5 + ⋅ +``` """ OneElement(val, ind::Int, len::Int) = OneElement(val, (ind,), (len,)) -""" - OneElement(ind::Int, n::Int) -Creates a length `n` vector where the `ind` entry is equal to `1`, and all other entries are zero. """ -OneElement(inds::Int, sz::Int) = OneElement(1, inds, sz) -OneElement{T}(val, inds::NTuple{N,Int}, sz::NTuple{N,Integer}) where {T,N} = OneElement(convert(T,val), inds, oneto.(sz)) -OneElement{T}(val, inds::Int, sz::Int) where T = OneElement{T}(val, (inds,), (sz,)) - + OneElement(ind::Int, n::Int = ind) + OneElement{T}(ind::Int, n::Int = ind) + +Create a length-`n` vector where the index `ind` is set to `1` (or `oneunit(T)` in the second form), +and all other entries are zero. If `n` is unspecified, it is assumed to be equal to `ind`. + +# Examples +```jldoctest +julia> OneElement(2, 3) +3-element OneElement{Int64, 1, Tuple{Int64}, Tuple{Base.OneTo{Int64}}}: + ⋅ + 1 + ⋅ + +julia> OneElement{Int8}(2) +2-element OneElement{Int8, 1, Tuple{Int64}, Tuple{Base.OneTo{Int64}}}: + ⋅ + 1 +``` """ - OneElement{T}(val, ind::Int, n::Int) +OneElement(ind::Int, sz::Int = ind) = OneElement(1, ind, sz) +OneElement{T}(ind::Int, sz::Int = ind) where {T} = OneElement(oneunit(T), ind, sz) +OneElement{T}(val, ind::Int, sz::Int) where {T} = OneElement(convert(T,val), ind, sz) -Creates a length `n` vector where the `ind` entry is equal to `one(T)`, and all other entries are zero. """ -OneElement{T}(inds::Int, sz::Int) where T = OneElement(one(T), inds, sz) + OneElement(inds::NTuple{N,Int}, sz::NTuple{N,Integer} = inds) + OneElement{T}(inds::NTuple{N,Int}, sz::NTuple{N,Integer} = inds) + +Create an array with size `sz`, where the index `inds` is set to `1` +(or `oneunit(T)` in the second form), and all other entries are zero. +If `sz` is unspecified, it is assumed to be equal to `inds`. + +# Examples +```jldoctest +julia> OneElement((1,2), (2,3)) +2×3 OneElement{Int64, 2, Tuple{Int64, Int64}, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}: + ⋅ 1 ⋅ + ⋅ ⋅ ⋅ + +julia> OneElement{Int8}((2,2)) +2×2 OneElement{Int8, 2, Tuple{Int64, Int64}, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}: + ⋅ ⋅ + ⋅ 1 +``` +""" +OneElement(inds::NTuple{N,Int}, sz::NTuple{N,Integer} = inds) where {N} = OneElement(1, inds, sz) +OneElement{T}(inds::NTuple{N,Int}, sz::NTuple{N,Integer} = inds) where {T,N} = OneElement(oneunit(T), inds, sz) +OneElement{T}(val, inds::NTuple{N,Int}, sz::NTuple{N,Integer}) where {T,N} = OneElement(convert(T,val), inds, sz) + Base.size(A::OneElement) = map(length, A.axes) Base.axes(A::OneElement) = A.axes @@ -334,5 +393,18 @@ end _maybesize(t::Tuple{Base.OneTo{Int}, Vararg{Base.OneTo{Int}}}) = size.(t,1) _maybesize(t) = t Base.show(io::IO, A::OneElement) = print(io, OneElement, "(", A.val, ", ", A.ind, ", ", _maybesize(axes(A)), ")") -Base.show(io::IO, A::OneElement{<:Any,1,Tuple{Int},Tuple{Base.OneTo{Int}}}) = - print(io, OneElement, "(", A.val, ", ", A.ind[1], ", ", size(A,1), ")") +function Base.show(io::IO, A::OneElement{<:Any,1,Tuple{Int},Tuple{Base.OneTo{Int}}}) + print(io, OneElement) + if eltype(A) != Int + print(io, "{", eltype(A), "}") + end + print(io, "(") + if !isone(A.val) + print(io, A.val, ", ") + end + print(io, A.ind[1]) + if A.ind[1] != size(A,1) + print(io, ", ", size(A,1)) + end + print(io, ")") +end From ba819b8cd7ff0ecb56184bf8041df22f0c31d2ca Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Fri, 5 Apr 2024 13:19:00 +0530 Subject: [PATCH 2/2] Show inds and axes consistently --- src/oneelement.jl | 20 ++++++++++++-------- test/runtests.jl | 25 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/oneelement.jl b/src/oneelement.jl index 0498f154..1ce02ef2 100644 --- a/src/oneelement.jl +++ b/src/oneelement.jl @@ -392,19 +392,23 @@ end # show _maybesize(t::Tuple{Base.OneTo{Int}, Vararg{Base.OneTo{Int}}}) = size.(t,1) _maybesize(t) = t -Base.show(io::IO, A::OneElement) = print(io, OneElement, "(", A.val, ", ", A.ind, ", ", _maybesize(axes(A)), ")") -function Base.show(io::IO, A::OneElement{<:Any,1,Tuple{Int},Tuple{Base.OneTo{Int}}}) +function Base.show(io::IO, @nospecialize(A::OneElement)) + # We always print the inds and axes (or size, for Base.OneTo axes) + # We print the value only if it isn't 1 + # this way, we have at least two arguments displayed that are unambiguous print(io, OneElement) - if eltype(A) != Int + isvector = ndims(A) == 1 + sz = _maybesize(axes(A)) + hasstandardaxes = sz isa Tuple{Vararg{Integer}} + isstandardvector = isvector & hasstandardaxes + if hasstandardaxes && eltype(A) != Int && isone(A.val) print(io, "{", eltype(A), "}") end print(io, "(") - if !isone(A.val) + if !(hasstandardaxes && isone(A.val)) print(io, A.val, ", ") end - print(io, A.ind[1]) - if A.ind[1] != size(A,1) - print(io, ", ", size(A,1)) - end + print(io, isstandardvector ? A.ind[1] : A.ind, ", ") + print(io, isstandardvector ? sz[1] : sz) print(io, ")") end diff --git a/test/runtests.jl b/test/runtests.jl index 380c15f8..09174e1a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2346,6 +2346,31 @@ end @test repr(B) == "OneElement(2, 1, 3)" B = OneElement(2, (1, 2), (Base.IdentityUnitRange(1:1), Base.IdentityUnitRange(2:2))) @test repr(B) == "OneElement(2, (1, 2), (Base.IdentityUnitRange(1:1), Base.IdentityUnitRange(2:2)))" + + B = OneElement(2.0, (1, 2), (3, 4)) + @test repr(B) == "OneElement(2.0, (1, 2), (3, 4))" + B = OneElement(2.0, 1, 3) + @test repr(B) == "OneElement(2.0, 1, 3)" + B = OneElement(2.0, (1, 2), (Base.IdentityUnitRange(1:1), Base.IdentityUnitRange(2:2))) + @test repr(B) == "OneElement(2.0, (1, 2), (Base.IdentityUnitRange(1:1), Base.IdentityUnitRange(2:2)))" + + B = OneElement((1, 2), (3, 4)) + @test repr(B) == "OneElement((1, 2), (3, 4))" + B = OneElement((1, 2)) + @test repr(B) == "OneElement((1, 2), (1, 2))" + B = OneElement(2, 3) + @test repr(B) == "OneElement(2, 3)" + B = OneElement(2) + @test repr(B) == "OneElement(2, 2)" + + B = OneElement{Bool}((1, 2), (3, 4)) + @test repr(B) == "OneElement{Bool}((1, 2), (3, 4))" + B = OneElement(1.0, (1, 2), (3, 4)) + @test repr(B) == "OneElement{Float64}((1, 2), (3, 4))" + B = OneElement{Bool}(2, 3) + @test repr(B) == "OneElement{Bool}(2, 3)" + B = OneElement(1.0, 2, 3) + @test repr(B) == "OneElement{Float64}(2, 3)" end end