2727end
2828
2929
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+
3038# # nice-valued ranges for histograms
3139function histrange {T} (v:: AbstractArray{T} , n:: Integer , closed:: Symbol = :default_left )
3240 closed = _check_closed_arg (closed,:histrange )
@@ -134,7 +142,7 @@ type Histogram{T<:Real,N,E} <: AbstractHistogram{T,N,E}
134142 weights:: Array{T,N} , closed:: Symbol , isdensity:: Bool = false )
135143 closed == :right || closed == :left || error (" closed must :left or :right" )
136144 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" )
138146 new {T,N,E} (edges,weights,closed,isdensity)
139147 end
140148end
@@ -143,7 +151,7 @@ Histogram{T,N}(edges::NTuple{N,AbstractVector},weights::AbstractArray{T,N},close
143151 Histogram {T,N,typeof(edges)} (edges,weights,_check_closed_arg (closed,:Histogram ),isdensity)
144152
145153Histogram {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)
147155
148156Histogram {N} (edges:: NTuple{N,AbstractVector} ,closed:: Symbol = :default_left , isdensity:: Bool = false ) =
149157 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
180188binvolume {V,T,E} (:: Type{V} , h:: AbstractHistogram{T,1,E} , binidx:: Integer ) = binvolume (V, h, (binidx,))
181189
182190binvolume {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)
184192
185193binvolume {V,T,N,E} (:: Type{V} , h:: Histogram{T,N,E} , binidx:: NTuple{N,Integer} ) =
186194 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}) =
190198@inline _edge_binvolume (edge:: AbstractVector , i:: Integer ) = _edge_binvolume (eltype (edge), edge, i)
191199
192200
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+
193206# 1-dimensional
194207
195208Histogram {T} (edge:: AbstractVector , weights:: AbstractVector{T} , closed:: Symbol = :default_left , isdensity:: Bool = false ) =
@@ -259,34 +272,48 @@ end
259272append! {T,N} (h:: AbstractHistogram{T,N} , vs:: NTuple{N,AbstractVector} , wv:: WeightVec ) = append! (h, vs, values (wv))
260273
261274
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+
262294fit {T,N} (:: Type{Histogram{T}} , vs:: NTuple{N,AbstractVector} , edges:: NTuple{N,AbstractVector} ; closed:: Symbol = :default_left ) =
263295 append! (Histogram (edges, T, _check_closed_arg (closed,:fit ), false ), vs)
264296
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
266298 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)
268300end
269301
270302fit {T,N,W} (:: Type{Histogram{T}} , vs:: NTuple{N,AbstractVector} , wv:: WeightVec{W} , edges:: NTuple{N,AbstractVector} ; closed:: Symbol = :default_left ) =
271303 append! (Histogram (edges, T, _check_closed_arg (closed,:fit ), false ), vs, wv)
272304
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
274306 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)
276308end
277309
278310fit (:: Type{Histogram} , args... ; kwargs... ) = fit (Histogram{Int}, args... ; kwargs... )
279311fit {N,W} (:: Type{Histogram} , vs:: NTuple{N,AbstractVector} , wv:: WeightVec{W} , args... ; kwargs... ) = fit (Histogram{W}, vs, wv, args... ; kwargs... )
280312
281313
282314# 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))
290317
291318norm_type {T<:Integer} (:: Type{T} ) = promote_type (T, Int64)
292319norm_type {T<:AbstractFloat} (:: Type{T} ) = promote_type (T, Float64)
0 commit comments