From 508f058f1f71046d7dbd457367643267213f16e3 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Sun, 24 Apr 2022 18:07:28 +0900 Subject: [PATCH 01/16] add rules for Irrational --- src/IrrationalConstants.jl | 1 + src/rules.jl | 45 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/rules.jl diff --git a/src/IrrationalConstants.jl b/src/IrrationalConstants.jl index e9c2b27..79a20ba 100644 --- a/src/IrrationalConstants.jl +++ b/src/IrrationalConstants.jl @@ -29,5 +29,6 @@ export log4π # log(4π) include("stats.jl") +include("rules.jl") end # module diff --git a/src/rules.jl b/src/rules.jl new file mode 100644 index 0000000..3a1250f --- /dev/null +++ b/src/rules.jl @@ -0,0 +1,45 @@ +## Multiplication +Base.:*(::Irrational{:sqrt2}, ::Irrational{:sqrt2}) = 2.0 +Base.:*(::Irrational{:sqrt3}, ::Irrational{:sqrt3}) = 3.0 +Base.:*(::Irrational{:sqrtπ}, ::Irrational{:sqrtπ}) = π +Base.:*(::Irrational{:sqrt2π}, ::Irrational{:sqrt2π}) = twoπ +Base.:*(::Irrational{:sqrt4π}, ::Irrational{:sqrt4π}) = fourπ +Base.:*(::Irrational{:sqrt4π}, ::Irrational{:sqrt4π}) = fourπ + +## Inverse +Base.inv(::Irrational{:invπ}) = π +Base.inv(::Irrational{:twoinvπ}) = halfπ +# Base.inv(::Irrational{:fourinvπ}) = π/4 # This is not necessary because the return value will be approximated floating-point number. +Base.inv(::Irrational{:inv2π}) = twoπ +Base.inv(::Irrational{:inv4π}) = fourπ +Base.inv(::Irrational{:invsqrt2}) = sqrt2 +Base.inv(::Irrational{:invsqrtπ}) = sqrtπ +Base.inv(::Irrational{:invsqrt2π}) = sqrt2π +# Base.inv(::Irrational{:π}) = invπ # Avoid type piracy +Base.inv(::Irrational{:twoπ}) = inv2π +Base.inv(::Irrational{:halfπ}) = twoinvπ +Base.inv(::Irrational{:fourπ}) = inv4π +Base.inv(::Irrational{:sqrt2}) = invsqrt2 +Base.inv(::Irrational{:sqrtπ}) = sqrtπ +Base.inv(::Irrational{:sqrt2π}) = sqrt2π + +## Triangular +Base.sin(::Irrational{:twoπ}) = 0.0 +Base.cos(::Irrational{:twoπ}) = 1.0 +Base.sincos(::Irrational{:twoπ}) = (0.0, 1.0) +Base.sin(::Irrational{:fourπ}) = 0.0 +Base.cos(::Irrational{:fourπ}) = 1.0 +Base.sincos(::Irrational{:fourπ}) = (0.0, 1.0) + +## Exponential +Base.exp(::Irrational{:loghalf}) = 0.5 +Base.exp(::Irrational{:logtwo}) = 2.0 +Base.exp(::Irrational{:logten}) = 10.0 +Base.exp(::Irrational{:logπ}) = π +Base.exp(::Irrational{:log2π}) = twoπ +Base.exp(::Irrational{:log4π}) = fourπ + +## Logarithm +# Base.log(::Irrational{:π}) = logπ # Avoid type piracy +Base.log(::Irrational{:twoπ}) = log2π +Base.log(::Irrational{:fourπ}) = log4π From 018fe5f5f9107945ea132f8dfac484b1d0408b1e Mon Sep 17 00:00:00 2001 From: hyrodium Date: Sun, 24 Apr 2022 20:41:26 +0900 Subject: [PATCH 02/16] add more rules --- src/rules.jl | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/rules.jl b/src/rules.jl index 3a1250f..92cc845 100644 --- a/src/rules.jl +++ b/src/rules.jl @@ -1,27 +1,31 @@ -## Multiplication +## Square Base.:*(::Irrational{:sqrt2}, ::Irrational{:sqrt2}) = 2.0 Base.:*(::Irrational{:sqrt3}, ::Irrational{:sqrt3}) = 3.0 Base.:*(::Irrational{:sqrtπ}, ::Irrational{:sqrtπ}) = π Base.:*(::Irrational{:sqrt2π}, ::Irrational{:sqrt2π}) = twoπ Base.:*(::Irrational{:sqrt4π}, ::Irrational{:sqrt4π}) = fourπ -Base.:*(::Irrational{:sqrt4π}, ::Irrational{:sqrt4π}) = fourπ +Base.:*(::Irrational{:sqrthalfπ}, ::Irrational{:sqrthalfπ}) = halfπ +Base.:*(::Irrational{:invsqrt2}, ::Irrational{:invsqrt2}) = 0.5 +Base.:*(::Irrational{:invsqrtπ}, ::Irrational{:invsqrtπ}) = invπ +Base.:*(::Irrational{:invsqrt2π}, ::Irrational{:invsqrt2π}) = inv2π ## Inverse -Base.inv(::Irrational{:invπ}) = π -Base.inv(::Irrational{:twoinvπ}) = halfπ -# Base.inv(::Irrational{:fourinvπ}) = π/4 # This is not necessary because the return value will be approximated floating-point number. -Base.inv(::Irrational{:inv2π}) = twoπ -Base.inv(::Irrational{:inv4π}) = fourπ -Base.inv(::Irrational{:invsqrt2}) = sqrt2 -Base.inv(::Irrational{:invsqrtπ}) = sqrtπ -Base.inv(::Irrational{:invsqrt2π}) = sqrt2π # Base.inv(::Irrational{:π}) = invπ # Avoid type piracy +Base.inv(::Irrational{:invπ}) = π Base.inv(::Irrational{:twoπ}) = inv2π +Base.inv(::Irrational{:inv2π}) = twoπ +Base.inv(::Irrational{:twoinvπ}) = halfπ Base.inv(::Irrational{:halfπ}) = twoinvπ +Base.inv(::Irrational{:quartπ}) = fourinvπ +Base.inv(::Irrational{:fourinvπ}) = quartπ Base.inv(::Irrational{:fourπ}) = inv4π +Base.inv(::Irrational{:inv4π}) = fourπ +Base.inv(::Irrational{:sqrt2π}) = invsqrt2π +Base.inv(::Irrational{:invsqrt2π}) = sqrt2π Base.inv(::Irrational{:sqrt2}) = invsqrt2 -Base.inv(::Irrational{:sqrtπ}) = sqrtπ -Base.inv(::Irrational{:sqrt2π}) = sqrt2π +Base.inv(::Irrational{:invsqrt2}) = sqrt2 +Base.inv(::Irrational{:sqrtπ}) = invsqrtπ +Base.inv(::Irrational{:invsqrtπ}) = sqrtπ ## Triangular Base.sin(::Irrational{:twoπ}) = 0.0 @@ -30,6 +34,9 @@ Base.sincos(::Irrational{:twoπ}) = (0.0, 1.0) Base.sin(::Irrational{:fourπ}) = 0.0 Base.cos(::Irrational{:fourπ}) = 1.0 Base.sincos(::Irrational{:fourπ}) = (0.0, 1.0) +Base.sin(::Irrational{:quartπ}) = invsqrt2 +Base.cos(::Irrational{:quartπ}) = invsqrt2 +Base.sincos(::Irrational{:quartπ}) = (invsqrt2, invsqrt2) ## Exponential Base.exp(::Irrational{:loghalf}) = 0.5 From 88f59bfcaa0ae4295e80fcfcf5d7ca79ba7a8880 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Sun, 24 Apr 2022 20:44:05 +0900 Subject: [PATCH 03/16] organize testset --- test/runtests.jl | 69 ++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 0bab199..d95e646 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,42 +1,43 @@ using IrrationalConstants using Test -@testset "k*pi" begin - @test isapprox(2*pi, twoπ) - @test isapprox(4*pi, fourπ) - @test isapprox(pi/2, halfπ) - @test isapprox(pi/4, quartπ) -end +@testset "approximately equal" begin + @testset "k*pi" begin + @test isapprox(2*pi, twoπ) + @test isapprox(4*pi, fourπ) + @test isapprox(pi/2, halfπ) + @test isapprox(pi/4, quartπ) + end -@testset "k/pi" begin - @test isapprox(1/pi, invπ) - @test isapprox(2/pi, twoinvπ) - @test isapprox(4/pi, fourinvπ) -end + @testset "k/pi" begin + @test isapprox(1/pi, invπ) + @test isapprox(2/pi, twoinvπ) + @test isapprox(4/pi, fourinvπ) + end -@testset "1/(k*pi)" begin - @test isapprox(1/(2pi), inv2π) - @test isapprox(1/(4pi), inv4π) -end + @testset "1/(k*pi)" begin + @test isapprox(1/(2pi), inv2π) + @test isapprox(1/(4pi), inv4π) + end -@testset "sqrt" begin - @test isapprox(sqrt(2), sqrt2) - @test isapprox(sqrt(3), sqrt3) - @test isapprox(sqrt(pi), sqrtπ) - @test isapprox(sqrt(2pi), sqrt2π) - @test isapprox(sqrt(4pi), sqrt4π) - @test isapprox(sqrt(pi/2), sqrthalfπ) - @test isapprox(sqrt(1/2), invsqrt2) - @test isapprox(sqrt(1/(pi)), invsqrtπ) - @test isapprox(sqrt(1/(2pi)), invsqrt2π) -end + @testset "sqrt" begin + @test isapprox(sqrt(2), sqrt2) + @test isapprox(sqrt(3), sqrt3) + @test isapprox(sqrt(pi), sqrtπ) + @test isapprox(sqrt(2pi), sqrt2π) + @test isapprox(sqrt(4pi), sqrt4π) + @test isapprox(sqrt(pi/2), sqrthalfπ) + @test isapprox(sqrt(1/2), invsqrt2) + @test isapprox(sqrt(1/(pi)), invsqrtπ) + @test isapprox(sqrt(1/(2pi)), invsqrt2π) + end -@testset "log" begin - @test isapprox(log(1/2), loghalf) - @test isapprox(log(2), logtwo) - @test isapprox(log(10), logten) - @test isapprox(log(pi), logπ) - @test isapprox(log(2pi), log2π) - @test isapprox(log(4pi), log4π) + @testset "log" begin + @test isapprox(log(1/2), loghalf) + @test isapprox(log(2), logtwo) + @test isapprox(log(10), logten) + @test isapprox(log(pi), logπ) + @test isapprox(log(2pi), log2π) + @test isapprox(log(4pi), log4π) + end end - From 62ac1e30ccc08460bfc47ee634650825ff360625 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Sun, 24 Apr 2022 20:48:33 +0900 Subject: [PATCH 04/16] add tests for rules --- test/runtests.jl | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index d95e646..05ababf 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,6 +1,38 @@ using IrrationalConstants using Test +const IRRATIONALS = ( + twoπ, + fourπ, + halfπ, + quartπ, + invπ, + twoinvπ, + fourinvπ, + inv2π, + inv4π, + sqrt2, + sqrt3, + sqrtπ, + sqrt2π, + sqrt4π, + sqrthalfπ, + invsqrt2, + invsqrtπ, + invsqrt2π, + loghalf, + logtwo, + logten, + logπ, + log2π, + log4π, +) + +function test_with_function(f, a::Irrational) + @test f(a) ≈ f(float(a)) atol=1e-14 + @test (f(a) .≈ IRRATIONALS) == (f(a) .=== IRRATIONALS) +end + @testset "approximately equal" begin @testset "k*pi" begin @test isapprox(2*pi, twoπ) @@ -41,3 +73,29 @@ using Test @test isapprox(log(4pi), log4π) end end + +@testset "rules for $(a)" for a in IRRATIONALS + @testset "log" begin + if a > 0 + test_with_function(log, a) + end + end + + @testset "inv" begin + test_with_function(inv, a) + end + + @testset "exp" begin + test_with_function(exp, a) + end + + @testset "sin" begin + test_with_function(sin, a) + test_with_function(cos, a) + @test sincos(a) == (sin(a),cos(a)) + end + + @testset "square" begin + test_with_function(t->t*t, a) + end +end From c633fda85d4e3fc1c7a41949c00955497a751697 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Sun, 24 Apr 2022 21:12:21 +0900 Subject: [PATCH 05/16] update test_with_function --- test/runtests.jl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 05ababf..65dea39 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -29,8 +29,16 @@ const IRRATIONALS = ( ) function test_with_function(f, a::Irrational) - @test f(a) ≈ f(float(a)) atol=1e-14 - @test (f(a) .≈ IRRATIONALS) == (f(a) .=== IRRATIONALS) + b = f(a) + @test b ≈ f(float(a)) atol=1e-14 + + # If f(a) is approximately equal to a value in IRRATIONALS, f(a) should be Irrational. + @test (b .≈ IRRATIONALS) == (b .=== IRRATIONALS) + + # If f(a) is close to integer, it should be a integer. + if abs(b - round(b)) < 1e-14 + @test isinteger(b) + end end @testset "approximately equal" begin From d69df0455184a87f65c57fe8beda522dfa084211 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Sun, 24 Apr 2022 21:13:28 +0900 Subject: [PATCH 06/16] =?UTF-8?q?add=20rule=20for=20Base.sin(::Irrational{?= =?UTF-8?q?:half=CF=80})?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/rules.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rules.jl b/src/rules.jl index 92cc845..dc01ccf 100644 --- a/src/rules.jl +++ b/src/rules.jl @@ -37,6 +37,7 @@ Base.sincos(::Irrational{:fourπ}) = (0.0, 1.0) Base.sin(::Irrational{:quartπ}) = invsqrt2 Base.cos(::Irrational{:quartπ}) = invsqrt2 Base.sincos(::Irrational{:quartπ}) = (invsqrt2, invsqrt2) +Base.sin(::Irrational{:halfπ}) = 1.0 ## Exponential Base.exp(::Irrational{:loghalf}) = 0.5 From 81f4e20ad9738aeadbdae2f50cb3048b25ddefaa Mon Sep 17 00:00:00 2001 From: hyrodium Date: Sun, 24 Apr 2022 21:16:55 +0900 Subject: [PATCH 07/16] add more rules for triangular funcitons --- src/rules.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rules.jl b/src/rules.jl index dc01ccf..0fb38db 100644 --- a/src/rules.jl +++ b/src/rules.jl @@ -38,6 +38,8 @@ Base.sin(::Irrational{:quartπ}) = invsqrt2 Base.cos(::Irrational{:quartπ}) = invsqrt2 Base.sincos(::Irrational{:quartπ}) = (invsqrt2, invsqrt2) Base.sin(::Irrational{:halfπ}) = 1.0 +Base.cos(::Irrational{:halfπ}) = 0.0 +Base.sincos(::Irrational{:halfπ}) = (1.0, 0.0) ## Exponential Base.exp(::Irrational{:loghalf}) = 0.5 From 7b2e6f75b0718fd22343ec338dc6fba1862bbf51 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Sun, 24 Apr 2022 21:37:15 +0900 Subject: [PATCH 08/16] update rule definitions --- src/rules.jl | 59 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/src/rules.jl b/src/rules.jl index 0fb38db..39ff125 100644 --- a/src/rules.jl +++ b/src/rules.jl @@ -1,31 +1,40 @@ ## Square -Base.:*(::Irrational{:sqrt2}, ::Irrational{:sqrt2}) = 2.0 -Base.:*(::Irrational{:sqrt3}, ::Irrational{:sqrt3}) = 3.0 -Base.:*(::Irrational{:sqrtπ}, ::Irrational{:sqrtπ}) = π -Base.:*(::Irrational{:sqrt2π}, ::Irrational{:sqrt2π}) = twoπ -Base.:*(::Irrational{:sqrt4π}, ::Irrational{:sqrt4π}) = fourπ -Base.:*(::Irrational{:sqrthalfπ}, ::Irrational{:sqrthalfπ}) = halfπ -Base.:*(::Irrational{:invsqrt2}, ::Irrational{:invsqrt2}) = 0.5 -Base.:*(::Irrational{:invsqrtπ}, ::Irrational{:invsqrtπ}) = invπ -Base.:*(::Irrational{:invsqrt2π}, ::Irrational{:invsqrt2π}) = inv2π +SQUARE_PAIR = ( + (sqrt2, 2.0), + (sqrt3, 3.0), + (sqrtπ, π), + (sqrt2π, twoπ), + (sqrt4π, fourπ), + (sqrthalfπ, halfπ), + (invsqrt2, 0.5), + (invsqrtπ, invπ), + (invsqrt2π, inv2π), +) +for (a,b) in SQUARE_PAIR + Base.:(*)(::typeof(a), ::typeof(a)) = b + Base.literal_pow(::typeof(^), ::typeof(a), ::Val{2}) = b +end ## Inverse -# Base.inv(::Irrational{:π}) = invπ # Avoid type piracy -Base.inv(::Irrational{:invπ}) = π -Base.inv(::Irrational{:twoπ}) = inv2π -Base.inv(::Irrational{:inv2π}) = twoπ -Base.inv(::Irrational{:twoinvπ}) = halfπ -Base.inv(::Irrational{:halfπ}) = twoinvπ -Base.inv(::Irrational{:quartπ}) = fourinvπ -Base.inv(::Irrational{:fourinvπ}) = quartπ -Base.inv(::Irrational{:fourπ}) = inv4π -Base.inv(::Irrational{:inv4π}) = fourπ -Base.inv(::Irrational{:sqrt2π}) = invsqrt2π -Base.inv(::Irrational{:invsqrt2π}) = sqrt2π -Base.inv(::Irrational{:sqrt2}) = invsqrt2 -Base.inv(::Irrational{:invsqrt2}) = sqrt2 -Base.inv(::Irrational{:sqrtπ}) = invsqrtπ -Base.inv(::Irrational{:invsqrtπ}) = sqrtπ +INVERSE_PAIR = ( + (π, invπ), + (twoπ, inv2π), + (twoinvπ, halfπ), + (quartπ, fourinvπ), + (fourπ, inv4π), + (sqrt2π, invsqrt2π), + (sqrt2, invsqrt2), + (sqrtπ, invsqrtπ), +) +for (a,b) in INVERSE_PAIR + if a !== π # Avoid type piracy + Base.inv(::typeof(a)) = b + Base.literal_pow(::typeof(^), ::typeof(a), ::Val{-1}) = b + end + Base.inv(::typeof(b)) = a + Base.literal_pow(::typeof(^), ::typeof(b), ::Val{-1}) = a + Base.:(*)(::typeof(a), ::typeof(b)) = one(Irrational) +end ## Triangular Base.sin(::Irrational{:twoπ}) = 0.0 From 47e0808f40105f775fe6f1a1b6a0cf33b6b3348e Mon Sep 17 00:00:00 2001 From: hyrodium Date: Sun, 24 Apr 2022 21:40:12 +0900 Subject: [PATCH 09/16] add more tests --- test/runtests.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index 65dea39..49e0b33 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -86,11 +86,14 @@ end @testset "log" begin if a > 0 test_with_function(log, a) + else + @test_throws DomainError log(a) end end @testset "inv" begin test_with_function(inv, a) + test_with_function(t->t^-1, a) end @testset "exp" begin @@ -105,5 +108,7 @@ end @testset "square" begin test_with_function(t->t*t, a) + test_with_function(abs2, a) + test_with_function(t->t^2, a) end end From 693ae6a016cf6ec733b2158f578f903f5734fa85 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Sun, 24 Apr 2022 21:40:54 +0900 Subject: [PATCH 10/16] update variable names --- src/rules.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rules.jl b/src/rules.jl index 39ff125..bb20c30 100644 --- a/src/rules.jl +++ b/src/rules.jl @@ -1,5 +1,5 @@ ## Square -SQUARE_PAIR = ( +SQUARE_PAIRS = ( (sqrt2, 2.0), (sqrt3, 3.0), (sqrtπ, π), @@ -10,13 +10,13 @@ SQUARE_PAIR = ( (invsqrtπ, invπ), (invsqrt2π, inv2π), ) -for (a,b) in SQUARE_PAIR +for (a,b) in SQUARE_PAIRS Base.:(*)(::typeof(a), ::typeof(a)) = b Base.literal_pow(::typeof(^), ::typeof(a), ::Val{2}) = b end ## Inverse -INVERSE_PAIR = ( +INVERSE_PAIRS = ( (π, invπ), (twoπ, inv2π), (twoinvπ, halfπ), @@ -26,7 +26,7 @@ INVERSE_PAIR = ( (sqrt2, invsqrt2), (sqrtπ, invsqrtπ), ) -for (a,b) in INVERSE_PAIR +for (a,b) in INVERSE_PAIRS if a !== π # Avoid type piracy Base.inv(::typeof(a)) = b Base.literal_pow(::typeof(^), ::typeof(a), ::Val{-1}) = b From f623abdd7a28dabaf719a85a100ad1d4f0994e57 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Thu, 28 Apr 2022 22:11:44 +0900 Subject: [PATCH 11/16] use let blocks --- src/rules.jl | 64 +++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/src/rules.jl b/src/rules.jl index bb20c30..c315abd 100644 --- a/src/rules.jl +++ b/src/rules.jl @@ -1,39 +1,41 @@ ## Square -SQUARE_PAIRS = ( - (sqrt2, 2.0), - (sqrt3, 3.0), - (sqrtπ, π), - (sqrt2π, twoπ), - (sqrt4π, fourπ), - (sqrthalfπ, halfπ), - (invsqrt2, 0.5), - (invsqrtπ, invπ), - (invsqrt2π, inv2π), -) -for (a,b) in SQUARE_PAIRS - Base.:(*)(::typeof(a), ::typeof(a)) = b - Base.literal_pow(::typeof(^), ::typeof(a), ::Val{2}) = b +let SQUARE_PAIRS = ( + (sqrt2, 2.0), + (sqrt3, 3.0), + (sqrtπ, π), + (sqrt2π, twoπ), + (sqrt4π, fourπ), + (sqrthalfπ, halfπ), + (invsqrt2, 0.5), + (invsqrtπ, invπ), + (invsqrt2π, inv2π), + ) + for (a,b) in SQUARE_PAIRS + Base.:(*)(::typeof(a), ::typeof(a)) = b + Base.literal_pow(::typeof(^), ::typeof(a), ::Val{2}) = b + end end ## Inverse -INVERSE_PAIRS = ( - (π, invπ), - (twoπ, inv2π), - (twoinvπ, halfπ), - (quartπ, fourinvπ), - (fourπ, inv4π), - (sqrt2π, invsqrt2π), - (sqrt2, invsqrt2), - (sqrtπ, invsqrtπ), -) -for (a,b) in INVERSE_PAIRS - if a !== π # Avoid type piracy - Base.inv(::typeof(a)) = b - Base.literal_pow(::typeof(^), ::typeof(a), ::Val{-1}) = b +let INVERSE_PAIRS = ( + (π, invπ), + (twoπ, inv2π), + (twoinvπ, halfπ), + (quartπ, fourinvπ), + (fourπ, inv4π), + (sqrt2π, invsqrt2π), + (sqrt2, invsqrt2), + (sqrtπ, invsqrtπ), + ) + for (a,b) in INVERSE_PAIRS + if a !== π # Avoid type piracy + Base.inv(::typeof(a)) = b + Base.literal_pow(::typeof(^), ::typeof(a), ::Val{-1}) = b + end + Base.inv(::typeof(b)) = a + Base.literal_pow(::typeof(^), ::typeof(b), ::Val{-1}) = a + Base.:(*)(::typeof(a), ::typeof(b)) = one(Irrational) end - Base.inv(::typeof(b)) = a - Base.literal_pow(::typeof(^), ::typeof(b), ::Val{-1}) = a - Base.:(*)(::typeof(a), ::typeof(b)) = one(Irrational) end ## Triangular From b0a9e46799a722d093f05840cacb630c8ce90fb4 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Thu, 28 Apr 2022 22:16:28 +0900 Subject: [PATCH 12/16] update testset names --- test/runtests.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 49e0b33..ab4d009 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -83,7 +83,7 @@ end end @testset "rules for $(a)" for a in IRRATIONALS - @testset "log" begin + @testset "Logarithm" begin if a > 0 test_with_function(log, a) else @@ -91,22 +91,22 @@ end end end - @testset "inv" begin + @testset "Inverse" begin test_with_function(inv, a) test_with_function(t->t^-1, a) end - @testset "exp" begin + @testset "Exponential" begin test_with_function(exp, a) end - @testset "sin" begin + @testset "Triangular" begin test_with_function(sin, a) test_with_function(cos, a) @test sincos(a) == (sin(a),cos(a)) end - @testset "square" begin + @testset "Square" begin test_with_function(t->t*t, a) test_with_function(abs2, a) test_with_function(t->t^2, a) From 1db0ac973b4bd38e877d770b063aa535dc24131c Mon Sep 17 00:00:00 2001 From: hyrodium Date: Thu, 28 Apr 2022 22:41:48 +0900 Subject: [PATCH 13/16] enforce the output type with Float64 --- src/rules.jl | 31 ++++++++++++++++--------------- test/runtests.jl | 6 ++++-- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/rules.jl b/src/rules.jl index c315abd..716c32d 100644 --- a/src/rules.jl +++ b/src/rules.jl @@ -11,8 +11,9 @@ let SQUARE_PAIRS = ( (invsqrt2π, inv2π), ) for (a,b) in SQUARE_PAIRS - Base.:(*)(::typeof(a), ::typeof(a)) = b - Base.literal_pow(::typeof(^), ::typeof(a), ::Val{2}) = b + # The output type can be Irrational, but we enforces Float64 for now. + Base.:(*)(::typeof(a), ::typeof(a)) = Float64(b) + Base.literal_pow(::typeof(^), ::typeof(a), ::Val{2}) = Float64(b) end end @@ -29,12 +30,12 @@ let INVERSE_PAIRS = ( ) for (a,b) in INVERSE_PAIRS if a !== π # Avoid type piracy - Base.inv(::typeof(a)) = b - Base.literal_pow(::typeof(^), ::typeof(a), ::Val{-1}) = b + Base.inv(::typeof(a)) = Float64(b) + Base.literal_pow(::typeof(^), ::typeof(a), ::Val{-1}) = Float64(b) end - Base.inv(::typeof(b)) = a - Base.literal_pow(::typeof(^), ::typeof(b), ::Val{-1}) = a - Base.:(*)(::typeof(a), ::typeof(b)) = one(Irrational) + Base.inv(::typeof(b)) = Float64(a) + Base.literal_pow(::typeof(^), ::typeof(b), ::Val{-1}) = Float64(a) + Base.:(*)(::typeof(a), ::typeof(b)) = 1.0 # This can be one(Irrational). end end @@ -45,9 +46,9 @@ Base.sincos(::Irrational{:twoπ}) = (0.0, 1.0) Base.sin(::Irrational{:fourπ}) = 0.0 Base.cos(::Irrational{:fourπ}) = 1.0 Base.sincos(::Irrational{:fourπ}) = (0.0, 1.0) -Base.sin(::Irrational{:quartπ}) = invsqrt2 -Base.cos(::Irrational{:quartπ}) = invsqrt2 -Base.sincos(::Irrational{:quartπ}) = (invsqrt2, invsqrt2) +Base.sin(::Irrational{:quartπ}) = Float64(invsqrt2) +Base.cos(::Irrational{:quartπ}) = Float64(invsqrt2) +Base.sincos(::Irrational{:quartπ}) = (Float64(invsqrt2), Float64(invsqrt2)) Base.sin(::Irrational{:halfπ}) = 1.0 Base.cos(::Irrational{:halfπ}) = 0.0 Base.sincos(::Irrational{:halfπ}) = (1.0, 0.0) @@ -56,11 +57,11 @@ Base.sincos(::Irrational{:halfπ}) = (1.0, 0.0) Base.exp(::Irrational{:loghalf}) = 0.5 Base.exp(::Irrational{:logtwo}) = 2.0 Base.exp(::Irrational{:logten}) = 10.0 -Base.exp(::Irrational{:logπ}) = π -Base.exp(::Irrational{:log2π}) = twoπ -Base.exp(::Irrational{:log4π}) = fourπ +Base.exp(::Irrational{:logπ}) = Float64(π) +Base.exp(::Irrational{:log2π}) = Float64(twoπ) +Base.exp(::Irrational{:log4π}) = Float64(fourπ) ## Logarithm # Base.log(::Irrational{:π}) = logπ # Avoid type piracy -Base.log(::Irrational{:twoπ}) = log2π -Base.log(::Irrational{:fourπ}) = log4π +Base.log(::Irrational{:twoπ}) = Float64(log2π) +Base.log(::Irrational{:fourπ}) = Float64(log4π) diff --git a/test/runtests.jl b/test/runtests.jl index ab4d009..f13b8e6 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -32,8 +32,10 @@ function test_with_function(f, a::Irrational) b = f(a) @test b ≈ f(float(a)) atol=1e-14 - # If f(a) is approximately equal to a value in IRRATIONALS, f(a) should be Irrational. - @test (b .≈ IRRATIONALS) == (b .=== IRRATIONALS) + # The output type can be Irrational, but we enforces Float64 for now. + # # If f(a) is approximately equal to a value in IRRATIONALS, f(a) should be Irrational. + # @test (b .≈ IRRATIONALS) == (b .=== IRRATIONALS) + @test b isa Float64 # If f(a) is close to integer, it should be a integer. if abs(b - round(b)) < 1e-14 From 329e1d3b1b098e646467f1d79f8671db91448094 Mon Sep 17 00:00:00 2001 From: hyrodium Date: Fri, 29 Apr 2022 01:25:16 +0900 Subject: [PATCH 14/16] add Compat for Julia 1.0 test --- Project.toml | 3 ++- test/runtests.jl | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 389876d..4b97786 100644 --- a/Project.toml +++ b/Project.toml @@ -7,7 +7,8 @@ version = "0.1.1" julia = "1" [extras] +Compat = "34da2185-b29b-5c13-b0c7-acf172513d20" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test"] +test = ["Test", "Compat"] diff --git a/test/runtests.jl b/test/runtests.jl index f13b8e6..e55a294 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,5 +1,6 @@ using IrrationalConstants using Test +using Compat const IRRATIONALS = ( twoπ, From a4b2a6e574f5b096252b225cd5818090198f4bed Mon Sep 17 00:00:00 2001 From: hyrodium Date: Fri, 29 Apr 2022 01:44:23 +0900 Subject: [PATCH 15/16] add tests for multiplicative inverse --- test/runtests.jl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index e55a294..fbb8ba6 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -29,6 +29,17 @@ const IRRATIONALS = ( log4π, ) +const INVERSE_PAIRS = ( + (π, invπ), + (twoπ, inv2π), + (twoinvπ, halfπ), + (quartπ, fourinvπ), + (fourπ, inv4π), + (sqrt2π, invsqrt2π), + (sqrt2, invsqrt2), + (sqrtπ, invsqrtπ), +) + function test_with_function(f, a::Irrational) b = f(a) @test b ≈ f(float(a)) atol=1e-14 @@ -115,3 +126,8 @@ end test_with_function(t->t^2, a) end end + +@testset "Multiplicative inverse for (a,b)" for (a,b) in INVERSE_PAIRS + @test a*b === 1.0 + @test b*a === 1.0 +end From f1e6c86eeb69af2bf6d542befa477674d079056b Mon Sep 17 00:00:00 2001 From: hyrodium Date: Fri, 29 Apr 2022 01:44:56 +0900 Subject: [PATCH 16/16] add missing rule for multiplicative inverse --- src/rules.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rules.jl b/src/rules.jl index 716c32d..69f6c9d 100644 --- a/src/rules.jl +++ b/src/rules.jl @@ -36,6 +36,7 @@ let INVERSE_PAIRS = ( Base.inv(::typeof(b)) = Float64(a) Base.literal_pow(::typeof(^), ::typeof(b), ::Val{-1}) = Float64(a) Base.:(*)(::typeof(a), ::typeof(b)) = 1.0 # This can be one(Irrational). + Base.:(*)(::typeof(b), ::typeof(a)) = 1.0 # This can be one(Irrational). end end