27
27
end
28
28
29
29
30
+ # Need a generated function to promote edge types, because a simple
31
+ # promote_type(map(eltype, h.edges)...) isn't type stable (tested
32
+ # with Julia v0.5).
33
+ @generated function _promote_edge_types {N} (edges:: NTuple{N,AbstractVector} )
34
+ promote_type (map (eltype, edges. parameters)... )
35
+ end
36
+
37
+
30
38
# # nice-valued ranges for histograms
31
39
function histrange {T} (v:: AbstractArray{T} , n:: Integer , closed:: Symbol = :default_left )
32
40
closed = _check_closed_arg (closed,:histrange )
@@ -134,7 +142,7 @@ type Histogram{T<:Real,N,E} <: AbstractHistogram{T,N,E}
134
142
weights:: Array{T,N} , closed:: Symbol , isdensity:: Bool = false )
135
143
closed == :right || closed == :left || error (" closed must :left or :right" )
136
144
isdensity && ! (T <: AbstractFloat ) && error (" Density histogram must have float-type weights" )
137
- map (x -> length (x) - 1 , edges) == size (weights) || error (" Histogram edge vectors must be 1 longer than corresponding weight dimensions" )
145
+ _edges_nbins ( edges) == size (weights) || error (" Histogram edge vectors must be 1 longer than corresponding weight dimensions" )
138
146
new {T,N,E} (edges,weights,closed,isdensity)
139
147
end
140
148
end
@@ -143,7 +151,7 @@ Histogram{T,N}(edges::NTuple{N,AbstractVector},weights::AbstractArray{T,N},close
143
151
Histogram {T,N,typeof(edges)} (edges,weights,_check_closed_arg (closed,:Histogram ),isdensity)
144
152
145
153
Histogram {T,N} (edges:: NTuple{N,AbstractVector} ,:: Type{T} ,closed:: Symbol = :default_left , isdensity:: Bool = false ) =
146
- Histogram (edges,zeros (T,map (x -> length (x) - 1 , edges)... ),_check_closed_arg (closed,:Histogram ),isdensity)
154
+ Histogram (edges,zeros (T,_edges_nbins ( edges)... ),_check_closed_arg (closed,:Histogram ),isdensity)
147
155
148
156
Histogram {N} (edges:: NTuple{N,AbstractVector} ,closed:: Symbol = :default_left , isdensity:: Bool = false ) =
149
157
Histogram (edges,Int,_check_closed_arg (closed,:Histogram ),isdensity)
@@ -180,7 +188,7 @@ binvolume{T,E}(h::AbstractHistogram{T,1,E}, binidx::Integer) = binvolume(h, (bin
180
188
binvolume {V,T,E} (:: Type{V} , h:: AbstractHistogram{T,1,E} , binidx:: Integer ) = binvolume (V, h, (binidx,))
181
189
182
190
binvolume {T,N,E} (h:: Histogram{T,N,E} , binidx:: NTuple{N,Integer} ) =
183
- binvolume (promote_type ( map (eltype, h. edges) ... ), h, binidx)
191
+ binvolume (_promote_edge_types ( h. edges), h, binidx)
184
192
185
193
binvolume {V,T,N,E} (:: Type{V} , h:: Histogram{T,N,E} , binidx:: NTuple{N,Integer} ) =
186
194
prod (map ((edge, i) -> _edge_binvolume (V, edge, i), h. edges, binidx))
@@ -190,6 +198,11 @@ binvolume{V,T,N,E}(::Type{V}, h::Histogram{T,N,E}, binidx::NTuple{N,Integer}) =
190
198
@inline _edge_binvolume (edge:: AbstractVector , i:: Integer ) = _edge_binvolume (eltype (edge), edge, i)
191
199
192
200
201
+ @inline _edges_nbins {N} (edges:: NTuple{N,AbstractVector} ) = map (_edge_nbins, edges)
202
+
203
+ @inline _edge_nbins (edge:: AbstractVector ) = length (edge) - 1
204
+
205
+
193
206
# 1-dimensional
194
207
195
208
Histogram {T} (edge:: AbstractVector , weights:: AbstractVector{T} , closed:: Symbol = :default_left , isdensity:: Bool = false ) =
@@ -259,34 +272,48 @@ end
259
272
append! {T,N} (h:: AbstractHistogram{T,N} , vs:: NTuple{N,AbstractVector} , wv:: WeightVec ) = append! (h, vs, values (wv))
260
273
261
274
275
+ # Turn kwargs nbins into a type-stable tuple of integers:
276
+ function _nbins_tuple {N} (vs:: NTuple{N,AbstractVector} , nbins)
277
+ template = map (length, vs)
278
+
279
+ @static if VERSION < v " 0.6.0-dev.695"
280
+ result = if isa (nbins, Integer)
281
+ map (t -> typeof (t)(nbins), template)
282
+ elseif isa (nbins, NTuple{N, Integer})
283
+ map ((t, x) -> typeof (t)(x), template, nbins)
284
+ else
285
+ throw (ArgumentError (" nbins must be an Integer or NTuple{N, Integer}" ))
286
+ end
287
+ else
288
+ result = broadcast ((t, x) -> typeof (t)(x), template, nbins)
289
+ end
290
+
291
+ result:: typeof (template)
292
+ end
293
+
262
294
fit {T,N} (:: Type{Histogram{T}} , vs:: NTuple{N,AbstractVector} , edges:: NTuple{N,AbstractVector} ; closed:: Symbol = :default_left ) =
263
295
append! (Histogram (edges, T, _check_closed_arg (closed,:fit ), false ), vs)
264
296
265
- fit {T,N} (:: Type{Histogram{T}} , vs:: NTuple{N,AbstractVector} ; closed:: Symbol = :default_left , isdensity :: Bool = false , nbins= sturges (length (vs[1 ]))) = begin
297
+ fit {T,N} (:: Type{Histogram{T}} , vs:: NTuple{N,AbstractVector} ; closed:: Symbol = :default_left , nbins= sturges (length (vs[1 ]))) = begin
266
298
closed = _check_closed_arg (closed,:fit )
267
- fit (Histogram{T}, vs, histrange (vs,nbins,closed); closed= closed)
299
+ fit (Histogram{T}, vs, histrange (vs,_nbins_tuple (vs, nbins) ,closed); closed= closed)
268
300
end
269
301
270
302
fit {T,N,W} (:: Type{Histogram{T}} , vs:: NTuple{N,AbstractVector} , wv:: WeightVec{W} , edges:: NTuple{N,AbstractVector} ; closed:: Symbol = :default_left ) =
271
303
append! (Histogram (edges, T, _check_closed_arg (closed,:fit ), false ), vs, wv)
272
304
273
- fit {T,N} (:: Type{Histogram{T}} , vs:: NTuple{N,AbstractVector} , wv:: WeightVec ; closed:: Symbol = :default_left , isdensity :: Bool = false , nbins= sturges (length (vs[1 ]))) = begin
305
+ fit {T,N} (:: Type{Histogram{T}} , vs:: NTuple{N,AbstractVector} , wv:: WeightVec ; closed:: Symbol = :default_left , nbins= sturges (length (vs[1 ]))) = begin
274
306
closed = _check_closed_arg (closed,:fit )
275
- fit (Histogram{T}, vs, wv, histrange (vs,nbins,closed); closed= closed)
307
+ fit (Histogram{T}, vs, wv, histrange (vs,_nbins_tuple (vs, nbins) ,closed); closed= closed)
276
308
end
277
309
278
310
fit (:: Type{Histogram} , args... ; kwargs... ) = fit (Histogram{Int}, args... ; kwargs... )
279
311
fit {N,W} (:: Type{Histogram} , vs:: NTuple{N,AbstractVector} , wv:: WeightVec{W} , args... ; kwargs... ) = fit (Histogram{W}, vs, wv, args... ; kwargs... )
280
312
281
313
282
314
# Get a suitable high-precision type for the norm of a histogram.
283
- @generated function norm_type {T, N, E} (h:: Histogram{T, N, E} )
284
- args = [:( eltype (edges[$ d]) ) for d = 1 : N]
285
- quote
286
- edges = h. edges
287
- norm_type (promote_type (T, $ (args... )))
288
- end
289
- end
315
+ norm_type {T, N, E} (h:: Histogram{T, N, E} ) =
316
+ promote_type (T, _promote_edge_types (h. edges))
290
317
291
318
norm_type {T<:Integer} (:: Type{T} ) = promote_type (T, Int64)
292
319
norm_type {T<:AbstractFloat} (:: Type{T} ) = promote_type (T, Float64)
0 commit comments