Skip to content

Commit 481220f

Browse files
authored
add center/centered helpers (#242)
1 parent b189da0 commit 481220f

File tree

3 files changed

+132
-0
lines changed

3 files changed

+132
-0
lines changed

docs/src/index.md

+14
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,20 @@ OffsetArray(A, OffsetArrays.Origin(-1, -1))
6363
OffsetArray(OA, OffsetArrays.Origin(-1, -1))
6464
```
6565

66+
Sometimes, it will be convenient to shift the center coordinate of the given array to `(0, 0, ...)`,
67+
`OffsetArrays.centered` is a helper for this very purpose:
68+
69+
```@repl index
70+
Ao = OffsetArrays.centered(A)
71+
Ao[0, 0] == 8.0
72+
```
73+
74+
and `OffsetArrays.center` tells you the center coordinate of given array:
75+
76+
```@repl index
77+
c = OffsetArrays.center(A)
78+
A[c...] == 8.0
79+
```
6680

6781
## Example: Relativistic Notation
6882

src/OffsetArrays.jl

+69
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,75 @@ _no_offset_view(::Tuple{<:Base.OneTo,Vararg{<:Base.OneTo}}, A::AbstractUnitRange
626626
_no_offset_view(::Any, A::AbstractArray) = OffsetArray(A, Origin(1))
627627
_no_offset_view(::Any, A::AbstractUnitRange) = UnitRange(A)
628628

629+
#####
630+
# center/centered
631+
# These two helpers are deliberately not exported; their meaning can be very different in
632+
# other scenarios and will be very likely to cause name conflicts if exported.
633+
#####
634+
"""
635+
center(A, [r::RoundingMode=RoundDown])::Dims
636+
637+
Return the center coordinate of given array `A`. If `size(A, k)` is even,
638+
a rounding procedure will be applied with mode `r`.
639+
640+
!!! compat "OffsetArrays 1.9"
641+
This method requires at least OffsetArrays 1.9.
642+
643+
# Examples
644+
645+
```jldoctest; setup=:(using OffsetArrays)
646+
A = reshape(collect(1:9), 3, 3)
647+
c = OffsetArrays.center(A) # (2, 2)
648+
A[c...] == 5 # true
649+
650+
Ao = OffsetArray(A, -2, -2)
651+
c = OffsetArrays.center(Ao) # (0, 0)
652+
Ao[c...] == 5 # true
653+
654+
# output
655+
true
656+
```
657+
658+
To shift the center coordinate of the given array to `(0, 0, ...)`, you
659+
can use [`centered`](@ref OffsetArrays.centered).
660+
"""
661+
function center(A::AbstractArray, r::RoundingMode=RoundDown)
662+
map(axes(A)) do inds
663+
round(Int, (length(inds)-1)/2, r) + first(inds)
664+
end
665+
end
666+
667+
"""
668+
centered(A, r::RoundingMode=RoundDown) -> Ao
669+
670+
Shift the center coordinate of array `A` to `(0, 0, ...)`. If `size(A, k)`
671+
is even, a rounding procedure will be applied with mode `r`.
672+
673+
!!! compat "OffsetArrays 1.9"
674+
This method requires at least OffsetArrays 1.9.
675+
676+
# Examples
677+
678+
```jldoctest; setup=:(using OffsetArrays)
679+
A = reshape(collect(1:9), 3, 3)
680+
Ao = OffsetArrays.centered(A)
681+
Ao[0, 0] == 5 # true
682+
683+
A = reshape(collect(1:9), 3, 3)
684+
Ao = OffsetArray(A, OffsetArrays.Origin(0))
685+
Aoo = OffsetArrays.centered(Ao)
686+
Aoo[0, 0] == 5 # true
687+
688+
# output
689+
true
690+
```
691+
692+
To query the center coordinate of the given array, you can
693+
instead use [`center`](@ref OffsetArrays.center).
694+
"""
695+
centered(A::AbstractArray, r::RoundingMode=RoundDown) = OffsetArray(A, .-center(A, r))
696+
697+
629698
####
630699
# work around for segfault in searchsorted*
631700
# https://github.com/JuliaLang/julia/issues/33977

test/runtests.jl

+49
Original file line numberDiff line numberDiff line change
@@ -2408,4 +2408,53 @@ end
24082408
@test_throws MethodError convert(OffsetArray{Float64, 3, Array{Float64,3}}, A)
24092409
end
24102410

2411+
@testset "center/centered" begin
2412+
@testset "center" begin
2413+
A = reshape(collect(1:9), 3, 3)
2414+
c = OffsetArrays.center(A)
2415+
@test c == (2, 2)
2416+
@test A[c...] == 5
2417+
@test OffsetArrays.center(A, RoundDown) == OffsetArrays.center(A, RoundUp)
2418+
2419+
A = reshape(collect(1:6), 2, 3)
2420+
c = OffsetArrays.center(A)
2421+
@test OffsetArrays.center(A, RoundDown) == c
2422+
@test c == (1, 2)
2423+
@test A[c...] == 3
2424+
c = OffsetArrays.center(A, RoundUp)
2425+
@test c == (2, 2)
2426+
@test A[c...] == 4
2427+
end
2428+
2429+
@testset "centered" begin
2430+
A = reshape(collect(1:9), 3, 3)
2431+
Ao = OffsetArrays.centered(A)
2432+
@test typeof(Ao) <: OffsetArray
2433+
@test parent(Ao) === A
2434+
@test Ao.offsets == (-2, -2)
2435+
@test Ao[0, 0] == 5
2436+
@test OffsetArrays.centered(A, RoundDown) == OffsetArrays.centered(A, RoundUp)
2437+
2438+
A = reshape(collect(1:6), 2, 3)
2439+
Ao = OffsetArrays.centered(A)
2440+
@test OffsetArrays.centered(A, RoundDown) == Ao
2441+
@test typeof(Ao) <: OffsetArray
2442+
@test parent(Ao) === A
2443+
@test Ao.offsets == (-1, -2)
2444+
@test Ao[0, 0] == 3
2445+
Ao = OffsetArrays.centered(A, RoundUp)
2446+
@test typeof(Ao) <: OffsetArray
2447+
@test parent(Ao) === A
2448+
@test Ao.offsets == (-2, -2)
2449+
@test Ao[0, 0] == 4
2450+
2451+
A = reshape(collect(1:9), 3, 3)
2452+
Ao = OffsetArray(A, -1, -1)
2453+
Aoo = OffsetArrays.centered(Ao)
2454+
@test parent(Aoo) === A # there will be only one OffsetArray wrapper
2455+
@test Aoo.offsets == (-2, -2)
2456+
@test Aoo[0, 0] == 5
2457+
end
2458+
end
2459+
24112460
include("origin.jl")

0 commit comments

Comments
 (0)