Skip to content

Commit 24f62ed

Browse files
authored
Merge branch 'master' into jishnub/eigen
2 parents b429c82 + 9868632 commit 24f62ed

File tree

6 files changed

+166
-31
lines changed

6 files changed

+166
-31
lines changed

.github/workflows/downstream.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,13 @@ jobs:
4040
package:
4141
- {repo: Distributions.jl, group: JuliaStats}
4242
- {repo: BlockArrays.jl, group: JuliaArrays}
43-
# - {repo: LazyArrays.jl, group: JuliaArrays}
43+
- {repo: LazyArrays.jl, group: JuliaArrays}
44+
- {repo: InfiniteArrays.jl, group: JuliaArrays}
4445
- {repo: ArrayLayouts.jl, group: JuliaLinearAlgebra}
45-
# - {repo: LazyBandedMatrices.jl, group: JuliaLinearAlgebra}
46+
- {repo: LazyBandedMatrices.jl, group: JuliaLinearAlgebra}
4647
- {repo: BandedMatrices.jl, group: JuliaLinearAlgebra}
4748
- {repo: BlockBandedMatrices.jl, group: JuliaLinearAlgebra}
48-
# - {repo: InfiniteLinearAlgebra.jl, group: JuliaLinearAlgebra}
49+
- {repo: InfiniteLinearAlgebra.jl, group: JuliaLinearAlgebra}
4950
- {repo: Optim.jl, group: JuliaNLSolvers}
5051

5152
steps:

Project.toml

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "FillArrays"
22
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
3-
version = "1.11.0"
3+
version = "1.13.0"
44

55
[deps]
66
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
@@ -10,7 +10,6 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
1010

1111
[compat]
1212
Aqua = "0.8"
13-
Base64 = "1.6"
1413
Documenter = "1"
1514
Infinities = "0.1"
1615
LinearAlgebra = "1.6"
@@ -24,14 +23,18 @@ Statistics = "1.6"
2423
Test = "1.6"
2524
julia = "1.6"
2625

26+
[weakdeps]
27+
PDMats = "90014a1f-27ba-587c-ab20-58faa44d9150"
28+
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
29+
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
30+
2731
[extensions]
2832
FillArraysPDMatsExt = "PDMats"
2933
FillArraysSparseArraysExt = "SparseArrays"
3034
FillArraysStatisticsExt = "Statistics"
3135

3236
[extras]
3337
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
34-
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
3538
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
3639
Infinities = "e1ba4f0e-776d-440f-acd9-e1d2e9742647"
3740
PDMats = "90014a1f-27ba-587c-ab20-58faa44d9150"
@@ -45,8 +48,3 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
4548

4649
[targets]
4750
test = ["Aqua", "Test", "Base64", "Infinities", "PDMats", "ReverseDiff", "SparseArrays", "StaticArrays", "Statistics", "Quaternions", "Documenter", "Random"]
48-
49-
[weakdeps]
50-
PDMats = "90014a1f-27ba-587c-ab20-58faa44d9150"
51-
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
52-
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

src/FillArrays.jl

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Base: size, getindex, setindex!, IndexStyle, checkbounds, convert,
77
any, all, axes, isone, iszero, iterate, unique, allunique, permutedims, inv,
88
copy, vec, setindex!, count, ==, reshape, map, zero,
99
show, view, in, mapreduce, one, reverse, promote_op, promote_rule, repeat,
10-
parent, similar, issorted, add_sum, accumulate, OneTo
10+
parent, similar, issorted, add_sum, accumulate, OneTo, permutedims
1111

1212
import LinearAlgebra: rank, svdvals!, tril, triu, tril!, triu!, diag, transpose, adjoint, fill!,
1313
dot, norm2, norm1, normInf, normMinusInf, normp, lmul!, rmul!, diagzero, AdjointAbsVec, TransposeAbsVec,
@@ -273,17 +273,12 @@ reshape(parent::AbstractFill, dims::Tuple{Vararg{Union{Int,Colon}}}) =
273273
fill_reshape(parent, Base._reshape_uncolon(parent, dims)...)
274274
reshape(parent::AbstractFill, shp::Tuple{Union{Integer,Base.OneTo}, Vararg{Union{Integer,Base.OneTo}}}) =
275275
reshape(parent, Base.to_shape(shp))
276-
reshape(parent::AbstractFill, dims::Dims) = Base._reshape(parent, dims)
277-
reshape(parent::AbstractFill, dims::Tuple{Integer, Vararg{Integer}}) = Base._reshape(parent, dims)
276+
reshape(parent::AbstractFill, dims::Dims) = fill_reshape(parent, dims...)
277+
reshape(parent::AbstractFill, dims::Tuple{Integer, Vararg{Integer}}) = fill_reshape(parent, dims...)
278278

279279
# resolve ambiguity with Base
280280
reshape(parent::AbstractFillVector, dims::Tuple{Colon}) = parent
281281

282-
Base._reshape(parent::AbstractFill, dims::Dims) = fill_reshape(parent, dims...)
283-
Base._reshape(parent::AbstractFill, dims::Tuple{Integer,Vararg{Integer}}) = fill_reshape(parent, dims...)
284-
# Resolves ambiguity error with `_reshape(v::AbstractArray{T, 1}, dims::Tuple{Int})`
285-
Base._reshape(parent::AbstractFill{T, 1, Axes}, dims::Tuple{Int}) where {T, Axes} = fill_reshape(parent, dims...)
286-
287282
for (AbsTyp, Typ, funcs, func) in ((:AbstractZeros, :Zeros, :zeros, :zero), (:AbstractOnes, :Ones, :ones, :one))
288283
@eval begin
289284
abstract type $AbsTyp{T, N, Axes} <: AbstractFill{T, N, Axes} end

src/fillalgebra.jl

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,17 @@ for MT in (:(AbstractMatrix{T}), :(Transpose{<:Any, <:AbstractMatrix{T}}), :(Adj
102102
:(AbstractTriangular{T}))
103103
@eval *(a::$MT, b::AbstractZerosVector) where {T} = mult_zeros(a, b)
104104
end
105-
*(a::Transpose{<:Any, <:AbstractVector}, b::AbstractZerosMatrix) = transpose(transpose(b) * parent(a))
106-
*(a::Adjoint{<:Any, <:AbstractVector}, b::AbstractZerosMatrix) = adjoint(adjoint(b) * parent(a))
105+
for T in (:AbstractZerosMatrix, :AbstractFillMatrix)
106+
@eval begin
107+
*(a::Transpose{<:Any, <:AbstractVector}, b::$T) = transpose(transpose(b) * parent(a))
108+
*(a::Adjoint{<:Any, <:AbstractVector}, b::$T) = adjoint(adjoint(b) * parent(a))
109+
end
110+
end
107111
*(a::AbstractZerosMatrix, b::AbstractVector) = mult_zeros(a, b)
112+
function *(F::AbstractFillMatrix, v::AbstractVector)
113+
check_matmul_sizes(F, v)
114+
Fill(getindex_value(F) * sum(v), (axes(F,1),))
115+
end
108116

109117
function lmul_diag(a::Diagonal, b)
110118
size(a,2) == size(b,1) || throw(DimensionMismatch("A has dimensions $(size(a)) but B has dimensions $(size(b))"))
@@ -322,7 +330,7 @@ function _adjvec_mul_zeros(a, b)
322330
return a1 * b[1]
323331
end
324332

325-
for MT in (:AbstractMatrix, :AbstractTriangular, :(Adjoint{<:Any,<:TransposeAbsVec}))
333+
for MT in (:AbstractMatrix, :AbstractTriangular, :(Adjoint{<:Any,<:TransposeAbsVec}), :AbstractFillMatrix)
326334
@eval *(a::AdjointAbsVec{<:Any,<:AbstractZerosVector}, b::$MT) = (b' * a')'
327335
end
328336
# ambiguity
@@ -332,7 +340,7 @@ function *(a::AdjointAbsVec{<:Any,<:AbstractZerosVector}, b::TransposeAbsVec{<:A
332340
a * b2
333341
end
334342
*(a::AdjointAbsVec{<:Any,<:AbstractZerosVector}, b::AbstractZerosMatrix) = (b' * a')'
335-
for MT in (:AbstractMatrix, :AbstractTriangular, :(Transpose{<:Any,<:AdjointAbsVec}))
343+
for MT in (:AbstractMatrix, :AbstractTriangular, :(Transpose{<:Any,<:AdjointAbsVec}), :AbstractFillMatrix)
336344
@eval *(a::TransposeAbsVec{<:Any,<:AbstractZerosVector}, b::$MT) = transpose(transpose(b) * transpose(a))
337345
end
338346
*(a::TransposeAbsVec{<:Any,<:AbstractZerosVector}, b::AbstractZerosMatrix) = transpose(transpose(b) * transpose(a))
@@ -463,7 +471,7 @@ end
463471

464472
@inline function fill_add(a::AbstractArray, b::AbstractFill)
465473
promote_shape(a, b)
466-
a .+ [getindex_value(b)]
474+
a .+ (getindex_value(b),)
467475
end
468476
@inline function fill_add(a::AbstractArray{<:Number}, b::AbstractFill)
469477
promote_shape(a, b)

src/oneelement.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,25 @@ OneElement{T}(inds::Int, sz::Int) where T = OneElement(one(T), inds, sz)
4242

4343
Base.size(A::OneElement) = map(length, A.axes)
4444
Base.axes(A::OneElement) = A.axes
45+
Base.getindex(A::OneElement{T,0}) where {T} = getindex_value(A)
4546
Base.@propagate_inbounds function Base.getindex(A::OneElement{T,N}, kj::Vararg{Int,N}) where {T,N}
4647
@boundscheck checkbounds(A, kj...)
4748
ifelse(kj == A.ind, A.val, zero(T))
4849
end
50+
const VectorInds = Union{AbstractUnitRange{<:Integer}, Integer} # no index is repeated for these indices
51+
const VectorIndsWithColon = Union{VectorInds, Colon}
52+
# retain the values from Ainds corresponding to the vector indices in inds
53+
_index_shape(Ainds, inds::Tuple{Integer, Vararg{Any}}) = _index_shape(Base.tail(Ainds), Base.tail(inds))
54+
_index_shape(Ainds, inds::Tuple{AbstractVector, Vararg{Any}}) = (Ainds[1], _index_shape(Base.tail(Ainds), Base.tail(inds))...)
55+
_index_shape(::Tuple{}, ::Tuple{}) = ()
56+
Base.@propagate_inbounds function Base.getindex(A::OneElement{T,N}, inds::Vararg{VectorIndsWithColon,N}) where {T,N}
57+
I = to_indices(A, inds) # handle Bool, and convert to compatible index types
58+
@boundscheck checkbounds(A, I...)
59+
shape = _index_shape(I, I)
60+
nzind = _index_shape(A.ind, I) .- first.(shape) .+ firstindex.(shape)
61+
containsval = all(in.(A.ind, I))
62+
OneElement(getindex_value(A), containsval ? Int.(nzind) : Int.(lastindex.(shape,1)).+1, axes.(shape,1))
63+
end
4964

5065
"""
5166
nzind(A::OneElement{T,N}) -> CartesianIndex{N}
@@ -411,6 +426,12 @@ function Base.reshape(A::OneElement, shape::Tuple{Vararg{Int}})
411426
OneElement(A.val, Tuple(newcartind), shape)
412427
end
413428

429+
#permute
430+
_permute(x, p) = ntuple(i -> x[p[i]], length(x))
431+
permutedims(o::OneElementMatrix) = OneElement(o.val, reverse(o.ind), reverse(o.axes))
432+
permutedims(o::OneElementVector) = reshape(o, (1, length(o)))
433+
permutedims(o::OneElement, dims) = OneElement(o.val, _permute(o.ind, dims), _permute(o.axes, dims))
434+
414435
# show
415436
_maybesize(t::Tuple{Base.OneTo{Int}, Vararg{Base.OneTo{Int}}}) = size.(t,1)
416437
_maybesize(t) = t

test/runtests.jl

Lines changed: 119 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using FillArrays, LinearAlgebra, PDMats, SparseArrays, StaticArrays, ReverseDiff, Random, Base64, Test, Statistics, Quaternions
1+
using FillArrays, LinearAlgebra, PDMats, SparseArrays, StaticArrays, ReverseDiff, Random, Test, Statistics, Quaternions
2+
23
import FillArrays: AbstractFill, RectDiagonal, SquareEye
34

45
using Documenter
@@ -14,6 +15,8 @@ import .InfiniteArrays
1415
oneton(T::Type, sz...) = reshape(T.(1:prod(sz)), sz)
1516
oneton(sz...) = oneton(Float64, sz...)
1617

18+
stringmime(args...) = sprint(show, args...)
19+
1720
@testset "fill array constructors and convert" begin
1821
for (Typ, funcs) in ((Zeros, zeros), (Ones, ones))
1922
@test Typ((-1,5)) == Typ((0,5))
@@ -1640,14 +1643,16 @@ end
16401643

16411644
@test Fill(2,3)*A Vector(Fill(2,3))*A
16421645
@test Fill(2,0)*A Vector(Fill(2,0))*A
1643-
@test Fill(2,3,mA)*A Matrix(Fill(2,3,mA))*A
1644-
@test Fill(2,3,la)*a Matrix(Fill(2,3,la))*a
1646+
@test Fill(2,3,mA)*A mul!(similar(A, 3,nA), Fill(2,3,mA), A) Matrix(Fill(2,3,mA))*A
1647+
@test Fill(2,3,la)*a mul!(similar(a, 3), Fill(2,3,la), a) Matrix(Fill(2,3,la))*a
1648+
@test Fill(2,3,la)*a isa Fill
16451649
@test Ones(3)*A Vector(Ones(3))*A
1646-
@test Ones(3,mA)*A Matrix(Ones(3,mA))*A
1647-
@test Ones(3,la)*a Matrix(Ones(3,la))*a
1650+
@test Ones(3,mA)*A mul!(similar(A, 3, nA), Ones(3,mA), A) Matrix(Ones(3,mA))*A
1651+
@test Ones(3,la)*a mul!(similar(a, 3), Ones(3,la), a) Matrix(Ones(3,la))*a
1652+
@test Ones(3,la)*a isa Fill
16481653
@test Zeros(3)*A Zeros(3,nA)
1649-
@test Zeros(3,mA)*A == Zeros(3,nA)
1650-
@test Zeros(3,la)*a == Zeros(3)
1654+
@test Zeros(3,mA)*A == mul!(similar(A, 3, nA), Zeros(3,mA), A) == Zeros(3,nA)
1655+
@test Zeros(3,la)*a == mul!(similar(A, 3), Zeros(3,la), a) == Zeros(3)
16511656

16521657
@test A*Fill(2,nA) A*Vector(Fill(2,nA))
16531658
@test A*Fill(2,nA,1) A*Matrix(Fill(2,nA,1))
@@ -1669,6 +1674,17 @@ end
16691674

16701675
@test Zeros(la)' * Transpose(Adjoint(a)) == 0.0
16711676

1677+
F = Fill(2, mA, 3)
1678+
@test transpose(A) * F transpose(Fill(2, 3, mA) * A)
1679+
F = Fill(2, la, 3)
1680+
FS = Fill(2, (Base.OneTo(la), SOneTo(3)))
1681+
@testset for (adjf, adjT) in ((transpose, Transpose), (adjoint, Adjoint))
1682+
@test adjf(a) * F adjf(Fill(2, 3, la) * a)
1683+
@test adjf(a) * F isa adjT{<:Any, <:Fill{<:Any,1}}
1684+
@test adjf(a) * FS adjf(Fill(2, 3, la) * a)
1685+
@test axes(adjf(a) * FS, 2) == SOneTo(3)
1686+
end
1687+
16721688
w = zeros(mA)
16731689
@test mul!(w, A, Fill(2,nA), true, false) A * fill(2,nA)
16741690
w .= 2
@@ -2148,10 +2164,12 @@ end
21482164
@test FillArrays.nzind(A) == CartesianIndex()
21492165
@test A == Fill(2, ())
21502166
@test A[] === 2
2167+
@test A[1] === A[1,1] === 2
21512168

21522169
e₁ = OneElement(2, 5)
21532170
@test e₁ == [0,1,0,0,0]
21542171
@test FillArrays.nzind(e₁) == CartesianIndex(2)
2172+
@test e₁[2] === e₁[2,1] === e₁[2,1,1] === 1
21552173
@test_throws BoundsError e₁[6]
21562174

21572175
f₁ = AbstractArray{Float64}(e₁)
@@ -2193,6 +2211,89 @@ end
21932211
@test A[1,1] === A[1,2] === A[2,1] === zero(S)
21942212
end
21952213

2214+
@testset "Vector indexing" begin
2215+
@testset "1D" begin
2216+
A = OneElement(2, 2, 4)
2217+
@test @inferred(A[:]) === @inferred(A[axes(A)...]) === A
2218+
@test @inferred(A[3:4]) isa OneElement{Int,1}
2219+
@test @inferred(A[3:4]) == Zeros(2)
2220+
@test @inferred(A[1:2]) === OneElement(2, 2, 2)
2221+
@test @inferred(A[2:3]) === OneElement(2, 1, 2)
2222+
@test @inferred(A[Base.IdentityUnitRange(2:3)]) isa OneElement{Int,1}
2223+
@test @inferred(A[Base.IdentityUnitRange(2:3)]) == OneElement(2,(2,),(Base.IdentityUnitRange(2:3),))
2224+
@test A[:,:] == reshape(A, size(A)..., 1)
2225+
2226+
@test A[reverse(axes(A,1))] == A[collect(reverse(axes(A,1)))]
2227+
2228+
@testset "repeated indices" begin
2229+
@test A[StepRangeLen(2, 0, 3)] == A[fill(2, 3)]
2230+
end
2231+
2232+
B = OneElement(2, (2,), (Base.IdentityUnitRange(-1:4),))
2233+
@test @inferred(A[:]) === @inferred(A[axes(A)...]) === A
2234+
@test @inferred(A[3:4]) isa OneElement{Int,1}
2235+
@test @inferred(A[3:4]) == Zeros(2)
2236+
@test @inferred(A[2:3]) === OneElement(2, 1, 2)
2237+
2238+
C = OneElement(2, (2,), (Base.OneTo(big(4)),))
2239+
@test @inferred(C[1:4]) === OneElement(2, 2, 4)
2240+
2241+
D = OneElement(2, (2,), (InfiniteArrays.OneToInf(),))
2242+
D2 = D[:]
2243+
@test axes(D2) == axes(D)
2244+
@test D2[2] == D[2]
2245+
D3 = D[axes(D)...]
2246+
@test axes(D3) == axes(D)
2247+
@test D3[2] == D[2]
2248+
end
2249+
@testset "2D" begin
2250+
A = OneElement(2, (2,3), (4,5))
2251+
@test @inferred(A[:,:]) === @inferred(A[axes(A)...]) === A
2252+
@test @inferred(A[:,1]) isa OneElement{Int,1}
2253+
@test @inferred(A[:,1]) == Zeros(4)
2254+
@test A[:, Int64(1)] === A[:, Int32(1)]
2255+
@test @inferred(A[1,:]) isa OneElement{Int,1}
2256+
@test @inferred(A[1,:]) == Zeros(5)
2257+
@test @inferred(A[:,3]) === OneElement(2, 2, 4)
2258+
@test @inferred(A[2,:]) === OneElement(2, 3, 5)
2259+
@test @inferred(A[1:1,:]) isa OneElement{Int,2}
2260+
@test @inferred(A[1:1,:]) == Zeros(1,5)
2261+
@test @inferred(A[4:4,:]) isa OneElement{Int,2}
2262+
@test @inferred(A[4:4,:]) == Zeros(1,5)
2263+
@test @inferred(A[2:2,:]) === OneElement(2, (1,3), (1,5))
2264+
@test @inferred(A[1:4,:]) === OneElement(2, (2,3), (4,5))
2265+
@test @inferred(A[:,3:3]) === OneElement(2, (2,1), (4,1))
2266+
@test @inferred(A[:,1:5]) === OneElement(2, (2,3), (4,5))
2267+
@test @inferred(A[1:4,1:4]) === OneElement(2, (2,3), (4,4))
2268+
@test @inferred(A[2:4,2:4]) === OneElement(2, (1,2), (3,3))
2269+
@test @inferred(A[2:4,3:4]) === OneElement(2, (1,1), (3,2))
2270+
@test @inferred(A[4:4,5:5]) isa OneElement{Int,2}
2271+
@test @inferred(A[4:4,5:5]) == Zeros(1,1)
2272+
@test @inferred(A[Base.IdentityUnitRange(2:4), :]) isa OneElement{Int,2}
2273+
@test axes(A[Base.IdentityUnitRange(2:4), :]) == (Base.IdentityUnitRange(2:4), axes(A,2))
2274+
@test @inferred(A[:,:,:]) == reshape(A, size(A)...,1)
2275+
2276+
B = OneElement(2, (2,3), (Base.IdentityUnitRange(2:4),Base.IdentityUnitRange(2:5)))
2277+
@test @inferred(B[:,:]) === @inferred(B[axes(B)...]) === B
2278+
@test @inferred(B[:,3]) === OneElement(2, (2,), (Base.IdentityUnitRange(2:4),))
2279+
@test @inferred(B[3:4, 4:5]) isa OneElement{Int,2}
2280+
@test @inferred(B[3:4, 4:5]) == Zeros(2,2)
2281+
b = @inferred(B[Base.IdentityUnitRange(3:4), Base.IdentityUnitRange(4:5)])
2282+
@test b == Zeros(axes(b))
2283+
2284+
C = OneElement(2, (2,3), (Base.OneTo(big(4)), Base.OneTo(big(5))))
2285+
@test @inferred(C[1:4, 1:5]) === OneElement(2, (2,3), Int.(size(C)))
2286+
2287+
D = OneElement(2, (2,3), (InfiniteArrays.OneToInf(), InfiniteArrays.OneToInf()))
2288+
D2 = @inferred D[:,:]
2289+
@test axes(D2) == axes(D)
2290+
@test D2[2,3] == D[2,3]
2291+
D3 = @inferred D[axes(D)...]
2292+
@test axes(D3) == axes(D)
2293+
@test D3[2,3] == D[2,3]
2294+
end
2295+
end
2296+
21962297
@testset "adjoint/transpose" begin
21972298
A = OneElement(3im, (2,4), (4,6))
21982299
@test A' === OneElement(-3im, (4,2), (6,4))
@@ -2579,6 +2680,17 @@ end
25792680
end
25802681
end
25812682

2683+
@testset "permutedims" begin
2684+
v = OneElement(1, (2, 3), (2, 5))
2685+
@test permutedims(v) === OneElement(1, (3, 2), (5, 2))
2686+
w = OneElement(1, 3, 5)
2687+
@test permutedims(w) === OneElement(1, (1, 3), (1, 5))
2688+
x = OneElement(1, (1, 2, 3), (4, 5, 6))
2689+
@test permutedims(x, (1, 2, 3)) === x
2690+
@test permutedims(x, (3, 2, 1)) === OneElement(1, (3, 2, 1), (6, 5, 4))
2691+
@test permutedims(x, [2, 3, 1]) === OneElement(1, (2, 3, 1), (5, 6, 4))
2692+
@test_throws BoundsError permutedims(x, (2, 1))
2693+
end
25822694
@testset "show" begin
25832695
B = OneElement(2, (1, 2), (3, 4))
25842696
@test repr(B) == "OneElement(2, (1, 2), (3, 4))"

0 commit comments

Comments
 (0)