Skip to content

Commit c0d077d

Browse files
authored
Merge branch 'JuliaArrays:master' into mf/blocks_strided
2 parents 0a30416 + 974337d commit c0d077d

File tree

6 files changed

+164
-5
lines changed

6 files changed

+164
-5
lines changed

docs/src/lib/public.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Block
3232
BlockIndex
3333
blockaxes
3434
blockisequal
35+
blockequals
36+
blockisapprox
3537
blocksize
3638
blockfirsts
3739
blocklasts

src/BlockArrays.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ using LinearAlgebra, ArrayLayouts, FillArrays
55
export AbstractBlockArray, AbstractBlockMatrix, AbstractBlockVector, AbstractBlockVecOrMat
66
export Block, getblock, getblock!, setblock!, eachblock, blocks
77
export blockaxes, blocksize, blocklength, blockcheckbounds, BlockBoundsError, BlockIndex, BlockIndexRange
8-
export blocksizes, blocklengths, eachblockaxes, blocklasts, blockfirsts, blockisequal
8+
export blocksizes, blocklengths, blocklasts, blockfirsts, blockisequal, blockequals, blockisapprox
9+
export eachblockaxes
910
export BlockRange, blockedrange, BlockedUnitRange, BlockedOneTo
1011

1112
export BlockArray, BlockMatrix, BlockVector, BlockVecOrMat, mortar

src/blockaxis.jl

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,12 @@ end
225225
length(a::AbstractBlockedUnitRange) = isempty(blocklasts(a)) ? zero(eltype(a)) : Integer(last(blocklasts(a))-first(a)+oneunit(eltype(a)))
226226

227227
"""
228+
blockisequal(a::AbstractArray, b::AbstractArray)
228229
blockisequal(a::AbstractUnitRange{<:Integer}, b::AbstractUnitRange{<:Integer})
229230
230-
Check if `a` and `b` have the same block structure.
231+
Check if `a` and `b` have the same values (compared with `isequal`) and block structure.
232+
233+
See also blockequals and blockisapprox.
231234
232235
# Examples
233236
```jldoctest
@@ -251,6 +254,29 @@ true
251254
252255
julia> blockisequal(b1, b2)
253256
false
257+
258+
julia> A = reshape([1:6;], 2, 3)
259+
2×3 Matrix{Int64}:
260+
1 3 5
261+
2 4 6
262+
263+
julia> B1 = BlockedMatrix(A, [1,1], [1,2])
264+
2×2-blocked 2×3 BlockedMatrix{Int64}:
265+
1 │ 3 5
266+
───┼──────
267+
2 │ 4 6
268+
269+
julia> B2 = BlockedMatrix(A, [1,1], [2,1])
270+
2×2-blocked 2×3 BlockedMatrix{Int64}:
271+
1 3 │ 5
272+
──────┼───
273+
2 4 │ 6
274+
275+
julia> blockisequal(B1, B1)
276+
true
277+
278+
julia> blockisequal(B1, B2)
279+
false
254280
```
255281
"""
256282
blockisequal(a::AbstractUnitRange{<:Integer}, b::AbstractUnitRange{<:Integer}) = first(a) == first(b) && blocklasts(a) == blocklasts(b)
@@ -265,6 +291,92 @@ blockisequal(::Tuple{}, ::Tuple{}) = true
265291
blockisequal(::Tuple, ::Tuple{}) = false
266292
blockisequal(::Tuple{}, ::Tuple) = false
267293

294+
blockisequal(a::AbstractArray, b::AbstractArray) =
295+
blockisequal(axes(a), axes(b)) && isequal(a, b)
296+
297+
"""
298+
blockequals(a::AbstractArray, b::AbstractArray)
299+
300+
Check if `a` and `b` have the same values (compared with `==`) and block structure.
301+
302+
See also blockisequal and blockisapprox.
303+
304+
# Examples
305+
```jldoctest
306+
julia> A = reshape([1:6;], 2, 3)
307+
2×3 Matrix{Int64}:
308+
1 3 5
309+
2 4 6
310+
311+
julia> B1 = BlockedMatrix(A, [1,1], [1,2])
312+
2×2-blocked 2×3 BlockedMatrix{Int64}:
313+
1 │ 3 5
314+
───┼──────
315+
2 │ 4 6
316+
317+
julia> B2 = BlockedMatrix(A, [1,1], [2,1])
318+
2×2-blocked 2×3 BlockedMatrix{Int64}:
319+
1 3 │ 5
320+
──────┼───
321+
2 4 │ 6
322+
323+
julia> blockequals(B1, B1)
324+
true
325+
326+
julia> blockequals(B1, B2)
327+
false
328+
```
329+
"""
330+
blockequals(a::AbstractArray, b::AbstractArray) =
331+
blockisequal(axes(a), axes(b)) && (a == b)
332+
333+
"""
334+
blockisapprox(a::AbstractArray, b::AbstractArray; kwargs...)
335+
336+
Check if `a` and `b` have the same block structure and approximately the same
337+
values, compared with `isapprox`. Accepts the same keyword arguments as `isapprox`.
338+
339+
See also blockisequal and blockequals.
340+
341+
# Examples
342+
```jldoctest
343+
julia> A1 = reshape([1:6;], 2, 3)
344+
2×3 Matrix{Int64}:
345+
1 3 5
346+
2 4 6
347+
348+
julia> A2 = A1 .+ 1e-5
349+
2×3 Matrix{Float64}:
350+
1.00001 3.00001 5.00001
351+
2.00001 4.00001 6.00001
352+
353+
julia> B1 = BlockedMatrix(A1, [1,1], [1,2])
354+
2×2-blocked 2×3 BlockedMatrix{Int64}:
355+
1 │ 3 5
356+
───┼──────
357+
2 │ 4 6
358+
359+
julia> B2 = BlockedMatrix(A2, [1,1], [1,2])
360+
2×2-blocked 2×3 BlockedMatrix{Float64}:
361+
1.00001 │ 3.00001 5.00001
362+
─────────┼──────────────────
363+
2.00001 │ 4.00001 6.00001
364+
365+
julia> B3 = BlockedMatrix(A2, [1,1], [2,1])
366+
2×2-blocked 2×3 BlockedMatrix{Float64}:
367+
1.00001 3.00001 │ 5.00001
368+
──────────────────┼─────────
369+
2.00001 4.00001 │ 6.00001
370+
371+
julia> blockisapprox(B1, B2; atol=1e-4)
372+
true
373+
374+
julia> blockisapprox(B1, B3; atol=1e-4)
375+
false
376+
```
377+
"""
378+
blockisapprox(a::AbstractArray, b::AbstractArray; kwargs...) =
379+
blockisequal(axes(a), axes(b)) && isapprox(a, b; kwargs...)
268380

269381
_shift_blocklengths(::AbstractBlockedUnitRange, bl, f) = bl
270382
_shift_blocklengths(::Any, bl, f) = bl .+ (f - 1)

src/views.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ collect(I::BlockedLogicalIndex) = collect(I.blocks)
111111
checkbounds(::Type{Bool}, A::AbstractArray, i::BlockedLogicalIndex) = checkbounds(Bool, A, i.blocks.mask)
112112
# `checkbounds_indices` has been handled via `I::AbstractArray` fallback
113113
checkindex(::Type{Bool}, inds::AbstractUnitRange, i::BlockedLogicalIndex) = checkindex(Bool, inds, i.blocks.mask)
114-
checkindex(::Type{Bool}, inds::Tuple, i::BlockedLogicalIndex) = checkindex(Bool, inds, i.blocks.mask)
115114

116115
# Instantiate the BlockedLogicalIndex when constructing a SubArray, similar to
117116
# `ensure_indexable(I::Tuple{LogicalIndex,Vararg{Any}})`:

test/test_blockindices.jl

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -937,15 +937,49 @@ end
937937
@test B[1,2] == 0
938938
end
939939

940-
@testset "blockisequal" begin
941-
B = BlockArray(rand(4,4), [1,3], [1,3])
940+
@testset "blockisequal, blockequals" begin
941+
A = rand(4,4)
942+
B = BlockArray(A, [1,3], [1,3])
943+
B2 = BlockArray(A, [1,3], [2,2])
944+
B3 = BlockArray(randn(4,4), [1,3], [1,3])
942945
v = BlockArray(rand(4), [1,3])
943946
axB = axes(B)
947+
axB2 = axes(B2)
944948
axv = axes(v)
945949
@test blockisequal(axB, axB)
950+
@test blockisequal(axB[1], axB[1])
951+
@test blockequals(axB[1], axB[1])
952+
@test !blockisequal(axB[2], axB2[2])
953+
@test !blockequals(axB[2], axB2[2])
954+
@test !blockisequal(axB2[2], axB[2])
955+
@test !blockequals(axB2[2], axB[2])
946956
@test blockisequal(axv, axv)
947957
@test !blockisequal(axB, axv)
948958
@test !blockisequal(axv, axB)
959+
960+
@test blockisequal(A, A)
961+
@test blockisequal(B, B)
962+
@test !blockisequal(B, A)
963+
@test !blockisequal(A, B)
964+
@test !blockisequal(B, B2)
965+
@test !blockisequal(B2, B)
966+
@test !blockisequal(B, B3)
967+
@test !blockisequal(B3, B)
968+
end
969+
970+
@testset "blockisapprox" begin
971+
A1 = reshape([1:16;], (4,4))
972+
A2 = A1 .+ 1e-10
973+
B1 = BlockArray(A1, [1,3], [1,3])
974+
B2 = BlockArray(A2, [1,3], [1,3])
975+
B12 = BlockArray(A1, [1,3], [2,2])
976+
@test !blockisapprox(A1, A2; rtol=0)
977+
@test blockisapprox(A1, A2; rtol=1e-9)
978+
@test !blockisapprox(A1, B1; rtol=1e-9)
979+
@test !blockisapprox(B1, B2; rtol=0)
980+
@test blockisapprox(B1, B2; rtol=1e-9)
981+
@test !blockisapprox(B1, B12; rtol=0)
982+
@test !blockisapprox(B1, B12; rtol=1e-9)
949983
end
950984

951985
@testset "BlockIndices" begin

test/test_blockviews.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,9 @@ bview(a, b) = Base.invoke(view, Tuple{AbstractArray,Any}, a, b)
360360
a = randn(6, 6)
361361
for mask in ([true, true, false, false, true, false], BitVector([true, true, false, false, true, false]))
362362
I = BlockedVector(mask, [3, 3])
363+
@test Base.to_index(I) == BlockedLogicalIndex(I)
364+
@test Base.to_index(I) == [1, 2, 5]
365+
@test Base.to_index(I) isa BlockedLogicalIndex
363366
@test to_indices(a, (I, I)) == to_indices(a, (mask, mask))
364367
@test to_indices(a, (I, I)) == (BlockedVector(LogicalIndex(mask), [2, 1]), BlockedVector(LogicalIndex(mask), [2, 1]))
365368
@test to_indices(a, (I, I)) isa Tuple{BlockedLogicalIndex{Int},BlockedLogicalIndex{Int}}
@@ -372,7 +375,15 @@ bview(a, b) = Base.invoke(view, Tuple{AbstractArray,Any}, a, b)
372375
@test parentindices(view(a, I, I)) == (BlockedVector([1, 2, 5], [2, 1]), BlockedVector([1, 2, 5], [2, 1]))
373376
@test parentindices(view(a, I, I)) isa Tuple{BlockedVector{Int,Vector{Int}},BlockedVector{Int,Vector{Int}}}
374377
@test blocklengths.(Base.axes1.(parentindices(view(a, I, I)))) == ([2, 1], [2, 1])
378+
@test sprint(show, BlockedLogicalIndex(I)) == "[1, 2, 5]"
375379
end
380+
bl = BlockedLogicalIndex(BlockedVector([true, true, false, false, true, false], [3, 3]))
381+
@test sprint(show, "text/plain", bl) ==
382+
"2-blocked 3-element BlockedVector{Int64, Base.LogicalIndex{Int64, BlockedVector{Bool, Vector{Bool}, Tuple{BlockedOneTo{Int64, Vector{Int64}}}}}, Tuple{BlockedOneTo{Int64, Vector{Int64}}}}:\n 1\n 2\n\n 5"
383+
@test checkbounds(Bool, randn(6), bl)
384+
@test !checkbounds(Bool, randn(5), bl)
385+
@test checkindex(Bool, 1:6, bl)
386+
@test !checkindex(Bool, 1:5, bl)
376387
end
377388
end
378389

0 commit comments

Comments
 (0)