-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add exact rules for irrational numbers #14
base: main
Are you sure you want to change the base?
Changes from 10 commits
508f058
018fe5f
88f59bf
62ac1e3
c633fda
d69df04
81f4e20
7b2e6f7
47e0808
693ae6a
f623abd
b0a9e46
1db0ac9
329e1d3
a4b2a6e
f1e6c86
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,5 +29,6 @@ export | |
log4π # log(4π) | ||
|
||
include("stats.jl") | ||
include("rules.jl") | ||
|
||
end # module |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
## Square | ||
SQUARE_PAIRS = ( | ||
(sqrt2, 2.0), | ||
(sqrt3, 3.0), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure these should be julia> versioninfo()
Julia Version 1.9.0-DEV.428
Commit f6a95348fe (2022-04-21 11:53 UTC)
Platform Info:
OS: Linux (x86_64-pc-linux-gnu)
CPU: 16 × AMD Ryzen 7 2700X Eight-Core Processor
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-13.0.1 (ORCJIT, znver1)
Threads: 1 on 16 virtual cores
julia> sin(π)
0.0
julia> cos(π)
-1.0 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think they should be |
||
(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 | ||
|
||
## 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 | ||
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 | ||
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) | ||
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 | ||
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π |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,42 +1,114 @@ | ||||||
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 | ||||||
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π, | ||||||
) | ||||||
|
||||||
@testset "k/pi" begin | ||||||
@test isapprox(1/pi, invπ) | ||||||
@test isapprox(2/pi, twoinvπ) | ||||||
@test isapprox(4/pi, fourinvπ) | ||||||
end | ||||||
function test_with_function(f, a::Irrational) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
MethodError: no method matching (::var"#test_with_function#4")(::typeof(sin), ::IrrationalConstants.Log4π)
Closest candidates are:
(::var"#test_with_function#4")(::Any, ::Irrational) |
||||||
b = f(a) | ||||||
@test b ≈ f(float(a)) atol=1e-14 | ||||||
|
||||||
@testset "1/(k*pi)" begin | ||||||
@test isapprox(1/(2pi), inv2π) | ||||||
@test isapprox(1/(4pi), inv4π) | ||||||
end | ||||||
# If f(a) is approximately equal to a value in IRRATIONALS, f(a) should be Irrational. | ||||||
@test (b .≈ IRRATIONALS) == (b .=== IRRATIONALS) | ||||||
|
||||||
@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π) | ||||||
# 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 "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 "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 "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 "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 | ||||||
|
||||||
@testset "rules for $(a)" for a in IRRATIONALS | ||||||
@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 | ||||||
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) | ||||||
test_with_function(abs2, a) | ||||||
test_with_function(t->t^2, a) | ||||||
end | ||||||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd put these variables in a
let
block (or dofor (a,b) in (...)
), otherwise you're bloating the compiled cache with stuff which isn't needed at runtimeThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review! I'll update the code later.