jli  Linuxx86_641.10.3v1.10.30b4590a5507d3f3046e5bafc007cacbbfc9b310b+yEOrderedCollections^r^Xź]i %5F/opt/julia/packages/OrderedCollections/9C4Uz/src/OrderedCollections.jl?}A@/opt/julia/packages/OrderedCollections/9C4Uz/src/dict_support.jl?}A@/opt/julia/packages/OrderedCollections/9C4Uz/src/ordered_dict.jl?}A?/opt/julia/packages/OrderedCollections/9C4Uz/src/little_dict.jl?}A?/opt/julia/packages/OrderedCollections/9C4Uz/src/ordered_set.jl?}A@/opt/julia/packages/OrderedCollections/9C4Uz/src/dict_sorting.jl?}A CoremуJ5Basemу]J5MainmуJ5ArgToolsBń x(mуF K5 Artifactsmr-V3|mу K5Base64UlD*_mу> K5CRC32c\y.jmуj K5 FileWatchingXzsy`{,zmуh& K5LibdluVW59˗,mу-" K5LoggingT{VhUXM=mуrU" K5MmapP~:xg,Omу|' K5NetworkOptionsC0YW,mуʠ, K5SHAQ<$!<%mу1 K5 Serialization [)*k1mу-G K5Sockets1V$ bdސݗmуYBY K5UnicodeP>I>Nrmуeszo K5 LinearAlgebraSm7̏mуuux K5 OpenBLAS_jll[(Śb6EcQ FmуDux K5libblastrampoline_jllLSۆ }lxӠmу^} K5MarkdownZPn7z`smу/Ed~ K5Printfg^cX׸QDmу;h K5Random_ɢ?\Ymу? K5TarOi>աmу!t, K5DatesEY8pj2 mуX K5FuturebS;3{I xVMmуsD K5InteractiveUtilsWL ~@'ZmуVg K5LibGit2Z[&RPTv3EКRmу8J K5 LibGit2_jll YXg}]$mуD K5 MbedTLS_jllAX 3ȡ_mу- K5 LibSSH2_jlloTZk)߆ 0 rehash!(d) end @assert d.ndel == 0 OrderedDict{K,V}(copy(d.slots), copy(d.keys), copy(d.vals), 0, d.maxprobe, false) end OrderedDict() = OrderedDict{Any,Any}() OrderedDict(kv::Tuple{}) = OrderedDict() copy(d::OrderedDict) = OrderedDict(d) # TODO: this can probably be simplified using `eltype` as a THT (Tim Holy trait) # OrderedDict{K,V}(kv::Tuple{Vararg{Tuple{K,V}}}) = OrderedDict{K,V}(kv) # OrderedDict{K }(kv::Tuple{Vararg{Tuple{K,Any}}}) = OrderedDict{K,Any}(kv) # OrderedDict{V }(kv::Tuple{Vararg{Tuple{Any,V}}}) = OrderedDict{Any,V}(kv) OrderedDict(kv::Tuple{Vararg{Pair{K,V}}}) where {K,V} = OrderedDict{K,V}(kv) OrderedDict(kv::AbstractArray{Tuple{K,V}}) where {K,V} = OrderedDict{K,V}(kv) OrderedDict(kv::AbstractArray{Pair{K,V}}) where {K,V} = OrderedDict{K,V}(kv) OrderedDict(kv::AbstractDict{K,V}) where {K,V} = OrderedDict{K,V}(kv) OrderedDict(ps::Pair{K,V}...) where {K,V} = OrderedDict{K,V}(ps) OrderedDict(ps::Pair...) = OrderedDict(ps) function OrderedDict(kv) try dict_with_eltype((K, V) -> OrderedDict{K, V}, kv, eltype(kv)) catch e if isempty(methods(iterate, (typeof(kv),))) || !all(x->isa(x, Union{Tuple,Pair}), kv) throw(ArgumentError("OrderedDict(kv): kv needs to be an iterator of tuples or pairs")) else rethrow(e) end end end empty(d::OrderedDict{K,V}) where {K,V} = OrderedDict{K,V}() empty(d::OrderedDict, ::Type{K}, ::Type{V}) where {K, V} = OrderedDict{K, V}() length(d::OrderedDict) = length(d.keys) - d.ndel isempty(d::OrderedDict) = (length(d) == 0) """ isordered(::Type) Property of associative containers, that is `true` if the container type has a defined order (such as `OrderedDict` and `SortedDict`), and `false` otherwise. """ isordered(::Type{T}) where {T<:AbstractDict} = false isordered(::Type{T}) where {T<:OrderedDict} = true # conversion between OrderedDict types function convert(::Type{OrderedDict{K,V}}, d::AbstractDict) where {K,V} d isa OrderedDict{K, V} && return d if !isordered(typeof(d)) Base.depwarn("Conversion to OrderedDict is deprecated for unordered associative containers (in this case, $(typeof(d))). Use an ordered or sorted associative type, such as SortedDict and OrderedDict.", :convert) end h = OrderedDict{K,V}() for (k,v) in d ck = convert(K,k) if !haskey(h,ck) h[ck] = convert(V,v) else error("key collision during dictionary conversion") end end return h end isslotempty(slot_value::Integer) = slot_value == 0 isslotfilled(slot_value::Integer) = slot_value > 0 isslotmissing(slot_value::Integer) = slot_value < 0 function rehash!(h::OrderedDict{K,V}, newsz = length(h.slots)) where {K,V} olds = h.slots keys = h.keys vals = h.vals sz = length(olds) newsz = _tablesz(newsz) h.dirty = true count0 = length(h) if count0 == 0 resize!(h.slots, newsz) fill!(h.slots, 0) resize!(h.keys, 0) resize!(h.vals, 0) h.ndel = 0 return h end slots = zeros(Int32, newsz) maxprobe = 0 if h.ndel > 0 ndel0 = h.ndel ptrs = !isbitstype(K) to = 1 # TODO: to get the best performance we need to avoid reallocating these. # This algorithm actually works in place, unless the dict is modified # due to GC during this process. newkeys = similar(keys, count0) newvals = similar(vals, count0) @inbounds for from = 1:length(keys) if !ptrs || isassigned(keys, from) k = keys[from] hashk = hash(k)%Int isdeleted = false if !ptrs iter = 0 index = (hashk & (sz-1)) + 1 while iter <= h.maxprobe si = olds[index] si == from && break # if we find si == 0, then the key was deleted and it's slot was reused/overwritten (si == -from || si == 0) && (isdeleted = true; break) index = (index & (sz-1)) + 1 iter += 1 end iter > h.maxprobe && (isdeleted = true) # Another case where the slot was reused/overwritten end if !isdeleted index0 = index = (hashk & (newsz-1)) + 1 while slots[index] != 0 index = (index & (newsz-1)) + 1 end probe = (index - index0) & (newsz-1) probe > maxprobe && (maxprobe = probe) slots[index] = to newkeys[to] = k newvals[to] = vals[from] to += 1 end if h.ndel != ndel0 # if items are removed by finalizers, retry return rehash!(h, newsz) end end end h.keys = newkeys h.vals = newvals h.ndel = 0 else @inbounds for i = 1:count0 k = keys[i] index0 = index = hashindex(k, newsz) while slots[index] != 0 index = (index & (newsz-1)) + 1 end probe = (index - index0) & (newsz-1) probe > maxprobe && (maxprobe = probe) slots[index] = i if h.ndel > 0 # if items are removed by finalizers, retry return rehash!(h, newsz) end end end h.slots = slots h.maxprobe = maxprobe return h end function sizehint!(d::OrderedDict, newsz) slotsz = (newsz*3)>>1 oldsz = length(d.slots) if slotsz <= oldsz # todo: shrink # be careful: rehash!() assumes everything fits. it was only designed # for growing. return d end # grow at least 25% slotsz = max(slotsz, (oldsz*5)>>2) rehash!(d, slotsz) end function empty!(h::OrderedDict{K,V}) where {K,V} fill!(h.slots, 0) empty!(h.keys) empty!(h.vals) h.ndel = 0 h.dirty = true return h end # get the index where a key is stored, or -1 if not present function ht_keyindex(h::OrderedDict{K,V}, key, direct) where {K,V} slots = h.slots sz = length(slots) iter = 0 maxprobe = h.maxprobe index = hashindex(key, sz) keys = h.keys @inbounds while iter <= maxprobe si = slots[index] isslotempty(si) && break if isslotfilled(si) && isequal(key, keys[si]) return ifelse(direct, oftype(index, si), index) end index = (index & (sz-1)) + 1 iter += 1 end return -1 end # get the index where a key is stored, or -pos if not present # and the key would be inserted at pos # This version is for use by setindex! and get! function ht_keyindex2(h::OrderedDict{K,V}, key) where {K,V} slots = h.slots sz = length(slots) iter = 0 maxprobe = h.maxprobe index = hashindex(key, sz) keys = h.keys avail = 0 @inbounds while iter <= maxprobe si = slots[index] if isslotempty(si) avail < 0 && return avail return -index end if isslotmissing(si) avail == 0 && (avail = -index) elseif isequal(key, keys[si]) return oftype(index, si) end index = (index & (sz-1)) + 1 iter += 1 end avail < 0 && return avail # If key is not present, may need to keep searching to find slot maxallowed = max(maxallowedprobe, sz>>maxprobeshift) @inbounds while iter < maxallowed if !isslotfilled(slots[index]) h.maxprobe = iter return -index end index = (index & (sz-1)) + 1 iter += 1 end rehash!(h, length(h) > 64000 ? sz*2 : sz*4) return ht_keyindex2(h, key) end function _setindex!(h::OrderedDict, v, key, index) hk, hv = h.keys, h.vals #push!(h.keys, key) ccall(:jl_array_grow_end, Cvoid, (Any, UInt), hk, 1) nk = length(hk) @inbounds hk[nk] = key #push!(h.vals, v) ccall(:jl_array_grow_end, Cvoid, (Any, UInt), hv, 1) @inbounds hv[nk] = v @inbounds h.slots[index] = nk h.dirty = true sz = length(h.slots) cnt = nk - h.ndel # Rehash now if necessary if h.ndel >= ((3*nk)>>2) || cnt*3 > sz*2 # > 3/4 deleted or > 2/3 full rehash!(h, cnt > 64000 ? cnt*2 : cnt*4) end end function setindex!(h::OrderedDict{K,V}, v0, key0) where {K,V} key = convert(K, key0) if !isequal(key, key0) throw(ArgumentError("$key0 is not a valid key for type $K")) end v = convert(V, v0) index = ht_keyindex2(h, key) if index > 0 @inbounds h.keys[index] = key @inbounds h.vals[index] = v else _setindex!(h, v, key, -index) end return h end function get!(h::OrderedDict{K,V}, key0, default) where {K,V} key = convert(K, key0) if !isequal(key, key0) throw(ArgumentError("$key0 is not a valid key for type $K")) end index = ht_keyindex2(h, key) index > 0 && return h.vals[index] v = convert(V, default) _setindex!(h, v, key, -index) return v end function get!(default::Base.Callable, h::OrderedDict{K,V}, key0) where {K,V} key = convert(K, key0) if !isequal(key, key0) throw(ArgumentError("$key0 is not a valid key for type $K")) end index = ht_keyindex2(h, key) index > 0 && return h.vals[index] h.dirty = false v = convert(V, default()) if h.dirty # calling default could have dirtied h index = ht_keyindex2(h, key) end if index > 0 h.keys[index] = key h.vals[index] = v else _setindex!(h, v, key, -index) end return v end function getindex(h::OrderedDict{K,V}, key) where {K,V} index = ht_keyindex(h, key, true) return (index<0) ? throw(KeyError(key)) : h.vals[index]::V end function get(h::OrderedDict{K,V}, key, default) where {K,V} index = ht_keyindex(h, key, true) return (index<0) ? default : h.vals[index]::V end function get(default::Base.Callable, h::OrderedDict{K,V}, key) where {K,V} index = ht_keyindex(h, key, true) return (index<0) ? default() : h.vals[index]::V end haskey(h::OrderedDict, key) = (ht_keyindex(h, key, true) >= 0) in(key, v::Base.KeySet{K,T}) where {K,T<:OrderedDict{K}} = (ht_keyindex(v.dict, key, true) >= 0) function getkey(h::OrderedDict{K,V}, key, default) where {K,V} index = ht_keyindex(h, key, true) return (index<0) ? default : h.keys[index]::K end function _pop!(h::OrderedDict, index) @inbounds val = h.vals[h.slots[index]] _delete!(h, index) return val end function pop!(h::OrderedDict) h.ndel > 0 && rehash!(h) key = h.keys[end] index = ht_keyindex(h, key, false) return key => _pop!(h, index) end function popfirst!(h::OrderedDict) h.ndel > 0 && rehash!(h) key = h.keys[1] index = ht_keyindex(h, key, false) key => _pop!(h, index) end function pop!(h::OrderedDict, key) index = ht_keyindex(h, key, false) index > 0 ? _pop!(h, index) : throw(KeyError(key)) end function pop!(h::OrderedDict, key, default) index = ht_keyindex(h, key, false) index > 0 ? _pop!(h, index) : default end function _delete!(h::OrderedDict, index) @inbounds ki = h.slots[index] @inbounds h.slots[index] = -ki ccall(:jl_arrayunset, Cvoid, (Any, UInt), h.keys, ki-1) ccall(:jl_arrayunset, Cvoid, (Any, UInt), h.vals, ki-1) h.ndel += 1 h.dirty = true return h end function delete!(h::OrderedDict, key) index = ht_keyindex(h, key, false) if index > 0; _delete!(h, index); end return h end function iterate(t::OrderedDict) t.ndel > 0 && rehash!(t) length(t.keys) < 1 && return nothing return (Pair(t.keys[1], t.vals[1]), 2) end function iterate(t::OrderedDict, i) length(t.keys) < i && return nothing return (Pair(t.keys[i], t.vals[i]), i+1) end # lazy reverse iteration function iterate(rt::Iterators.Reverse{<:OrderedDict}) t = rt.itr t.ndel > 0 && rehash!(t) n = length(t.keys) n < 1 && return nothing return (Pair(t.keys[n], t.vals[n]), n - 1) end function iterate(rt::Iterators.Reverse{<:OrderedDict}, i) t = rt.itr i < 1 && return nothing return (Pair(t.keys[i], t.vals[i]), i - 1) end function _merge_kvtypes(d, others...) K, V = keytype(d), valtype(d) for other in others K = promote_type(K, keytype(other)) V = promote_type(V, valtype(other)) end return (K,V) end function merge(d::OrderedDict, others::AbstractDict...) K,V = _merge_kvtypes(d, others...) merge!(OrderedDict{K,V}(), d, others...) end function merge(combine::Function, d::OrderedDict, others::AbstractDict...) K,V = _merge_kvtypes(d, others...) merge!(combine, OrderedDict{K,V}(), d, others...) end function Base.map!(f, iter::Base.ValueIterator{<:OrderedDict}) dict = iter.dict vals = dict.vals elements = length(vals) - dict.ndel elements == 0 && return iter for i in dict.slots if i > 0 @inbounds vals[i] = f(vals[i]) elements -= 1 elements == 0 && break end end return iter end last(h::OrderedDict) = h.keys[end] => h.vals[end] ?/opt/julia/packages/OrderedCollections/9C4Uz/src/little_dict.jl!const StoreType{T} = Union{Tuple{Vararg{T}}, AbstractVector{T}} @noinline function _throw_unequal_lengths(nk::Int, nv::Int) throw(ArgumentError("Number of keys ($nk) differs from number of values ($nv).")) end """ LittleDict(keys, vals)<:AbstractDict An ordered dictionary type for small numbers of keys. Rather than using `hash` or some other sophisticated measure to store the vals in a clever arrangement, it just keeps everything in a pair of lists. While theoretically this has expected time complexity _O(n)_ (vs the hash-based [`OrderedDict`](@ref)/`Dict`'s expected time complexity _O(1)_, and the search-tree-based `SortedDict`'s expected time complexity _O(log(n))_), in practice it is really fast, because it is cache & SIMD friendly. It is reasonable to expect it to outperform an `OrderedDict`, with up to around 30 elements in general; or with up to around 50 elements if using a `LittleDict` backed by `Tuples` (see [`freeze`](@ref)) However, this depends on exactly how long `isequal` and `hash` take, as well as on how many hash collisions occur etc. !!! note When constructing a `LittleDict` it is faster to pass in the keys and values each as seperate lists. So if you have them seperately already, do `LittleDict(ks, vs)` not `LittleDict(zip(ks, vs))`. Furthermore, key and value lists that are passed as `Tuple`s will not require any copies to create the `LittleDict`, so `LittleDict(ks::Tuple, vs::Tuple)` is the fastest constructor of all. """ struct LittleDict{K, V, KS<:StoreType{K}, VS<:StoreType{V}} <: AbstractDict{K, V} keys::KS vals::VS function LittleDict{K, V, KS, VS}(keys, vals) where {K, V, KS, VS} nk = length(keys) nv = length(vals) nk == nv || _throw_unequal_lengths(Int(nk), Int(nv)) return new{K, V, KS, VS}(keys, vals) end LittleDict{K, V, <:Tuple, <:Tuple}() where {K, V} = new{K, V, Tuple{}, Tuple{}}((), ()) LittleDict{K, V, KS, VS}() where {K, V, KS, VS} = LittleDict{K, V, KS, VS}(KS(), VS()) end function LittleDict{K,V}(ks::KS, vs::VS) where {K,V, KS<:StoreType,VS<:StoreType} return LittleDict{K, V, KS, VS}(ks, vs) end function LittleDict(ks::KS, vs::VS) where {KS<:StoreType,VS<:StoreType} return LittleDict{eltype(KS), eltype(VS)}(ks, vs) end # Other iterators should be copied to a Vector LittleDict(ks, vs) = LittleDict(collect(ks), collect(vs)) function LittleDict{K,V}(itr) where {K,V} ks = K[] vs = V[] for val in itr if !(val isa Union{Tuple{<:Any, <:Any}, Pair}) throw(ArgumentError( "LittleDict(kv): kv needs to be an iterator of tuples or pairs") ) end k, v = val push!(ks, k) push!(vs, v) end return LittleDict(ks, vs) end LittleDict{K,V}(itr...) where {K,V} = LittleDict{K,V}(itr) LittleDict(itr...) = LittleDict(itr) LittleDict(itr::T) where T = LittleDict{kvtype(eltype(T))...}(itr) # Avoid contention between the core constructor, and the list of elements LittleDict(itr1::Pair, itr2::Pair) = LittleDict(first.([itr1, itr2]), last.([itr1,itr2])) LittleDict(itr1::Pair) = LittleDict([first(itr1)], [last(itr1)]) LittleDict{K, V}(itr::Pair) where {K, V} = LittleDict{K,V}(K[first(itr)], V[last(itr)]) kvtype(::Any) = (Any, Any) kvtype(::Type{Union{}}) = (Any,Any) kvtype(::Type{Pair{K,V}}) where {K,V} = (K,V) kvtype(::Type{Pair{<:Any,V}}) where {V} = (Any,V) kvtype(::Type{Pair{K,<:Any}}) where {K} = (K,Any) kvtype(::Type{Tuple{K,V}}) where {K,V} = (K,V) """ freeze(dd::AbstractDict) Render a dictionary immutable by converting it to a `Tuple`-backed `LittleDict`. The `Tuple`-backed `LittleDict` is faster than the `Vector`-backed `LittleDict`, particularly when the keys are all concretely typed. """ function freeze(dd::AbstractDict) ks = Tuple(keys(dd)) vs = Tuple(values(dd)) return LittleDict(ks, vs) end isordered(::Type{<:LittleDict}) = true # For now these are internal UnionAlls for dispatch purposes const UnfrozenLittleDict{K, V} = LittleDict{K, V, <:AbstractVector{K}, <:AbstractVector{V}} const FrozenLittleDict{K, V} = LittleDict{K, V, <:Tuple, <:Tuple} ##### Methods that all AbstractDicts should implement Base.length(dd::LittleDict) = length(dd.keys) function Base.getkey(dd::LittleDict, key, default) if key ∈ dd.keys return key else return default end end function Base.map!(f, iter::Base.ValueIterator{<:LittleDict}) dict = iter.dict vals = dict.vals for i in 1:length(vals) @inbounds vals[i] = f(vals[i]) end return iter end struct NotFoundSentinel end # Struct to mark not not found function Base.get(dd::LittleDict, key, default) @assert length(dd.keys) == length(dd.vals) for ii in 1:length(dd.keys) cand = @inbounds dd.keys[ii] isequal(cand, key) && return @inbounds(dd.vals[ii]) end return default end function get(default::Base.Callable, dd::LittleDict, key) got = get(dd, key, NotFoundSentinel()) if got isa NotFoundSentinel # not found return default() else return got end end function Base.iterate(dd::LittleDict, ii=1) ii > length(dd.keys) && return nothing return (dd.keys[ii] => dd.vals[ii], ii+1) end # lazy reverse iteration function Base.iterate(rdd::Iterators.Reverse{<:LittleDict}, ii=length(rdd.itr.keys)) dd = rdd.itr ii < 1 && return nothing return (dd.keys[ii] => dd.vals[ii], ii-1) end function merge(d1::LittleDict, others::AbstractDict...) return merge((x,y)->y, d1, others...) end function merge( combine::Function, d::LittleDict, others::AbstractDict... ) K,V = _merge_kvtypes(d, others...) dc = LittleDict{K,V}(d) for d2 in others for (k2,v2) in d2 got = get(dc, k2, NotFoundSentinel()) if got isa NotFoundSentinel add_new!(dc, k2, v2) else # GOLDPLATE: ideally we would avoid iterating this twice # once for get and once for setindex! dc[k2]=combine(got, v2) end end end return dc end function Base.empty(dd::LittleDict{K,V}) where {K,V} LittleDict{K, V}(empty(getfield(dd, :keys)), empty(getfield(dd, :vals))) end ######## Methods that all mutable AbstractDict's should implement function Base.sizehint!(dd::UnfrozenLittleDict, sz) sizehint!(dd.keys, sz) sizehint!(dd.vals,sz) return dd end function add_new!(dd::UnfrozenLittleDict{K, V}, key, value) where {K, V} kk = convert(K, key) vv = convert(V, value) # if we can convert it to the right type, and the dict is unfrozen # then neither push can fail, so the dict length will remain in sync push!(dd.keys, kk) push!(dd.vals, vv) return dd end function Base.setindex!(dd::LittleDict{K,V, <:Any, <:Vector}, value, key) where {K,V} # Note we only care if the Value store is mutable (<:Vector) # As we can have immutable keys, if we are setting the value of an existing key # Assertion below commented out as by standards of carefully optimised # setindex! it has huge code (26%), this does mean that if someone has messed # with the fields of the LittleDict directly, then the @inbounds could be invalid #@assert length(dd.keys) == length(dd.vals) kk = convert(K, key) vv = convert(V, value) for ii in 1:length(dd.keys) cand = @inbounds dd.keys[ii] if isequal(cand, kk) @inbounds(dd.vals[ii] = vv) return dd end end add_new!(dd, key, value) return dd end function Base.pop!(dd::UnfrozenLittleDict) pop!(dd.keys) return pop!(dd.vals) end function Base.pop!(dd::UnfrozenLittleDict, key) @assert length(dd.keys) == length(dd.vals) for ii in 1:length(dd.keys) cand = @inbounds dd.keys[ii] if isequal(cand, key) deleteat!(dd.keys, ii) val = @inbounds dd.vals[ii] deleteat!(dd.vals, ii) return val end end end function Base.delete!(dd::UnfrozenLittleDict, key) pop!(dd, key) return dd end Base.empty!(dd::UnfrozenLittleDict) = (empty!(dd.keys); empty!(dd.vals); dd) function get!(default::Base.Callable, dd::UnfrozenLittleDict, key) got = get(dd, key, NotFoundSentinel()) if got isa NotFoundSentinel # not found val = default() add_new!(dd, key, val) return val else return got end end get!(dd::UnfrozenLittleDict, key, default) = get!(()->default, dd, key) ?/opt/julia/packages/OrderedCollections/9C4Uz/src/ordered_set.jl# ordered sets # This was largely copied and modified from Base struct OrderedSet{T} <: AbstractSet{T} dict::OrderedDict{T,Nothing} OrderedSet{T}() where {T} = new{T}(OrderedDict{T,Nothing}()) OrderedSet{T}(xs) where {T} = union!(OrderedSet{T}(), xs) function OrderedSet{T}(s::Base.KeySet{T, <:OrderedDict{T}}) where {T} d = s.dict slots = copy(d.slots) keys = copy(d.keys) vals = similar(d.vals, Nothing) new{T}(OrderedDict{T,Nothing}(slots, keys, vals, d.ndel, d.maxprobe, d.dirty)) end end OrderedSet() = OrderedSet{Any}() OrderedSet(xs) = OrderedSet{eltype(xs)}(xs) show(io::IO, s::OrderedSet) = (show(io, typeof(s)); print(io, "("); !isempty(s) && Base.show_vector(io, s,'[',']'); print(io, ")")) isempty(s::OrderedSet) = isempty(s.dict) length(s::OrderedSet) = length(s.dict) sizehint!(s::OrderedSet, sz::Integer) = (sizehint!(s.dict, sz); s) in(x, s::OrderedSet) = haskey(s.dict, x) push!(s::OrderedSet, x) = (s.dict[x] = nothing; s) pop!(s::OrderedSet, x) = (pop!(s.dict, x); x) pop!(s::OrderedSet, x, deflt) = pop!(s.dict, x, deflt) == deflt ? deflt : x delete!(s::OrderedSet, x) = (delete!(s.dict, x); s) empty(s::OrderedSet{T}) where {T} = OrderedSet{T}() copy(s::OrderedSet) = union!(empty(s), s) empty!(s::OrderedSet{T}) where {T} = (empty!(s.dict); s) emptymutable(s::OrderedSet{T}, ::Type{U}=T) where {T,U} = OrderedSet{U}() copymutable(s::OrderedSet) = copy(s) # NOTE: manually optimized to take advantage of OrderedDict representation function iterate(s::OrderedSet) s.dict.ndel > 0 && rehash!(s.dict) length(s.dict.keys) < 1 && return nothing return (s.dict.keys[1], 2) end function iterate(s::OrderedSet, i) length(s.dict.keys) < i && return nothing return (s.dict.keys[i], i+1) end # lazy reverse iteration function iterate(rs::Iterators.Reverse{<:OrderedSet}, i = length(rs.itr)) s = rs.itr i < 1 && return nothing return (s.dict.keys[i], i-1) end pop!(s::OrderedSet) = pop!(s.dict)[1] popfirst!(s::OrderedSet) = popfirst!(s.dict)[1] ==(l::OrderedSet, r::OrderedSet) = (length(l) == length(r)) && (l <= r) <(l::OrderedSet, r::OrderedSet) = (length(l) < length(r)) && (l <= r) <=(l::OrderedSet, r::OrderedSet) = issubset(l, r) function filter!(f::Function, s::OrderedSet) for x in s if !f(x) delete!(s, x) end end return s end const orderedset_seed = UInt === UInt64 ? 0x2114638a942a91a5 : 0xd86bdbf1 function hash(s::OrderedSet, h::UInt) h = hash(orderedset_seed, h) s.dict.ndel > 0 && rehash!(s.dict) hash(s.dict.keys, h) end # Deprecated functionality, see # https://github.com/JuliaCollections/DataStructures.jl/pull/180#issuecomment-400269803 function getindex(s::OrderedSet, i::Int) Base.depwarn("indexing is deprecated for OrderedSet, please rewrite your code to use iteration", :getindex) s.dict.ndel > 0 && rehash!(s.dict) return s.dict.keys[i] end function lastindex(s::OrderedSet) Base.depwarn("indexing is deprecated for OrderedSet, please rewrite your code to use iteration", :lastindex) s.dict.ndel > 0 && rehash!(s.dict) return lastindex(s.dict.keys) end function nextind(::OrderedSet, i::Int) Base.depwarn("indexing is deprecated for OrderedSet, please rewrite your code to use iteration", :lastindex) return i + 1 # Needed on 0.7 to mimic array indexing. end function keys(s::OrderedSet) Base.depwarn("indexing is deprecated for OrderedSet, please rewrite your code to use iteration", :lastindex) s.dict.ndel > 0 && rehash!(s.dict) return 1:length(s) end @/opt/julia/packages/OrderedCollections/9C4Uz/src/dict_sorting.jl# Sort for dicts import Base: sort, sort! function sort!(d::OrderedDict; byvalue::Bool=false, args...) if d.ndel > 0 rehash!(d) end data = byvalue ? d.vals : d.keys # Filter out the kwargs supported by issorted (notably, :alg needs to be removed) issorted_kw = NamedTuple(k => v for (k, v) in args if k in (:lt, :by, :rev, :order)) issorted(data; issorted_kw...) && return d p = sortperm(data; args...) d.keys = d.keys[p] d.vals = d.vals[p] rehash!(d) return d end # Compared to just sorting the underlying OrderedDict, this method calls sort! # directly on the keys (no need to sort d.vals::Vector{Nothing}). This saves # the allocation of the permutation vector in sortperm, and subsequent # allocations of new d.keys and d.vals vectors. function sort!(s::OrderedSet; kwargs...) d = s.dict d.ndel > 0 && rehash!(d) sort!(d.keys; kwargs...) rehash!(d) return s end sort(d::Union{OrderedDict,OrderedSet}; args...) = sort!(copy(d); args...) @deprecate sort(d::Dict; args...) sort!(OrderedDict(d); args...) function sort(d::LittleDict; byvalue::Bool=false, args...) if byvalue p = sortperm(d.vals; args...) else p = sortperm(d.keys; args...) end return LittleDict(d.keys[p], d.vals[p]) end _ }