Skip to content

Commit fdd9e41

Browse files
committed
added subcat functions
1 parent 699de33 commit fdd9e41

File tree

5 files changed

+382
-3
lines changed

5 files changed

+382
-3
lines changed

Project.toml

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
name = "ParallelUtilities"
22
uuid = "fad6cfc8-4f83-11e9-06cc-151124046ad0"
3-
authors = ["Jishnu Bhattacharya <jishnuonline@gmail.com>"]
4-
version = "0.7.5"
3+
authors = ["Jishnu Bhattacharya"]
4+
version = "0.7.6"
55

66
[deps]
77
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
88
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
9+
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
910
ProgressMeter = "92933f4c-e287-5a05-a399-4b506db050ca"
1011
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
1112

1213
[compat]
1314
DataStructures = "0.17, 0.18"
15+
OffsetArrays = "1"
1416
ProgressMeter = "1.2"
1517
Reexport = "0.2"
1618
julia = "1.2"

docs/make.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ makedocs(;
1414
assets=String[],
1515
),
1616
pages=[
17-
"Reference" => "index.md",
17+
"API" => "index.md",
1818
],
1919
)
2020

src/ParallelUtilities.jl

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module ParallelUtilities
22
using ProgressMeter
33
using DataStructures
44
using Reexport
5+
using OffsetArrays
56
@reexport using Distributed
67

78
export ProductSplit,
@@ -28,5 +29,6 @@ include("productsplit.jl")
2829
include("utils.jl")
2930
include("trees.jl")
3031
include("mapreduce.jl")
32+
include("reductionfunctions.jl")
3133

3234
end # module

src/reductionfunctions.jl

+200
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
throw_dimserror(dims::Integer, N) = throw(ArgumentError("dims = $dims does not satisfy 1 <= dims <= $N"))
2+
throw_dimserror(dims, N) = throw(ArgumentError("dims = $dims does not satisfy 1 <= dims <= $N for all elements"))
3+
4+
throw_axesmismatcherror(dim, axexp, axrcv) = throw(
5+
DimensionMismatch("axes mismatch in dimension $dim, expected $axexp but received $axrcv"))
6+
7+
function _checkdims(A, dim, ax_exp)
8+
for a in A
9+
axadim = axes(a, dim)
10+
if axadim != ax_exp
11+
throw_axesmismatcherror(dim, ax_exp, axadim)
12+
end
13+
end
14+
end
15+
16+
function checkdims(A, dims)
17+
for (dim, ax_exp) in enumerate(axes(first(A)))
18+
if dim dims
19+
_checkdims(A, dim, ax_exp)
20+
end
21+
end
22+
end
23+
24+
function checkdims(A, d::Integer)
25+
for (dim, ax_exp) in enumerate(axes(first(A)))
26+
dim == d && continue
27+
_checkdims(A, dim, ax_exp)
28+
end
29+
end
30+
31+
"""
32+
ParallelUtilities.sumcat_aligned(A::AbstractArray{T,N}...; dims) where {T,N}
33+
34+
Concatenate the arrays along the dimensions `dims` according to their axes,
35+
with overlapping sections being summed over. Returns an `OffsetArray` with the minimal
36+
axes span encompassing all the arrays.
37+
38+
`dims` may be an `Integer` or a collection of `Integer`s, but all elements of `dims` must be from the range `1:N`.
39+
40+
# Examples
41+
```jldoctest
42+
julia> ParallelUtilities.sumcat_aligned(ones(1:2), ones(4:5), dims=1)
43+
5-element OffsetArray(::Array{Float64,1}, 1:5) with eltype Float64 with indices 1:5:
44+
1.0
45+
1.0
46+
0.0
47+
1.0
48+
1.0
49+
50+
julia> ParallelUtilities.sumcat_aligned(ones(1:2, 1:2), ones(2:3, 2:3), dims=(1,2))
51+
3×3 OffsetArray(::Array{Float64,2}, 1:3, 1:3) with eltype Float64 with indices 1:3×1:3:
52+
1.0 1.0 0.0
53+
1.0 2.0 1.0
54+
0.0 1.0 1.0
55+
56+
julia> ParallelUtilities.sumcat_aligned(ones(1:2, 1:2), ones(3:4, 3:4), dims=(1,2))
57+
4×4 OffsetArray(::Array{Float64,2}, 1:4, 1:4) with eltype Float64 with indices 1:4×1:4:
58+
1.0 1.0 0.0 0.0
59+
1.0 1.0 0.0 0.0
60+
0.0 0.0 1.0 1.0
61+
0.0 0.0 1.0 1.0
62+
```
63+
64+
See also: [`sumhcat_aligned`](@ref), [`sumvcat_aligned`](@ref)
65+
"""
66+
function sumcat_aligned(A::AbstractArray{T,N}...; dims) where {T,N}
67+
68+
all(x -> 1 <= x <= N, dims) || throw_dimserror(dims, N)
69+
70+
checkdims(A, dims)
71+
72+
ax = Vector{UnitRange{Int}}(undef, N)
73+
ax .= axes(first(A))
74+
75+
for d in dims
76+
axmin = minimum(minimum.(axes.(A, d)))
77+
axmax = maximum(maximum.(axes.(A, d)))
78+
ax[d] = axmin:axmax
79+
end
80+
81+
arr = OffsetArray{T,N}(undef, ax...)
82+
fill!(arr, zero(T))
83+
84+
for a in A
85+
arr[axes(a)...] .+= a
86+
end
87+
arr
88+
end
89+
90+
sumcat_aligned(A1::AbstractArray; dims) = (all(x -> 1 <= x <= ndims(A1), dims) || throw_dimserror(dims); A1)
91+
92+
"""
93+
ParallelUtilities.sumvcat_aligned(A::AbstractArray{T,N}...) where {T,N}
94+
95+
Concatenate the arrays along the first dimension according to their axes,
96+
with overlapping sections being summed over. Returns an `OffsetArray` with the minimal
97+
axes span encompassing all the arrays.
98+
99+
The input arrays must be at least one-dimensional.
100+
101+
# Examples
102+
```jldoctest
103+
julia> ParallelUtilities.sumvcat_aligned(ones(1:2), ones(4:5))
104+
5-element OffsetArray(::Array{Float64,1}, 1:5) with eltype Float64 with indices 1:5:
105+
1.0
106+
1.0
107+
0.0
108+
1.0
109+
1.0
110+
111+
julia> ParallelUtilities.sumvcat_aligned(ones(1:2, 1:2), ones(2:3, 1:2))
112+
3×2 OffsetArray(::Array{Float64,2}, 1:3, 1:2) with eltype Float64 with indices 1:3×1:2:
113+
1.0 1.0
114+
2.0 2.0
115+
1.0 1.0
116+
```
117+
118+
See also: [`sumcat_aligned`](@ref), [`sumhcat_aligned`](@ref)
119+
"""
120+
function sumvcat_aligned(A::AbstractArray{T,N}...) where {T,N}
121+
122+
N >= 1 || throw(ArgumentError("all the arrays need to have at least 1 dimension"))
123+
checkdims(A, 1)
124+
125+
axmin = minimum(minimum.(axes.(A, 1)))
126+
axmax = maximum(maximum.(axes.(A, 1)))
127+
128+
axcat = axmin:axmax
129+
130+
trailing_axes = Base.tail(axes(first(A)))
131+
132+
arr = OffsetArray{T,N}(undef, axcat, trailing_axes...)
133+
fill!(arr, zero(T))
134+
135+
for axt in CartesianIndices(trailing_axes)
136+
for a in A, ind1 in axes(a,1)
137+
arr[ind1, axt] += a[ind1, axt]
138+
end
139+
end
140+
141+
arr
142+
end
143+
144+
function sumvcat_aligned(A::AbstractArray)
145+
ndims(A) >= 1 || throw(ArgumentError("the array needs to have at least 1 dimension"))
146+
A
147+
end
148+
149+
"""
150+
ParallelUtilities.sumhcat_aligned(A::AbstractArray{T,N}...) where {T,N}
151+
152+
Concatenate the arrays along the second dimension according to their axes,
153+
with overlapping sections being summed over. Returns an `OffsetArray` with the minimal
154+
axes span encompassing all the arrays.
155+
156+
The input arrays must be at least two-dimensional.
157+
158+
# Examples
159+
```jldoctest
160+
julia> ParallelUtilities.sumhcat_aligned(ones(2, 1:2), ones(2, 4:5))
161+
2×5 OffsetArray(::Array{Float64,2}, 1:2, 1:5) with eltype Float64 with indices 1:2×1:5:
162+
1.0 1.0 0.0 1.0 1.0
163+
1.0 1.0 0.0 1.0 1.0
164+
165+
julia> ParallelUtilities.sumhcat_aligned(ones(1:2, 1:2), ones(1:2, 2:3))
166+
2×3 OffsetArray(::Array{Float64,2}, 1:2, 1:3) with eltype Float64 with indices 1:2×1:3:
167+
1.0 2.0 1.0
168+
1.0 2.0 1.0
169+
```
170+
171+
See also: [`sumcat_aligned`](@ref), [`sumvcat_aligned`](@ref)
172+
"""
173+
function sumhcat_aligned(A::AbstractArray{T,N}...) where {T,N}
174+
175+
N >= 2 || throw(ArgumentError("all the arrays need to have at least 2 dimensions"))
176+
checkdims(A, 2)
177+
178+
axmin = minimum(minimum.(axes.(A, 2)))
179+
axmax = maximum(maximum.(axes.(A, 2)))
180+
181+
axcat = axmin:axmax
182+
183+
trailing_axes = Base.tail(Base.tail(axes(first(A))))
184+
185+
arr = OffsetArray{T,N}(undef, axes(first(A),1), axcat, trailing_axes...)
186+
fill!(arr, zero(T))
187+
188+
for axt in CartesianIndices(trailing_axes)
189+
for a in A, ind2 in axes(a,2), ind1 in axes(a,1)
190+
arr[ind1, ind2, axt] += a[ind1, ind2, axt]
191+
end
192+
end
193+
194+
arr
195+
end
196+
197+
function sumhcat_aligned(A::AbstractArray)
198+
ndims(A) >= 2 || throw(ArgumentError("the array needs to have at least 2 dimensions"))
199+
A
200+
end

0 commit comments

Comments
 (0)