@@ -255,7 +255,9 @@ raw counts.
255255- `:dict`: use `Dict`-based method which is generally slower but uses less
256256 RAM and is safe for any data type.
257257"""
258- function addcounts! (cm:: Dict{T} , x:: AbstractArray{T} ; alg = :auto ) where T
258+ addcounts! (cm:: Dict , x; alg = :auto ) = _addcounts! (eltype (x), cm, x, alg = alg)
259+
260+ function _addcounts! (:: Type{T} , cm:: Dict , x; alg = :auto ) where T
259261 # if it's safe to be sorted using radixsort then it should be faster
260262 # albeit using more RAM
261263 if radixsort_safe (T) && (alg == :auto || alg == :radixsort )
@@ -269,7 +271,7 @@ function addcounts!(cm::Dict{T}, x::AbstractArray{T}; alg = :auto) where T
269271end
270272
271273""" Dict-based addcounts method"""
272- function addcounts_dict! (cm:: Dict{T} , x:: AbstractArray{T} ) where T
274+ function addcounts_dict! (cm:: Dict{T} , x) where T
273275 for v in x
274276 index = ht_keyindex2! (cm, v)
275277 if index > 0
@@ -286,14 +288,27 @@ end
286288# faster results and less memory usage. However we still wish to enable others
287289# to write generic algorithms, therefore the methods below still accept the
288290# `alg` argument but it is ignored.
289- function addcounts! ( cm:: Dict{Bool} , x:: AbstractArray{Bool} ; alg = :ignored )
291+ function _addcounts! ( :: Type{Bool} , cm:: Dict{Bool} , x:: AbstractArray{Bool} ; alg = :ignored )
290292 sumx = sum (x)
291293 cm[true ] = get (cm, true , 0 ) + sumx
292294 cm[false ] = get (cm, false , 0 ) + length (x) - sumx
293295 cm
294296end
295297
296- function addcounts! (cm:: Dict{T} , x:: AbstractArray{T} ; alg = :ignored ) where T <: Union{UInt8, UInt16, Int8, Int16}
298+ # specialized for `Bool` iterator
299+ function _addcounts! (:: Type{Bool} , cm:: Dict{Bool} , x; alg = :ignored )
300+ sumx = 0
301+ len = 0
302+ for i in x
303+ sumx += i
304+ len += 1
305+ end
306+ cm[true ] = get (cm, true , 0 ) + sumx
307+ cm[false ] = get (cm, false , 0 ) + len - sumx
308+ cm
309+ end
310+
311+ function _addcounts! (:: Type{T} , cm:: Dict{T} , x; alg = :ignored ) where T <: Union{UInt8, UInt16, Int8, Int16}
297312 counts = zeros (Int, 2 ^ (8 sizeof (T)))
298313
299314 @inbounds for xi in x
@@ -318,8 +333,7 @@ const BaseRadixSortSafeTypes = Union{Int8, Int16, Int32, Int64, Int128,
318333 Float32, Float64}
319334
320335" Can the type be safely sorted by radixsort"
321- radixsort_safe (:: Type{T} ) where {T<: BaseRadixSortSafeTypes } = true
322- radixsort_safe (:: Type ) = false
336+ radixsort_safe (:: Type{T} ) where T = T<: BaseRadixSortSafeTypes
323337
324338function _addcounts_radix_sort_loop! (cm:: Dict{T} , sx:: AbstractArray{T} ) where T
325339 last_sx = sx[1 ]
@@ -353,6 +367,12 @@ function addcounts_radixsort!(cm::Dict{T}, x::AbstractArray{T}) where T
353367 return _addcounts_radix_sort_loop! (cm, sx)
354368end
355369
370+ # fall-back for `x` an iterator
371+ function addcounts_radixsort! (cm:: Dict{T} , x) where T
372+ sx = sort! (collect (x), alg = RadixSort)
373+ return _addcounts_radix_sort_loop! (cm, sx)
374+ end
375+
356376function addcounts! (cm:: Dict{T} , x:: AbstractArray{T} , wv:: AbstractVector{W} ) where {T,W<: Real }
357377 n = length (x)
358378 length (wv) == n || throw (DimensionMismatch ())
@@ -386,7 +406,7 @@ of occurrences.
386406- `:dict`: use `Dict`-based method which is generally slower but uses less
387407 RAM and is safe for any data type.
388408"""
389- countmap (x:: AbstractArray{T} ; alg = :auto ) where {T} = addcounts! (Dict {T ,Int} (), x; alg = alg)
409+ countmap (x; alg = :auto ) = addcounts! (Dict {eltype(x) ,Int} (), x; alg = alg)
390410countmap (x:: AbstractArray{T} , wv:: AbstractVector{W} ) where {T,W<: Real } = addcounts! (Dict {T,W} (), x, wv)
391411
392412
0 commit comments