@@ -24,6 +24,13 @@ BlockMap{T}(maps::As, rows::Rs) where {T, As<:LinearMapTuple, Rs} =
2424
2525MulStyle (A:: BlockMap ) = MulStyle (A. maps... )
2626
27+ function _getranges (maps, dim, inds= ntuple (identity, Val (length (maps))))
28+ sizes = map (i -> size (maps[i], dim):: Int , inds)
29+ ends = cumsum (sizes)
30+ starts = (1 , (1 .+ Base. front (ends)). .. )
31+ return UnitRange .(starts, ends)
32+ end
33+
2734"""
2835 rowcolranges(maps, rows)
2936
@@ -32,24 +39,20 @@ map in `maps`, according to its position in a virtual matrix representation of t
3239block linear map obtained from `hvcat(rows, maps...)`.
3340"""
3441function rowcolranges (maps, rows)
35- rowranges = ntuple (n-> 1 : 0 , Val (length (rows)))
36- colranges = ntuple (n-> 1 : 0 , Val (length (maps)))
37- mapind = 0
38- rowstart = 1
39- for (i, row) in enumerate (rows)
40- mapind += 1
41- rowend = rowstart + Int (size (maps[mapind], 1 )):: Int - 1
42- rowranges = Base. setindex (rowranges, rowstart: rowend, i)
43- colstart = 1
44- colend = Int (size (maps[mapind], 2 )):: Int
45- colranges = Base. setindex (colranges, colstart: colend, mapind)
46- for colind in 2 : row
47- mapind += 1
48- colstart = colend + 1
49- colend += Int (size (maps[mapind], 2 )):: Int
50- colranges = Base. setindex (colranges, colstart: colend, mapind)
51- end
52- rowstart = rowend + 1
42+ # find indices of the row-wise first maps
43+ firstmapinds = cumsum ((1 , Base. front (rows)... ))
44+ # compute rowranges from first dimension of the row-wise first maps
45+ rowranges = _getranges (maps, 1 , firstmapinds)
46+
47+ # compute ranges from second dimension as if all in one row
48+ temp = _getranges (maps, 2 )
49+ # introduce "line breaks"
50+ colranges = ntuple (Val (length (maps))) do i
51+ # for each map find the index of the respective row-wise first map
52+ # something-trick just to assure the compiler that the index is an Int
53+ @inbounds firstmapind = firstmapinds[something (findlast (<= (i), firstmapinds), 1 )]
54+ # shift ranges by the first col-index of the row-wise first map
55+ return @inbounds temp[i] .- first (temp[firstmapind]) .+ 1
5356 end
5457 return rowranges, colranges
5558end
@@ -82,17 +85,13 @@ function Base.hcat(As::Union{LinearMap, UniformScaling, AbstractVecOrMat}...)
8285 T = promote_type (map (eltype, As)... )
8386 nbc = length (As)
8487
85- nrows = - 1
8688 # find first non-UniformScaling to detect number of rows
87- for A in As
88- if ! (A isa UniformScaling)
89- nrows = size (A, 1 )
90- break
91- end
92- end
93- @assert nrows != - 1
89+ j = findfirst (A -> ! isa (A, UniformScaling), As)
9490 # this should not happen, function should only be called with at least one LinearMap
95- return BlockMap {T} (promote_to_lmaps (ntuple (i-> nrows, nbc), 1 , 1 , As... ), (nbc,))
91+ @assert ! isnothing (j)
92+ @inbounds nrows = size (As[j], 1 ):: Int
93+
94+ return BlockMap {T} (promote_to_lmaps (ntuple (_ -> nrows, Val (nbc)), 1 , 1 , As... ), (nbc,))
9695end
9796
9897# ###########
@@ -124,18 +123,14 @@ function Base.vcat(As::Union{LinearMap,UniformScaling,AbstractVecOrMat}...)
124123 T = promote_type (map (eltype, As)... )
125124 nbr = length (As)
126125
127- ncols = - 1
128- # find first non-UniformScaling to detect number of columns
129- for A in As
130- if ! (A isa UniformScaling)
131- ncols = size (A, 2 )
132- break
133- end
134- end
135- @assert ncols != - 1
126+ # find first non-UniformScaling to detect number of rows
127+ j = findfirst (A -> ! isa (A, UniformScaling), As)
136128 # this should not happen, function should only be called with at least one LinearMap
137- rows = ntuple (i-> 1 , nbr)
138- return BlockMap {T} (promote_to_lmaps (ntuple (i-> ncols, nbr), 1 , 2 , As... ), rows)
129+ @assert ! isnothing (j)
130+ @inbounds ncols = size (As[j], 2 ):: Int
131+
132+ rows = ntuple (_ -> 1 , Val (nbr))
133+ return BlockMap {T} (promote_to_lmaps (ntuple (_ -> ncols, Val (nbr)), 1 , 2 , As... ), rows)
139134end
140135
141136# ###########
@@ -181,7 +176,7 @@ function Base.hvcat(rows::Tuple{Vararg{Int}},
181176 ni = - 1 # number of rows in this block-row, -1 indicates unknown
182177 for k in 1 : rows[i]
183178 if ! isa (As[j+ k], UniformScaling)
184- na = size (As[j+ k], 1 )
179+ na = size (As[j+ k], 1 ):: Int
185180 ni >= 0 && ni != na &&
186181 throw (DimensionMismatch (" mismatch in number of rows" ))
187182 ni = na
@@ -199,7 +194,7 @@ function Base.hvcat(rows::Tuple{Vararg{Int}},
199194 nci = 0
200195 rows[i] > 0 && n[j+ 1 ] == - 1 && (j += rows[i]; continue )
201196 for k = 1 : rows[i]
202- nci += isa (As[j+ k], UniformScaling) ? n[j+ k] : size (As[j+ k], 2 )
197+ nci += isa (As[j+ k], UniformScaling) ? n[j+ k] : size (As[j+ k], 2 ):: Int
203198 end
204199 nc >= 0 && nc != nci && throw (DimensionMismatch (" mismatch in number of columns" ))
205200 nc = nci
@@ -412,14 +407,8 @@ struct BlockDiagonalMap{T,
412407 promote_type (T, TA) == T ||
413408 error (" eltype $TA cannot be promoted to $T in BlockDiagonalMap constructor" )
414409 end
415- # row ranges
416- inds = vcat (1 , size .(maps, 1 )... )
417- cumsum! (inds, inds)
418- rowranges = ntuple (i -> inds[i]: inds[i+ 1 ]- 1 , Val (length (maps)))
419- # column ranges
420- inds[2 : end ] .= size .(maps, 2 )
421- cumsum! (inds, inds)
422- colranges = ntuple (i -> inds[i]: inds[i+ 1 ]- 1 , Val (length (maps)))
410+ rowranges = _getranges (maps, 1 )
411+ colranges = _getranges (maps, 2 )
423412 return new {T, As, typeof(rowranges)} (maps, rowranges, colranges)
424413 end
425414end
@@ -476,7 +465,7 @@ object among the first 8 arguments.
476465"""
477466Base. cat
478467
479- Base. size (A:: BlockDiagonalMap ) = (last (A. rowranges[ end ]) , last (A. colranges[ end ] ))
468+ Base. size (A:: BlockDiagonalMap ) = (last (last ( A. rowranges)) , last (last ( A. colranges) ))
480469
481470MulStyle (A:: BlockDiagonalMap ) = MulStyle (A. maps... )
482471
0 commit comments