Skip to content

Commit 8b122c8

Browse files
authored
Adjust to !(AbstractQ <: AbstractMatrix) (#122)
* Adjust to `!(AbstractQ <: AbstractMatrix)` * be more restrictive
1 parent 90002ca commit 8b122c8

File tree

10 files changed

+98
-66
lines changed

10 files changed

+98
-66
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "InfiniteLinearAlgebra"
22
uuid = "cde9dba0-b1de-11e9-2c62-0bab9446c55c"
3-
version = "0.6.13"
3+
version = "0.6.14"
44

55
[deps]
66
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"

src/InfiniteLinearAlgebra.jl

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ using BlockArrays, BlockBandedMatrices, BandedMatrices, LazyArrays, LazyBandedMa
55

66
import Base: +, -, *, /, \, ^, OneTo, getindex, promote_op, _unsafe_getindex, size, axes, length,
77
AbstractMatrix, AbstractArray, Matrix, Array, Vector, AbstractVector, Slice,
8-
show, getproperty, copy, copyto!, map, require_one_based_indexing, similar, inv
8+
show, getproperty, copy, copyto!, map, require_one_based_indexing, similar, inv,
9+
oneto, unitrange
910
import Base.Broadcast: BroadcastStyle, Broadcasted, broadcasted
1011

1112
import ArrayLayouts: colsupport, rowsupport, triangularlayout, MatLdivVec, triangulardata, TriangularLayout, TridiagonalLayout,
@@ -17,7 +18,7 @@ import FillArrays: AbstractFill, getindex_value, axes_print_matrix_row
1718
import InfiniteArrays: OneToInf, InfUnitRange, Infinity, PosInfinity, InfiniteCardinal, InfStepRange, AbstractInfUnitRange, InfAxes, InfRanges
1819
import LinearAlgebra: matprod, qr, AbstractTriangular, AbstractQ, adjoint, transpose, AdjOrTrans
1920
import LazyArrays: applybroadcaststyle, CachedArray, CachedMatrix, CachedVector, DenseColumnMajor, FillLayout, ApplyMatrix, check_mul_axes, LazyArrayStyle,
20-
resizedata!, MemoryLayout, most,
21+
resizedata!, MemoryLayout,
2122
factorize, sub_materialize, LazyLayout, LazyArrayStyle, layout_getindex,
2223
applylayout, ApplyLayout, PaddedLayout, CachedLayout, cacheddata, zero!, MulAddStyle,
2324
LazyArray, LazyMatrix, LazyVector, paddeddata, arguments
@@ -40,17 +41,13 @@ import DSP: conv
4041
import SemiseparableMatrices: AbstractAlmostBandedLayout, _almostbanded_qr!
4142

4243

43-
if VERSION < v"1.6-"
44-
oneto(n) = Base.OneTo(n)
45-
else
46-
import Base: oneto, unitrange
47-
end
48-
4944
if VERSION v"1.7-"
50-
LinearAlgebra._cut_B(x::AbstractVector, r::InfUnitRange) = x
51-
LinearAlgebra._cut_B(X::AbstractMatrix, r::InfUnitRange) = X
45+
LinearAlgebra._cut_B(x::AbstractVector, ::InfUnitRange) = x
46+
LinearAlgebra._cut_B(X::AbstractMatrix, ::InfUnitRange) = X
5247
end
5348

49+
const AdjointQtype = isdefined(LinearAlgebra, :AdjointQ) ? LinearAlgebra.AdjointQ : Adjoint
50+
5451
# BroadcastStyle(::Type{<:BandedMatrix{<:Any,<:Any,<:OneToInf}}) = LazyArrayStyle{2}()
5552

5653
function ArrayLayouts._power_by_squaring(_, ::NTuple{2,InfiniteCardinal{0}}, A::AbstractMatrix{T}, p::Integer) where T

src/banded/hessenbergq.jl

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,39 @@
11
isorthogonal(::AbstractQ) = true
22
isorthogonal(q) = q'q I
33

4+
convert_eltype(Q::AbstractMatrix, ::Type{T}) where {T} = convert(AbstractMatrix{T}, Q)
5+
if !(AbstractQ <: AbstractMatrix)
6+
convert_eltype(Q::AbstractQ, ::Type{T}) where {T} = convert(AbstractQ{T}, Q)
7+
end
8+
49
"""
510
QLHessenberg(factors, q)
611
712
represents a Hessenberg QL factorization where factors contains L in its
813
lower triangular components and q is a vector of 2x2 orthogonal transformations
914
whose product gives Q.
1015
"""
11-
struct QLHessenberg{T,S<:AbstractMatrix{T},QT<:AbstractVector{<:AbstractMatrix{T}}} <: Factorization{T}
16+
struct QLHessenberg{T,S<:AbstractMatrix{T},QT<:AbstractVector{<:Union{AbstractMatrix{T},AbstractQ{T}}}} <: Factorization{T}
1217
factors::S
1318
q::QT
1419

15-
function QLHessenberg{T,S,QT}(factors, q) where {T,S<:AbstractMatrix{T},QT<:AbstractVector{<:AbstractMatrix{T}}}
20+
function QLHessenberg{T,S,QT}(factors, q) where {T,S<:AbstractMatrix{T},QT<:AbstractVector{<:Union{AbstractMatrix{T},AbstractQ{T}}}}
1621
require_one_based_indexing(factors)
1722
new{T,S,QT}(factors, q)
1823
end
1924
end
2025

21-
QLHessenberg(factors::AbstractMatrix{T}, q::AbstractVector{<:AbstractMatrix{T}}) where {T} = QLHessenberg{T,typeof(factors),typeof(q)}(factors, q)
26+
QLHessenberg(factors::AbstractMatrix{T}, q::AbstractVector{<:Union{AbstractMatrix{T},AbstractQ{T}}}) where {T} =
27+
QLHessenberg{T,typeof(factors),typeof(q)}(factors, q)
2228
QLHessenberg{T}(factors::AbstractMatrix, q::AbstractVector) where {T} =
23-
QLHessenberg(convert(AbstractMatrix{T}, factors), convert.(AbstractMatrix{T}, q))
29+
QLHessenberg(convert(AbstractMatrix{T}, factors), convert_eltype.(q, T))
2430

2531
# iteration for destructuring into components
2632
Base.iterate(S::QLHessenberg) = (S.Q, Val(:L))
2733
Base.iterate(S::QLHessenberg, ::Val{:L}) = (S.L, Val(:done))
2834
Base.iterate(S::QLHessenberg, ::Val{:done}) = nothing
2935

30-
QLHessenberg{T}(A::QLHessenberg) where {T} = QLHessenberg(convert(AbstractMatrix{T}, A.factors), convert.(AbstractMatrix{T}, A.q))
36+
QLHessenberg{T}(A::QLHessenberg) where {T} = QLHessenberg(convert(AbstractMatrix{T}, A.factors), convert_eltype.(A.q, T))
3137
Factorization{T}(A::QLHessenberg{T}) where {T} = A
3238
Factorization{T}(A::QLHessenberg) where {T} = QLHessenberg{T}(A)
3339
AbstractMatrix(F::QLHessenberg) = F.Q * F.L
@@ -69,16 +75,16 @@ abstract type AbstractHessenbergQ{T} <: LayoutQ{T} end
6975

7076
for Typ in (:UpperHessenbergQ, :LowerHessenbergQ)
7177
@eval begin
72-
struct $Typ{T, QT<:AbstractVector{<:AbstractMatrix{T}}} <: AbstractHessenbergQ{T}
78+
struct $Typ{T, QT<:AbstractVector{<:Union{AbstractMatrix{T},AbstractQ{T}}}} <: AbstractHessenbergQ{T}
7379
q::QT
74-
function $Typ{T,QT}(q::QT) where {T,QT<:AbstractVector{<:AbstractMatrix{T}}}
80+
function $Typ{T,QT}(q::QT) where {T,QT<:AbstractVector{<:Union{AbstractMatrix{T},AbstractQ{T}}}}
7581
all(isorthogonal.(q)) || throw(ArgumentError("input must be orthogonal"))
7682
all(size.(q) .== Ref((2,2))) || throw(ArgumentError("input must be 2x2"))
7783
new{T,QT}(q)
7884
end
7985
end
8086

81-
$Typ(q::AbstractVector{<:AbstractMatrix{T}}) where T =
87+
$Typ(q::AbstractVector{<:Union{AbstractMatrix{T},AbstractQ{T}}}) where {T} =
8288
$Typ{T,typeof(q)}(q)
8389
end
8490
end
@@ -141,13 +147,12 @@ end
141147
# getindex
142148
####
143149

144-
function getindex(Q::UpperHessenbergQ, i::Int, j::Int)
145-
y = zeros(eltype(Q), size(Q, 2))
146-
y[j] = 1
147-
lmul!(Q, y)[i]
148-
end
150+
getindex(Q::UpperHessenbergQ, I::AbstractVector{Int}, J::AbstractVector{Int}) =
151+
hcat((Q[:,j][I] for j in J)...)
149152

150153
getindex(Q::LowerHessenbergQ, i::Int, j::Int) = (Q')[j,i]'
154+
getindex(Q::LowerHessenbergQ, I::AbstractVector{Int}, J::AbstractVector{Int}) =
155+
[Q[i,j] for i in I, j in J]
151156

152157

153158
###

src/banded/infbanded.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ getindex(B::InfBandCartesianIndices, k::Int) = B.b ≥ 0 ? CartesianIndex(k, k+B
1515

1616
Base.checkindex(::Type{Bool}, ::NTuple{2,OneToInf{Int}}, ::InfBandCartesianIndices) = true
1717
BandedMatrices.band_to_indices(_, ::NTuple{2,OneToInf{Int}}, b) = (InfBandCartesianIndices(b),)
18-
Base.BroadcastStyle(::Type{<:SubArray{<:Any,1,<:Any,Tuple{InfBandCartesianIndices}}}) = LazyArrayStyle{1}()
18+
BroadcastStyle(::Type{<:SubArray{<:Any,1,<:Any,Tuple{InfBandCartesianIndices}}}) = LazyArrayStyle{1}()
1919

2020
_inf_banded_sub_materialize(_, V) = V
2121
function _inf_banded_sub_materialize(::BandedColumns, V)
@@ -487,7 +487,7 @@ for Typ in (:(LinearAlgebra.Tridiagonal{<:Any,<:InfFill}),
487487
:(LazyBandedMatrices.SymTridiagonal{<:Any,<:InfFill,<:InfFill}))
488488
@eval begin
489489
MemoryLayout(::Type{<:$Typ}) = TridiagonalToeplitzLayout()
490-
Base.BroadcastStyle(::Type{<:$Typ}) = LazyArrayStyle{2}()
490+
BroadcastStyle(::Type{<:$Typ}) = LazyArrayStyle{2}()
491491
end
492492
end
493493

@@ -497,7 +497,7 @@ for Typ in (:(LinearAlgebra.Bidiagonal{<:Any,<:InfFill}),
497497
:(LazyBandedMatrices.Bidiagonal{<:Any,<:InfFill,<:InfFill}))
498498
@eval begin
499499
MemoryLayout(::Type{<:$Typ}) = BidiagonalToeplitzLayout()
500-
Base.BroadcastStyle(::Type{<:$Typ}) = LazyArrayStyle{2}()
500+
BroadcastStyle(::Type{<:$Typ}) = LazyArrayStyle{2}()
501501
end
502502
end
503503

src/banded/infqltoeplitz.jl

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,18 @@ struct ProductQ{T,QQ<:Tuple} <: LayoutQ{T}
8888
Qs::QQ
8989
end
9090

91-
ArrayLayouts.@layoutmatrix ProductQ
92-
ArrayLayouts.@_layoutlmul ProductQ
91+
if VERSION < v"1.8-"
92+
ArrayLayouts.@layoutmatrix ProductQ
93+
ArrayLayouts.@_layoutlmul ProductQ
94+
else # ArrayLayouts.@layoutmatrix ProductQ without ArrayLayouts.@layoutgetindex
95+
ArrayLayouts.@layoutldiv ProductQ
96+
ArrayLayouts.@layoutmul ProductQ
97+
ArrayLayouts.@layoutlmul ProductQ
98+
ArrayLayouts.@layoutfactorizations ProductQ
99+
ArrayLayouts.@_layoutlmul ProductQ
100+
end
93101

94-
ProductQ(Qs::AbstractMatrix...) = ProductQ{mapreduce(eltype, promote_type, Qs),typeof(Qs)}(Qs)
102+
ProductQ(Qs::Union{AbstractMatrix,AbstractQ}...) = ProductQ{mapreduce(eltype, promote_type, Qs),typeof(Qs)}(Qs)
95103

96104
adjoint(Q::ProductQ) = ProductQ(reverse(map(adjoint, Q.Qs))...)
97105

@@ -105,14 +113,21 @@ function lmul!(Q::ProductQ, v::AbstractVecOrMat)
105113
v
106114
end
107115

108-
# Avoid ambiguities
109-
getindex(Q::ProductQ, i::Int, j::Int) = Q[:, j][i]
116+
if VERSION < v"1.8-"
117+
# Avoid ambiguities
118+
getindex(Q::ProductQ, i::Int, j::Int) = Q[:, j][i]
110119

111-
function getindex(Q::ProductQ, ::Colon, j::Int)
112-
y = zeros(eltype(Q), size(Q, 2))
113-
y[j] = 1
114-
lmul!(Q, y)
120+
function getindex(Q::ProductQ, ::Colon, j::Int)
121+
y = zeros(eltype(Q), size(Q, 2))
122+
y[j] = 1
123+
lmul!(Q, y)
124+
end
115125
end
126+
if VERSION >= v"1.10-"
127+
getindex(Q::ProductQ, I::AbstractVector{Int}, J::AbstractVector{Int}) =
128+
hcat((Q[:,j][I] for j in J)...)
129+
end
130+
116131
getindex(Q::ProductQ{<:Any,<:Tuple{Vararg{LowerHessenbergQ}}}, i::Int, j::Int) = (Q')[j, i]'
117132

118133
function _productq_mul(A::ProductQ{T}, x::AbstractVector{S}) where {T,S}

src/blockbanded/blockbanded.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const OneToInfCumsum = InfiniteArrays.RangeCumsum{Int,OneToInf{Int}}
1+
const OneToInfCumsum = RangeCumsum{Int,OneToInf{Int}}
22

33
BlockArrays.sortedunion(::AbstractVector{<:PosInfinity}, ::AbstractVector{<:PosInfinity}) = [∞]
44
function BlockArrays.sortedunion(::AbstractVector{<:PosInfinity}, b)

src/infql.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ end
145145
function materialize!(M::Lmul{<:AdjQLPackedQLayout{<:BandedColumns},<:PaddedLayout})
146146
adjA,B = M.A,M.B
147147
require_one_based_indexing(B)
148-
A = adjA.parent
148+
A = parent(adjA)
149149
mA, nA = size(A.factors)
150150
mB, nB = size(B,1), size(B,2)
151151
if mA != mB
@@ -179,9 +179,9 @@ function _lmul_cache(A::AbstractMatrix{T}, x::AbstractVector{S}) where {T,S}
179179
end
180180

181181
(*)(A::QLPackedQ{T,<:InfBandedMatrix}, x::AbstractVector) where {T} = _lmul_cache(A, x)
182-
(*)(A::Adjoint{T,<:QLPackedQ{T,<:InfBandedMatrix}}, x::AbstractVector) where {T} = _lmul_cache(A, x)
182+
(*)(A::AdjointQtype{T,<:QLPackedQ{T,<:InfBandedMatrix}}, x::AbstractVector) where {T} = _lmul_cache(A, x)
183183
(*)(A::QLPackedQ{T,<:InfBandedMatrix}, x::LazyVector) where {T} = _lmul_cache(A, x)
184-
(*)(A::Adjoint{T,<:QLPackedQ{T,<:InfBandedMatrix}}, x::LazyVector) where {T} = _lmul_cache(A, x)
184+
(*)(A::AdjointQtype{T,<:QLPackedQ{T,<:InfBandedMatrix}}, x::LazyVector) where {T} = _lmul_cache(A, x)
185185

186186

187187
function blocktailiterate(c,a,b, d=c, e=a)
@@ -230,9 +230,9 @@ ql(A::Adjoint{T,BlockTriPertToeplitz{T}}) where T = ql(BlockTridiagonal(A))
230230

231231
const InfBlockBandedMatrix{T} = BlockSkylineMatrix{T,<:Vcat{T,1,<:Tuple{Vector{T},<:BlockArray{T,1,<:Fill{<:Any,1,Tuple{OneToInf{Int64}}}}}}}
232232

233-
function lmul!(adjA::Adjoint{<:Any,<:QLPackedQ{<:Any,<:InfBlockBandedMatrix}}, B::AbstractVector)
233+
function lmul!(adjA::AdjointQtype{<:Any,<:QLPackedQ{<:Any,<:InfBlockBandedMatrix}}, B::AbstractVector)
234234
require_one_based_indexing(B)
235-
A = adjA.parent
235+
A = parent(adjA)
236236
mA, nA = size(A.factors)
237237
mB, nB = size(B,1), size(B,2)
238238
if mA != mB
@@ -270,7 +270,7 @@ function (*)(A::QLPackedQ{T,<:InfBlockBandedMatrix}, x::AbstractVector{S}) where
270270
lmul!(A, cache(convert(AbstractVector{TS},x)))
271271
end
272272

273-
function (*)(A::Adjoint{T,<:QLPackedQ{T,<:InfBlockBandedMatrix}}, x::AbstractVector{S}) where {T,S}
273+
function (*)(A::AdjointQtype{T,<:QLPackedQ{T,<:InfBlockBandedMatrix}}, x::AbstractVector{S}) where {T,S}
274274
TS = promote_op(matprod, T, S)
275275
lmul!(A, cache(convert(AbstractVector{TS},x)))
276276
end
@@ -308,7 +308,7 @@ _data_tail(::CachedLayout, a) = cacheddata(a), getindex_value(a.array)
308308
function _data_tail(::ApplyLayout{typeof(vcat)}, a)
309309
args = arguments(vcat, a)
310310
dat,tl = _data_tail(last(args))
311-
vcat(most(args)..., dat), tl
311+
vcat(Base.front(args)..., dat), tl
312312
end
313313
_data_tail(a) = _data_tail(MemoryLayout(a), a)
314314

src/infqr.jl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,13 @@ _factorize(::AbstractBandedLayout, ::NTuple{2,OneToInf{Int}}, A) = qr(A)
158158
partialqr!(F::QR, n) = partialqr!(F.factors, n)
159159
partialqr!(F::AdaptiveQRFactors, n) = partialqr!(F.data, n)
160160

161+
#########
162+
# getindex
163+
#########
164+
165+
getindex(Q::QRPackedQ{<:Any,<:AdaptiveQRFactors,<:AdaptiveQRTau}, I::AbstractVector{Int}, J::AbstractVector{Int64}) =
166+
hcat((Q[:,j][I] for j in J)...)
167+
161168
#########
162169
# lmul!
163170
#########
@@ -210,7 +217,7 @@ function materialize!(M::MatLmulVec{<:AdjQRPackedQLayout{<:AdaptiveLayout},<:Pad
210217
COLGROWTH = 1000 # rate to grow columns
211218

212219
require_one_based_indexing(B)
213-
A = adjA.parent
220+
A = parent(adjA)
214221
mA, nA = size(A.factors)
215222
mB = length(B)
216223
if mA != mB
@@ -274,7 +281,7 @@ end
274281

275282
function materialize!(M::MatLmulVec{<:AdjQRPackedQLayout{<:AdaptiveLayout{<:AbstractBlockBandedLayout}},<:PaddedLayout}; tolerance=1E-30)
276283
adjA,B_in = M.A,M.B
277-
A = adjA.parent
284+
A = parent(adjA)
278285
T = eltype(M)
279286
COLGROWTH = 300 # rate to grow columns
280287
ax1,ax2 = axes(A.factors.data.data)
@@ -309,15 +316,15 @@ function materialize!(M::MatLmulVec{<:AdjQRPackedQLayout{<:AdaptiveLayout{<:Abst
309316
end
310317

311318

312-
function _lmul_copymutable(A::AbstractMatrix{T}, x::AbstractVector{S}; kwds...) where {T,S}
319+
function _lmul_copymutable(A::Union{AbstractMatrix{T},AbstractQ{T}}, x::AbstractVector{S}; kwds...) where {T,S}
313320
TS = promote_op(matprod, T, S)
314321
lmul!(A, Base.copymutable(convert(AbstractVector{TS},x)); kwds...)
315322
end
316323

317324
(*)(A::QRPackedQ{T,<:AdaptiveQRFactors}, x::AbstractVector; kwds...) where {T} = _lmul_copymutable(A, x; kwds...)
318-
(*)(A::Adjoint{T,<:QRPackedQ{T,<:AdaptiveQRFactors}}, x::AbstractVector; kwds...) where {T} = _lmul_copymutable(A, x; kwds...)
325+
(*)(A::AdjointQtype{T,<:QRPackedQ{T,<:AdaptiveQRFactors}}, x::AbstractVector; kwds...) where {T} = _lmul_copymutable(A, x; kwds...)
319326
(*)(A::QRPackedQ{T,<:AdaptiveQRFactors}, x::LayoutVector; kwds...) where {T} = _lmul_copymutable(A, x; kwds...)
320-
(*)(A::Adjoint{T,<:QRPackedQ{T,<:AdaptiveQRFactors}}, x::LayoutVector; kwds...) where {T} = _lmul_copymutable(A, x; kwds...)
327+
(*)(A::AdjointQtype{T,<:QRPackedQ{T,<:AdaptiveQRFactors}}, x::LayoutVector; kwds...) where {T} = _lmul_copymutable(A, x; kwds...)
321328

322329
function ldiv!(R::UpperTriangular{<:Any,<:AdaptiveQRFactors}, B::CachedVector{<:Any,<:Any,<:Zeros{<:Any,1}})
323330
n = B.datasize[1]

test/runtests.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ include("test_infbanded.jl")
150150
N = 1000
151151
v = view(n, Block.(Base.OneTo(N)))
152152
@test view(v, Block(2)) Fill(2, 2)
153-
@test axes(v) isa Tuple{BlockedUnitRange{InfiniteArrays.RangeCumsum{Int64,Base.OneTo{Int64}}}}
153+
@test axes(v) isa Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64,Base.OneTo{Int64}}}}
154154
@test @allocated(axes(v)) 40
155155

156156
dest = PseudoBlockArray{Float64}(undef, axes(v))
@@ -159,7 +159,7 @@ include("test_infbanded.jl")
159159

160160
v = view(k, Block.(Base.OneTo(N)))
161161
@test view(v, Block(2)) Base.OneTo(2)
162-
@test axes(v) isa Tuple{BlockedUnitRange{InfiniteArrays.RangeCumsum{Int64,Base.OneTo{Int64}}}}
162+
@test axes(v) isa Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64,Base.OneTo{Int64}}}}
163163
@test @allocated(axes(v)) 40
164164
@test copyto!(dest, v) == v
165165

@@ -173,7 +173,7 @@ include("test_infbanded.jl")
173173
@test v[Block(1)] == 1:2
174174
@test v[Block(1)] k[Block(2)] Base.OneTo(2)
175175

176-
@test axes(n, 1) isa BlockedUnitRange{InfiniteArrays.RangeCumsum{Int64,OneToInf{Int64}}}
176+
@test axes(n, 1) isa BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64,OneToInf{Int64}}}
177177
end
178178

179179
@testset "BlockHcat copyto!" begin

0 commit comments

Comments
 (0)