Skip to content

Commit

Permalink
Fix tests and update with recent changes in Base
Browse files Browse the repository at this point in the history
  • Loading branch information
devmotion committed Oct 9, 2024
1 parent 872ace5 commit aafbfb2
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 80 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "IrrationalConstants"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
authors = ["JuliaMath"]
version = "0.2.2"
version = "0.2.3"

[compat]
julia = "1"
Expand Down
72 changes: 46 additions & 26 deletions src/macro.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,19 @@ if VERSION < v"1.2.0-DEV.337"
Base.inv(x::IrrationalConstant) = 1/x
end

# https://github.com/JuliaLang/julia/pull/50894
Base.typemin(::Type{T}) where {T<:IrrationalConstant} = T()
Base.typemax(::Type{T}) where {T<:IrrationalConstant} = T()

"""
@irrational sym val def [T]
@irrational(sym, val, def[, T])
@irrational sym [val] def [T]
Define an instance named `sym` of a new singleton type `T` representing an irrational constant as subtype of
`IrrationalConstants.IrrationalConstant <: AbstractIrrational`,
with arbitrary-precision definition in terms of `BigFloat`s given by the expression `def`.
Define a new singleton type `T` representing an irrational constant as subtype of
`IrrationalConstants.IrrationalConstant <: AbstractIrrational` with an instance named `sym`, pre-computed `Float64` value `val`,
and arbitrary-precision definition in terms of `BigFloat`s given by the expression `def`.
Optionally provide a pre-computed `Float64` value `val` which must equal `Float64(def)`.
It will be computed automatically if omitted.
As default, `T` is set to `sym` with the first character converted to uppercase.
Expand All @@ -49,30 +55,36 @@ returns `false`.
# Examples
```jldoctest
julia> IrrationalConstants.@irrational(twoπ, 6.2831853071795864769, 2*big(π))
```jldoctest; setup = :(import IrrationalConstants)
julia> IrrationalConstants.@irrational twoπ 2*big(π)
julia> twoπ
twoπ = 6.2831853071795...
julia> IrrationalConstants.@irrational sqrt2 1.4142135623730950488 √big(2)
julia> IrrationalConstants.@irrational sqrt2 1.4142135623730950488 √big(2)
julia> sqrt2
sqrt2 = 1.4142135623730...
julia> IrrationalConstants.@irrational halfτ 3.14159265358979323846 pi
julia> IrrationalConstants.@irrational halfτ 3.14159265358979323846 pi
julia> halfτ
halfτ = 3.1415926535897...
julia> IrrationalConstants.@irrational sqrt2 1.4142135623730950488 big(2)
ERROR: AssertionError: big($(Expr(:escape, :sqrt2))) isa BigFloat
julia> IrrationalConstants.@irrational sqrt3 1.7320508075688772 big(3)
ERROR: AssertionError: big($(Expr(:escape, :sqrt3))) isa BigFloat
julia> IrrationalConstants.@irrational sqrt2 1.41421356237309 √big(2)
ERROR: AssertionError: Float64($(Expr(:escape, :sqrt2))) == Float64(big($(Expr(:escape, :sqrt2))))
julia> IrrationalConstants.@irrational sqrt5 2.2360679775 √big(5)
ERROR: AssertionError: Float64($(Expr(:escape, :sqrt5))) == Float64(big($(Expr(:escape, :sqrt5))))
```
"""
macro irrational(sym, val, def, T=Symbol(uppercasefirst(string(sym))))
macro irrational(sym::Symbol, val::Float64, def::Union{Symbol,Expr}, T::Symbol=Symbol(uppercasefirst(string(sym))))
irrational(sym, val, def, T)
end
macro irrational(sym::Symbol, def::Union{Symbol,Expr}, T::Symbol=Symbol(uppercasefirst(string(sym))))
irrational(sym, :(big($(esc(sym)))), def, T)
end
function irrational(sym::Symbol, val::Union{Float64,Expr}, def::Union{Symbol,Expr}, T::Symbol)
esym = esc(sym)
qsym = esc(Expr(:quote, sym))
eT = esc(T)
Expand All @@ -90,17 +102,23 @@ macro irrational(sym, val, def, T=Symbol(uppercasefirst(string(sym))))
end
else
# newer Julia versions
isa(def, Symbol) ? quote
function Base.BigFloat(::$eT, r::Base.MPFR.MPFRRoundingMode=Base.MPFR.ROUNDING_MODE[]; precision=precision(BigFloat))
c = BigFloat(; precision=precision)
ccall(($(string("mpfr_const_", def)), :libmpfr),
Cint, (Ref{BigFloat}, Base.MPFR.MPFRRoundingMode), c, r)
return c
if isa(def, Symbol)
# support older Julia versions prior to https://github.com/JuliaLang/julia/pull/51362
r = VERSION < v"1.12.0-DEV.78" ? :(Base.MPFR.ROUNDING_MODE[]) : :(Rounding.rounding_raw(BigFloat))
quote
function Base.BigFloat(::$eT, r::Base.MPFR.MPFRRoundingMode=$r; precision=precision(BigFloat))
c = BigFloat(; precision=precision)
ccall(($(string("mpfr_const_", def)), :libmpfr),
Cint, (Ref{BigFloat}, Base.MPFR.MPFRRoundingMode), c, r)
return c
end
end
end : quote
function Base.BigFloat(::$eT; precision=precision(BigFloat))
setprecision(BigFloat, precision) do
$(esc(def))
else
quote
function Base.BigFloat(::$eT; precision=precision(BigFloat))
setprecision(BigFloat, precision) do
$(esc(def))
end
end
end
end
Expand All @@ -109,8 +127,10 @@ macro irrational(sym, val, def, T=Symbol(uppercasefirst(string(sym))))
struct $T <: IrrationalConstant end
const $esym = $eT()
$bigconvert
Base.Float64(::$eT) = $val
Base.Float32(::$eT) = $(Float32(val))
let v = $val, v64 = Float64(v), v32 = Float32(v)
Base.Float64(::$eT) = v64
Base.Float32(::$eT) = v32
end
Base.show(io::IO, ::$eT) = print(io, $qsym)
@assert isa(big($esym), BigFloat)
@assert Float64($esym) == Float64(big($esym))
Expand Down
48 changes: 24 additions & 24 deletions src/stats.jl
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
# mathematical constants related to statistics

@irrational twoπ 6.2831853071795864769 2 * big(π)
@irrational fourπ 12.566370614359172954 4 * big(π)
@irrational halfπ 1.5707963267948966192 big(π) / 2
@irrational quartπ 0.7853981633974483096 big(π) / 4
@irrational twoπ 2 * big(π)
@irrational fourπ 4 * big(π)
@irrational halfπ big(π) / 2
@irrational quartπ big(π) / 4

@irrational invπ 0.31830988618379067154 inv(big(π))
@irrational twoinvπ 0.63661977236758134308 2 / big(π)
@irrational fourinvπ 1.27323954473516268615 4 / big(π)
@irrational inv2π 0.159154943091895335769 inv(2 * big(π))
@irrational inv4π 0.079577471545947667884 inv(4 * big(π))
@irrational invπ inv(big(π))
@irrational twoinvπ 2 / big(π)
@irrational fourinvπ 4 / big(π)
@irrational inv2π inv(2 * big(π))
@irrational inv4π inv(4 * big(π))

@irrational sqrt2 1.4142135623730950488 sqrt(big(2))
@irrational sqrt3 1.7320508075688772935 sqrt(big(3))
@irrational sqrtπ 1.7724538509055160273 sqrt(big(π))
@irrational sqrt2π 2.5066282746310005024 sqrt(2 * big(π))
@irrational sqrt4π 3.5449077018110320546 sqrt(4 * big(π))
@irrational sqrthalfπ 1.2533141373155002512 sqrt(big(π) / 2)
@irrational sqrt2 sqrt(big(2))
@irrational sqrt3 sqrt(big(3))
@irrational sqrtπ sqrt(big(π))
@irrational sqrt2π sqrt(2 * big(π))
@irrational sqrt4π sqrt(4 * big(π))
@irrational sqrthalfπ sqrt(big(π) / 2)

@irrational invsqrt2 0.7071067811865475244 inv(sqrt(big(2)))
@irrational invsqrtπ 0.5641895835477563 inv(sqrt(big(π)))
@irrational invsqrt2π 0.3989422804014326779 inv(sqrt(2 * big(π)))
@irrational invsqrt2 inv(sqrt(big(2)))
@irrational invsqrtπ inv(sqrt(big(π)))
@irrational invsqrt2π inv(sqrt(2 * big(π)))

@irrational loghalf -0.6931471805599453094 log(inv(big(2)))
@irrational logtwo 0.6931471805599453094 log2
@irrational logten 2.302585092994046 log(big(10))
@irrational logπ 1.1447298858494001741 log(big(π))
@irrational log2π 1.8378770664093454836 log(2 * big(π))
@irrational log4π 2.5310242469692907930 log(4 * big(π))
@irrational loghalf log(inv(big(2)))
@irrational logtwo log2
@irrational logten log(big(10))
@irrational logπ log(big(π))
@irrational log2π log(2 * big(π))
@irrational log4π log(4 * big(π))
129 changes: 100 additions & 29 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ using IrrationalConstants
using Documenter
using Test

const ALLCONSTANTS = filter!(
x -> x isa IrrationalConstants.IrrationalConstant,
map(Base.Fix1(getproperty, IrrationalConstants), names(IrrationalConstants)),
)

@testset "k*pi" begin
@test isapprox(2*pi, twoπ)
@test isapprox(4*pi, fourπ)
Expand Down Expand Up @@ -48,30 +53,47 @@ end
end

@testset "hash" begin
for i in (twoπ, invπ, sqrt2, logtwo), j in (twoπ, invπ, sqrt2, logtwo)
for i in ALLCONSTANTS, j in ALLCONSTANTS
@test isequal(i==j, hash(i)==hash(j))
end
end

@testset "doctests" begin
DocMeta.setdocmeta!(
IrrationalConstants, :DocTestSetup, :(using IrrationalConstants); recursive=true
)
doctest(IrrationalConstants; manual=false)
end

# copied from https://github.com/JuliaLang/julia/blob/cf5ae0369ceae078cf6a29d7aa34f48a5a53531e/test/numbers.jl
# and adapted to irrationals in this package

@testset "IrrationalConstant zero and one" begin
@test one(twoπ) === true
@test zero(twoπ) === false
@test one(typeof(twoπ)) === true
@test zero(typeof(twoπ)) === false
@testset "IrrationalConstants zero and one" begin
for i in ALLCONSTANTS
@test one(i) === true
@test zero(i) === false
@test one(typeof(i)) === true
@test zero(typeof(i)) === false
end
end

@testset "IrrationalConstants iszero, isfinite, isinteger, and isone" begin
for i in ALLCONSTANTS
@test !iszero(i)
@test !isone(i)
@test !isinteger(i)
@test isfinite(i)
end
end

@testset "IrrationalConstants promote_type" begin
for T in (Float16, Float32, Float64)
for i in ALLCONSTANTS
@test T(2.0) * i T(2.0) * T(i)
@test T(2.0) * i isa T
end
end
end

@testset "IrrationalConstants compared with IrrationalConstants" begin
for i in (twoπ, invπ, sqrt2, logtwo), j in (twoπ, invπ, sqrt2, logtwo)
for i in ALLCONSTANTS, j in ALLCONSTANTS
@test isequal(i==j, Float64(i)==Float64(j))
@test isequal(i!=j, Float64(i)!=Float64(j))
@test isequal(i<=j, Float64(i)<=Float64(j))
Expand All @@ -81,29 +103,31 @@ end
end
end

@testset "IrrationalConstant Inverses, JuliaLang/Julia Issue #30882" begin
@testset "IrrationalConstants Inverses, JuliaLang/Julia Issue #30882" begin
@test @inferred(inv(twoπ)) 0.15915494309189535
end

@testset "IrrationalConstants compared with Rationals and Floats" begin
@test Float64(twoπ, RoundDown) < twoπ
@test Float64(twoπ, RoundUp) > twoπ
@test !(Float64(twoπ, RoundDown) > twoπ)
@test !(Float64(twoπ, RoundUp) < twoπ)
@test Float64(twoπ, RoundDown) <= twoπ
@test Float64(twoπ, RoundUp) >= twoπ
@test Float64(twoπ, RoundDown) != twoπ
@test Float64(twoπ, RoundUp) != twoπ

@test Float32(twoπ, RoundDown) < twoπ
@test Float32(twoπ, RoundUp) > twoπ
@test !(Float32(twoπ, RoundDown) > twoπ)
@test !(Float32(twoπ, RoundUp) < twoπ)

@test prevfloat(big(twoπ)) < twoπ
@test nextfloat(big(twoπ)) > twoπ
@test !(prevfloat(big(twoπ)) > twoπ)
@test !(nextfloat(big(twoπ)) < twoπ)
for i in ALLCONSTANTS
@test Float64(i, RoundDown) < i
@test Float64(i, RoundUp) > i
@test !(Float64(i, RoundDown) > i)
@test !(Float64(i, RoundUp) < i)
@test Float64(i, RoundDown) <= i
@test Float64(i, RoundUp) >= i
@test Float64(i, RoundDown) != i
@test Float64(i, RoundUp) != i

@test Float32(i, RoundDown) < i
@test Float32(i, RoundUp) > i
@test !(Float32(i, RoundDown) > i)
@test !(Float32(i, RoundUp) < i)

@test prevfloat(big(i)) < i
@test nextfloat(big(i)) > i
@test !(prevfloat(big(i)) > i)
@test !(nextfloat(big(i)) < i)
end

@test 5293386250278608690//842468587426513207 < twoπ
@test !(5293386250278608690//842468587426513207 > twoπ)
Expand Down Expand Up @@ -181,3 +205,50 @@ end
@test sec(quartπ) === Float64(sec(big(quartπ)))
@test cot(quartπ) === Float64(cot(big(quartπ)))
end

# Ref https://github.com/JuliaLang/julia/pull/46054
IrrationalConstants.@irrational irrational_1548_pi 4863.185427757 1548big(pi)
IrrationalConstants.@irrational irrational_inv_1548_pi 1/big(irrational_1548_pi)
@testset "IrrationalConstants.@irrational" begin
@test irrational_1548_pi 1548big(pi)
@test Float64(irrational_1548_pi) == 1548π
@test irrational_1548_pi 1548pi
@test irrational_1548_pi != 1548pi
@test irrational_inv_1548_pi inv(1548big(pi))
@test Float64(irrational_inv_1548_pi) == 1/(1548π)
@test irrational_inv_1548_pi inv(1548pi)
@test irrational_inv_1548_pi != inv(1548pi)
end

# Ref https://github.com/JuliaLang/julia/pull/50894
@testset "irrational special values" begin
for v ALLCONSTANTS
@test v === typemin(v) === typemax(v)
end
end

# Ref https://github.com/JuliaLang/julia/pull/55911
@testset "logtwo to `BigFloat` with `setrounding`" begin
function irrational_to_big_float(c::AbstractIrrational)
BigFloat(c)
end

function irrational_to_big_float_with_rounding_mode(c::AbstractIrrational, rm::RoundingMode)
f = () -> irrational_to_big_float(c)
setrounding(f, BigFloat, rm)
end

function irrational_to_big_float_with_rounding_mode_and_precision(c::AbstractIrrational, rm::RoundingMode, prec::Int)
f = () -> irrational_to_big_float_with_rounding_mode(c, rm)
setprecision(f, BigFloat, prec)
end

# logtwo is the only constant defined based on an MPFR constant (similar to π, γ, catalan)
c = logtwo
for p 1:40
@test (
irrational_to_big_float_with_rounding_mode_and_precision(c, RoundDown, p) < c <
irrational_to_big_float_with_rounding_mode_and_precision(c, RoundUp, p)
)
end
end

0 comments on commit aafbfb2

Please sign in to comment.