Skip to content

Commit

Permalink
added support for complex numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
jishnub committed Mar 3, 2020
1 parent 29fdb25 commit 083f797
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 7 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "MultiplesOfPi"
uuid = "b749d01f-fee9-4313-9f11-89ddf7ea9d58"
authors = ["Jishnu Bhattacharya", "Center for Space Science", "New York University Abu Dhabi"]
version = "0.1.0"
version = "0.1.1"

[compat]
julia = "1"
Expand Down
38 changes: 36 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,41 @@ julia> sin(PiTimes(-1))
-0.0
```

It automatically promotes to `Complex` as necessary, so we may compute complex exponentials exactly for some arguments:

```julia
julia> exp(im*π/2)
6.123233995736766e-17 + 1.0im

julia> exp(im*PiTimes(1/2))
0.0 + 1.0im

# Euler's identity : exp(iπ) + 1 == 0
julia> exp(im*π) + 1
0.0 + 1.2246467991473532e-16im

julia> exp(im*PiTimes(1)) + 1
0.0 + 0.0im
```

The function `exp(ix)` for a finite real `x` might also be computed using `cis`, as
```julia
julia> cis(PiTimes(1/2))
0.0 + 1.0im
```

Hyperbolic functions work as expected:

```julia
# cosh(ix) = cos(x)
# Should be exactly zero for x = π/2
julia> cosh(im*π/2)
6.123233995736766e-17 + 0.0im

julia> cosh(im*PiTimes(1/2))
0.0 + 0.0im
```

# Installation

Install the package using
Expand All @@ -32,7 +67,6 @@ pkg> add https://github.com/jishnub/MultiplesOfPi.jl.git

julia> using MultiplesOfPi
```

# To-do

Add support for complex numbers
Add support for `tan`
17 changes: 17 additions & 0 deletions src/MultiplesOfPi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ struct PiTimes{T<:Real} <: AbstractIrrational
end

Base.:(<)(p::PiTimes,q::PiTimes) = p.x < q.x
Base.:(==)(p::PiTimes,q::PiTimes) = p.x == q.x

for T in (:BigFloat,:Float64,:Float32,:Float16)
eval(quote
Expand All @@ -22,4 +23,20 @@ end

@inline Base.cis(p::PiTimes) = Complex(cos(p),sin(p))

Base.:(+)(p1::PiTimes,p2::PiTimes) = PiTimes(p1.x+p2.x)

Base.:(-)(p::PiTimes) = PiTimes(-p.x)
Base.:(-)(p1::PiTimes,p2::PiTimes) = PiTimes(p1.x-p2.x)

Base.:(/)(p1::PiTimes,p2::PiTimes) = p1.x/p2.x

# Divisions involving pi retain type
Base.:(/)(::Irrational{:π},p::PiTimes) = inv(p.x)
Base.:(/)(p::PiTimes,::Irrational{:π}) = p.x

Base.:(*)(p1::PiTimes,y::Real) = PiTimes(p1.x*y)
Base.:(*)(y::Real,p1::PiTimes) = PiTimes(p1.x*y)
Base.:(*)(p1::PiTimes,p2::PiTimes) = float(p1) * float(p2)
Base.:(*)(z::Complex{Bool},p::PiTimes) = p*z # switch the orders to get to something that's non-ambiguous

end # module
69 changes: 65 additions & 4 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ using Test
@test PiTimes(1//2) π/2
end
@testset "Ordering" begin
@test PiTimes(1) < 4
@test PiTimes(2) > 4
@test PiTimes(2) > π
@test PiTimes(2) < PiTimes(4)
@testset "inequality" begin
@test PiTimes(1) < 4
@test PiTimes(2) > 4
@test PiTimes(2) > π
@test PiTimes(2) < PiTimes(4)
end
@testset "equality" begin
@test PiTimes(2) == PiTimes(2)
end
end
@testset "conversion" begin
@test convert(Float64,PiTimes(1)) Float64(1π)
Expand All @@ -25,6 +30,47 @@ using Test
@test convert(Float16,PiTimes(1)) Float16(1)*π
@test Float16(PiTimes(1)) Float16(1)*π
end
@testset "algebra" begin
p1 = PiTimes(3)
p2 = PiTimes(4)

@testset "negation" begin
@test -p1 isa PiTimes{Int}
@test -p1 == PiTimes(-p1.x)
end

@testset "addition" begin
@test p1 + p1 == PiTimes(2p1.x)
@test p1 + p2 == PiTimes(p1.x + p2.x)
end

@testset "subtraction" begin
@test p1 - p1 == PiTimes(0)
@test p1 - p2 == PiTimes(p1.x - p2.x)
end

@testset "multiplication" begin
@test p1*2 == PiTimes(p1.x*2)
@test 2*p1 == PiTimes(p1.x*2)
@test 2p1 == PiTimes(p1.x*2)
@test p1*p1 (p1.x*π)^2
@test p1*p2 (p1.x*p2.x)*π^2
@test p1 * im == PiTimes(0) + PiTimes(p1.x)*im
@test im* p1 == PiTimes(0) + PiTimes(p1.x)*im
@test (1+im)*p1 == PiTimes(p1.x) + PiTimes(p1.x)*im
end

@testset "division" begin
@test p1/p1 == 1
@test p1/p2 == p1.x/p2.x == 3/4 # works as 1/4 can be stored exactly
@test p2/p1 == p2.x/p1.x

@test p1/π === p1.x
@test PiTimes(7.3)/π === 7.3
@test π/PiTimes(1/7.3) 7.3 # within rounding errors
@test π/PiTimes(1//7) === 7//1
end
end
@testset "trigonometric functions" begin
x = 1.5
@test sin(PiTimes(x)) == sinpi(x) sin*x)
Expand All @@ -36,5 +82,20 @@ using Test
a = sincos(PiTimes(x))
@test a[1] == sinpi(x)
@test a[2] == cospi(x)

@testset "exp" begin
@test exp(im*PiTimes(0)) == cis(PiTimes(0)) == 1
@test exp(im*PiTimes(1/2)) == cis(PiTimes(1/2)) == im
@test exp(im*PiTimes(1)) == cis(PiTimes(1))== -1
@test exp(im*PiTimes(3/2)) == cis(PiTimes(3/2)) == -im
end
end
@testset "hyperbolic" begin
@testset "cosh" begin
@test cosh(im*PiTimes(1/2)) == 0
end
@testset "sinh" begin
@test sinh(im*PiTimes(-1)) == 0
end
end
end

0 comments on commit 083f797

Please sign in to comment.