Skip to content

Commit

Permalink
restrict: only return OffsetArray when input is an OffsetArray
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnychen94 committed May 22, 2021
1 parent eff14e9 commit cd9a89e
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 9 deletions.
2 changes: 2 additions & 0 deletions src/ImageUtils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ export restrict

using Base.Cartesian: @nloops
using ImageCore
using ImageCore.OffsetArrays

include("restrict.jl")
include("compat.jl")

end
5 changes: 5 additions & 0 deletions src/compat.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
if VERSION < v"1.2"
require_one_based_indexing(A...) = !Base.has_offset_axes(A...) || throw(ArgumentError("offset arrays are not supported but got an array with index other than 1"))
else
const require_one_based_indexing = Base.require_one_based_indexing
end
21 changes: 16 additions & 5 deletions src/restrict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,20 @@ function restrict(A::AbstractArray, region::Dims)
end

function restrict(A::AbstractArray{T,N}, dim::Integer) where {T,N}
require_one_based_indexing(A)

indsA = axes(A)
newinds = ntuple(i->i==dim ? restrict_indices(indsA[dim]) : indsA[i], Val(N))
out = Array{restrict_eltype(first(A)), N}(undef, last.(newinds))
restrict!(out, A, dim)
out
end
function restrict(A::OffsetArray{T,N}, dim::Integer) where {T,N}
indsA = axes(A)
newinds = map(UnitRange, ntuple(i->i==dim ? restrict_indices(indsA[dim]) : indsA[i], Val(N)))
out = similar(Array{restrict_eltype(first(A)), N}, newinds)
# This calls OffsetArrays implementation: a type piracy
# https://github.com/JuliaArrays/OffsetArrays.jl/issues/87
out = similar(A, restrict_eltype(first(A)), newinds)
restrict!(out, A, dim)
out
end
Expand Down Expand Up @@ -190,8 +201,8 @@ end
$(Expr(:meta, :noinline))
T = eltype(out)
if isodd(length(indA))
half = convert(eltype(T), 0.5)
quarter = convert(eltype(T), 0.25)
half = 0.5
quarter = 0.25
@inbounds @nloops $Npost ipost d->indspost[d] begin
iout, iA = first(indout), first(indA)
nxt = convert(T, A[iA+1, $(Ipost...)])
Expand All @@ -204,8 +215,8 @@ end
out[iout+1, $(Ipost...)] = quarter*nxt + half*convert(T, A[last(indA), $(Ipost...)])
end
else
threeeighths = convert(eltype(T), 0.375)
oneeighth = convert(eltype(T), 0.125)
threeeighths = 0.375
oneeighth = 0.125
z = zero(T)
@inbounds @nloops $Npost ipost d->indspost[d] begin
c = d = z
Expand Down
35 changes: 31 additions & 4 deletions test/restrict.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@
@testset "restrict" begin
@testset "restrict" begin
@testset "interfaces" begin
A = rand(N0f8, 4, 5, 3)

Ar = @inferred restrict(A, 1)
@test typeof(Ar) <: Array
@test size(Ar) == (3, 5, 3)

Ar = @inferred restrict(A, (1, ))
@test typeof(Ar) <: Array
@test size(Ar) == (3, 5, 3)

Ar = @inferred restrict(A, (1, 2, 3))
@test typeof(Ar) <: Array
@test size(Ar) == (3, 3, 2)
@test Ar == restrict(A)

@test_throws MethodError restrict(A, 1, 2, 3)
end

@testset "numerical test" begin
A = reshape([UInt16(i) for i = 1:60], 4, 5, 3)
B = restrict(A, (1,2))
Expand Down Expand Up @@ -36,9 +55,17 @@
@testset "OffsetArray" begin
A = rand(5, 4, 3)
Ao = OffsetArray(A, (-2,1,0))
@test parent(@inferred(restrict(Ao, 1))) == restrict(A, 1)
@test parent(@inferred(restrict(Ao, 2))) == restrict(A, 2)
@test parent(@inferred(restrict(Ao, (1,2)))) == restrict(A, (1,2))

for (dims, offsets) in [
(1, (-1, 1, 0)),
(2, (-2, 0, 0)),
((1, 2), (-1, 0, 0))
]
Ar = @inferred restrict(Ao, dims)
@test typeof(Ar) <: OffsetArray
@test Ar.offsets == offsets
@test parent(Ar) == restrict(A, dims)
end
end

@testset "FixedPoint overflow" begin
Expand Down

0 comments on commit cd9a89e

Please sign in to comment.