From 7bc21643c84fae17761f0668a2ff6598c05a4c1f Mon Sep 17 00:00:00 2001 From: Heptazhou Date: Wed, 27 Nov 2024 05:28:07 +0000 Subject: [PATCH] Update --- docs/make.jl | 3 +-- ext/StatisticsExt.jl | 2 +- src/Exts.jl | 5 ++++- src/Function.jl | 12 ++++++++++++ src/OrderedCollectionsExt.jl | 7 ++++--- src/Type.jl | 14 +++++++------- test/runtests.jl | 31 +++++++++++++++++++------------ 7 files changed, 48 insertions(+), 26 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index e2dffb9..62188da 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -31,8 +31,7 @@ const cache = URL::String -> (URL, HTTP.download(URL * "objects.inv", mktempdir( const entry = ODict{String, String}() const extra = Vector{Module}() const links = InterLinks( - "Julia" => cache("https://docs.julialang.org/en/v1/"), - "OrderedCollections" => cache("https://juliacollections.github.io/OrderedCollections.jl/dev/"), + "Julia" => cache("https://docs.julialang.org/en/v1/"), ) cd(@__DIR__) do diff --git a/ext/StatisticsExt.jl b/ext/StatisticsExt.jl index cead3d5..4036ab2 100644 --- a/ext/StatisticsExt.jl +++ b/ext/StatisticsExt.jl @@ -34,7 +34,7 @@ See also [`mean(::AbstractArray)`](@extref Statistics.mean), """ function Exts.nanmean(A::AbstractArray, w::AbstractWeights; dims::Union{Colon, Int} = :) r = mean(A, (w); dims) - !isnan(r) ? (r) : (@assert all(iszero, w); mean(A; dims)) + !isnan(r) ? (r) : (x = mean(A; dims); @assert isnan(x) || all(iszero, w); x) end # @doc nanmean end # module diff --git a/src/Exts.jl b/src/Exts.jl index d418b6d..ae9cbe5 100644 --- a/src/Exts.jl +++ b/src/Exts.jl @@ -40,6 +40,7 @@ export dropmissing export dropnothing export ensure_vector export flatten +export freeze export getfirst export getlast export invsqrt @@ -53,6 +54,7 @@ export return_type export stdpath using Logging: Logging +using OrderedCollections: OrderedCollections using Reexport: @reexport @reexport begin @@ -61,7 +63,8 @@ using Base: Bottom, Fix1, Fix2 using Base: nonnothingtype, notnothing, return_types using Base.Threads: @spawn, @threads, nthreads using Core: TypeofBottom, TypeofVararg -using OrderedCollections: LittleDict, OrderedDict, OrderedSet, freeze +using OrderedCollections: FrozenLittleDict, UnfrozenLittleDict +using OrderedCollections: LittleDict, OrderedDict, OrderedSet end include("BaseExt.jl") diff --git a/src/Function.jl b/src/Function.jl index 553c3ea..be53a10 100644 --- a/src/Function.jl +++ b/src/Function.jl @@ -52,6 +52,18 @@ function ext(x::Symbol)::Maybe{Module} Base.get_extension(Exts, Symbol(x, :Ext)) end +""" + freeze(d::AbstractDict{K, V}) where {K, V} -> LDict{K, V} + +Render a dictionary immutable by converting it to a `Tuple`-backed +[`LittleDict`](@ref LDict). The `Tuple`-backed `LittleDict` is faster than +the `Vector`-backed `LittleDict`, particularly when the keys are all +concretely typed. +""" +function freeze(d::AbstractDict{K, V})::FrozenLittleDict{K, V} where {K, V} + OrderedCollections.freeze(d) +end + """ invsqrt(x::T) where T <: Real -> AbstractFloat diff --git a/src/OrderedCollectionsExt.jl b/src/OrderedCollectionsExt.jl index 035274c..e83dd17 100644 --- a/src/OrderedCollectionsExt.jl +++ b/src/OrderedCollectionsExt.jl @@ -15,11 +15,12 @@ module OrderedCollectionsExt using Base: isbitsunion, unwrap_unionall -using OrderedCollections: OrderedCollections, OrderedDict, _tablesz, hashindex, rehash! +using Exts: ODict +using OrderedCollections: OrderedCollections, _tablesz, hashindex, rehash! -@static if [unwrap_unionall(methods(rehash!, (OrderedDict, Int))[1].sig)...][3] == Any +@static if [unwrap_unionall(methods(rehash!, (ODict, Int))[1].sig)...][3] == Any #! format: noindent -function OrderedCollections.rehash!(h::OrderedDict{K, V}, newsz::Integer) where {K, V} +function OrderedCollections.rehash!(h::ODict{K, V}, newsz::Integer) where {K, V} olds = h.slots keys = h.keys vals = h.vals diff --git a/src/Type.jl b/src/Type.jl index 634209b..afbce89 100644 --- a/src/Type.jl +++ b/src/Type.jl @@ -65,16 +65,16 @@ An ordered dictionary type for small numbers of keys. Rather than using arrangement, it just keeps everything in a pair of lists. While theoretically this has expected time complexity ``O(n)`` (vs the -hash-based [`OrderedDict`](@extref OrderedCollections.OrderedDict)/`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. +hash-based [`OrderedDict`](@ref ODict)/`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 `Tuple`s (see [`freeze`](@extref -OrderedCollections.freeze)). However, this depends on exactly how long -`isequal` and `hash` take, as well as on how many hash collisions occur etc. +`LittleDict` backed by `Tuple`s (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 diff --git a/test/runtests.jl b/test/runtests.jl index 75b5693..87af833 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -127,6 +127,7 @@ end @test_throws UndefVarError dropnothing @test_throws UndefVarError ensure_vector @test_throws UndefVarError flatten + @test_throws UndefVarError freeze @test_throws UndefVarError getfirst @test_throws UndefVarError getlast @test_throws UndefVarError invsqrt @@ -145,7 +146,7 @@ end @test_throws UndefVarError Bottom @test_throws UndefVarError Fix1 @test_throws UndefVarError Fix2 - @test_throws UndefVarError freeze + @test_throws UndefVarError FrozenLittleDict @test_throws UndefVarError LittleDict @test_throws UndefVarError nonnothingtype @test_throws UndefVarError notnothing @@ -155,6 +156,7 @@ end @test_throws UndefVarError return_types @test_throws UndefVarError TypeofBottom @test_throws UndefVarError TypeofVararg + @test_throws UndefVarError UnfrozenLittleDict @test_throws MethodError (>, <)(0) @test_throws MethodError (sin, cos)(0) @@ -169,14 +171,15 @@ end @test_throws MethodError collect(Tuple{}) @test_throws MethodError convert(Set, 1:3) @test_throws MethodError convert(Set{Int}, 1:3) - @test_throws MethodError display([:_, -1]') - @test_throws MethodError display([:p, :q]') - @test_throws MethodError display(['1', '2']') - @test_throws MethodError display(["x", "y"]') - @test_throws MethodError display([(r"^"), (r"$")]') @test_throws MethodError log10(11, 2) @test_throws MethodError ntuple(2, 1) - a_unionall = Union{Vector{T}, Matrix{T}, Array{T, 3}} where T + @test_throws MethodError sprint(display, [:_, -1]') + @test_throws MethodError sprint(display, [:p, :q]') + @test_throws MethodError sprint(display, ['1', '2']') + @test_throws MethodError sprint(display, ["x", "y"]') + @test_throws MethodError sprint(display, [(r"^"), (r"$")]') + a_ua_tuple = Tuple{Vector{T}, Matrix{T}, Array{T, 3}} where T + a_ua_union = Union{Vector{T}, Matrix{T}, Array{T, 3}} where T a2_missing = Array{Missing, 2}(undef, Tuple(rand(0:9, 2))) a3_nothing = Array{Nothing, 3}(undef, Tuple(rand(0:9, 3))) allowed_undefineds = GlobalRef.(Ref(Base), [:active_repl, :active_repl_backend]) @@ -190,11 +193,12 @@ end @test ['1' '2'] == ['1', '2']' @test ["x" "y"] == ["x", "y"]' @test [(r"^") (r"$")] == [(r"^"), (r"$")]' - @test [a_unionall::UnionAll...] == UnionAll[Vector, Matrix, Array{T, 3} where T] - @test [AbstractMatrix...] == [Vector...] == [] - @test [AbstractMatrix{UInt8}...] == [UInt8, 2] - @test [AbstractVecOrMat...] == [AbstractVector, AbstractMatrix] - @test [Core.BuiltinInts...] ⊋ [Bool, Int8, Int16, Int32, Int64, Int128] + @test [a_ua_tuple::UnionAll...] == Any[] + @test [a_ua_union::UnionAll...] == UnionAll[Vector, Matrix, Array{T, 3} where T] + @test [AbstractMatrix...] == [Vector...] == Any[] + @test [AbstractMatrix{UInt8}...] == Any[UInt8, 2] + @test [AbstractVecOrMat...] == UnionAll[AbstractVector, AbstractMatrix] + @test [Core.BuiltinInts...] ⊋ DataType[Bool, Int8, Int16, Int32, Int64, Int128] @test [NTuple{3, Int}...] == fill(Int, 3) @test [Tuple...] == [Vararg{Any}] @test [Tuple{}...] == [NTuple...] == [] @@ -220,6 +224,8 @@ end @test dropnothing(x for x ∈ a3_nothing) == dropnothing(a3_nothing) == [] @test ensure_vector(a3_nothing) isa AbstractVector{<:AbstractMatrix{Nothing}} @test flatten(rand(UInt8, 3, 3, 3)::Array{UInt8, 3}) isa Vector{UInt8} + @test freeze(Dict(1 => 2)) isa FrozenLittleDict{Int, Int} + @test freeze(Dict(1 => 2)) isa LDict{Int, Int} @test getfirst(iseven, 1:9) == getfirst(iseven)(1:9) == 2 @test getlast(iseven, 1:9) == getlast(iseven)(1:9) == 8 @test invsqrt(2^-2) == 2 @@ -255,6 +261,7 @@ end @test Tuple === Tuple{Vararg{Any}} === VTuple{Any} @test_throws ArgumentError notmissing(missing) @test_throws ArgumentError notnothing(nothing) + @test_throws MethodError freeze(Dict()) @test Bool(0) == Exts.isdir("") @test Bool(1) == Exts.isdir(".")