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