diff --git a/Project.toml b/Project.toml index 4badf8e..b4d1889 100644 --- a/Project.toml +++ b/Project.toml @@ -3,15 +3,18 @@ uuid = "8197267c-284f-5f27-9208-e0e47529a953" version = "0.7.8" [deps] -Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" [weakdeps] +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" [extensions] +IntervalSetsRandomExt = "Random" IntervalSetsStatisticsExt = "Statistics" +IntervalSetsStatsBaseExt = "StatsBase" [compat] Aqua = "0.7" @@ -20,11 +23,13 @@ julia = "1.6" [extras] Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" [targets] -test = ["Aqua", "Test", "Random", "OffsetArrays", "Statistics", "Unitful"] +test = ["Aqua", "Dates", "Test", "Random", "OffsetArrays", "StatsBase", "Statistics", "Unitful"] diff --git a/ext/IntervalSetsRandomExt.jl b/ext/IntervalSetsRandomExt.jl new file mode 100644 index 0000000..16c3d2f --- /dev/null +++ b/ext/IntervalSetsRandomExt.jl @@ -0,0 +1,17 @@ +module IntervalSetsRandomExt + +using IntervalSets +using IntervalSets: TypedEndpointsInterval +using Random + +# random sampling from interval +Random.gentype(::Type{Interval{L,R,T}}) where {L,R,T} = float(T) +function Random.rand(rng::AbstractRNG, i::Random.SamplerTrivial{<:TypedEndpointsInterval{:closed, :closed, T}}) where T<:Real + _i = i[] + isempty(_i) && throw(ArgumentError("The interval should be non-empty.")) + a,b = endpoints(_i) + t = rand(rng, float(T)) # technically this samples from [0, 1), but we still allow it with TypedEndpointsInterval{:closed, :closed} for convenience + return clamp(t*a+(1-t)*b, _i) +end + +end diff --git a/ext/IntervalSetsStatsBaseExt.jl b/ext/IntervalSetsStatsBaseExt.jl new file mode 100644 index 0000000..dda2400 --- /dev/null +++ b/ext/IntervalSetsStatsBaseExt.jl @@ -0,0 +1,8 @@ +module IntervalSetsStatsBaseExt + +using IntervalSets +using StatsBase + +StatsBase.geomean(d::AbstractInterval) = sqrt(leftendpoint(d) * rightendpoint(d)) + +end diff --git a/src/IntervalSets.jl b/src/IntervalSets.jl index 05ef38c..2e59285 100644 --- a/src/IntervalSets.jl +++ b/src/IntervalSets.jl @@ -4,10 +4,6 @@ using Base: @pure import Base: eltype, convert, show, in, length, isempty, isequal, isapprox, issubset, ==, hash, union, intersect, minimum, maximum, extrema, range, clamp, mod, float, ⊇, ⊊, ⊋ -using Random - -using Dates - export AbstractInterval, Interval, OpenInterval, ClosedInterval, ⊇, .., ±, ordered, width, leftendpoint, rightendpoint, endpoints, isopenset, isclosedset, isleftclosed, isrightclosed, @@ -283,6 +279,9 @@ include("findall.jl") if !isdefined(Base, :get_extension) include("../ext/IntervalSetsStatisticsExt.jl") + include("../ext/IntervalSetsRandomExt.jl") + # We don't support the extension with StatsBase.jl before Julia v1.9. + # include("../ext/IntervalSetsStatsBaseExt.jl") end end # module diff --git a/src/interval.jl b/src/interval.jl index 569d417..0496068 100644 --- a/src/interval.jl +++ b/src/interval.jl @@ -158,16 +158,6 @@ function _union(A::TypedEndpointsInterval{L1,R1}, B::TypedEndpointsInterval{L2,R Interval{L,R}(left, right) end -# random sampling from interval -Random.gentype(::Type{Interval{L,R,T}}) where {L,R,T} = float(T) -function Random.rand(rng::AbstractRNG, i::Random.SamplerTrivial{<:TypedEndpointsInterval{:closed, :closed, T}}) where T<:Real - _i = i[] - isempty(_i) && throw(ArgumentError("The interval should be non-empty.")) - a,b = endpoints(_i) - t = rand(rng, float(T)) # technically this samples from [0, 1), but we still allow it with TypedEndpointsInterval{:closed, :closed} for convenience - return clamp(t*a+(1-t)*b, _i) -end - ClosedInterval{T}(i::AbstractUnitRange{I}) where {T,I<:Integer} = ClosedInterval{T}(minimum(i), maximum(i)) ClosedInterval(i::AbstractUnitRange{I}) where {I<:Integer} = ClosedInterval{I}(minimum(i), maximum(i)) diff --git a/test/runtests.jl b/test/runtests.jl index f2db5c5..2f62f9a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,6 +1,7 @@ using IntervalSets using Test using Dates +using StatsBase: geomean using Statistics import Statistics: mean using Random @@ -136,6 +137,7 @@ struct IncompleteInterval <: AbstractInterval{Int} end @test width(ClosedInterval(4.0,8.0)) ≡ 4.0 @test mean(0..1) == 0.5 + VERSION ≥ v"1.9" && @test geomean(1..100) == 10 @test promote(1..2, 1.0..2.0) === (1.0..2.0, 1.0..2.0) end