Skip to content

Commit 5a5d6b8

Browse files
committed
resolved type ambiguity in convert, updated Readme
1 parent a6035b8 commit 5a5d6b8

File tree

2 files changed

+53
-16
lines changed

2 files changed

+53
-16
lines changed

README.md

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,16 @@
77

88
# Introduction
99

10-
This package introduces the type `PiTimes` that automatically uses the functions `sinpi` and `cospi` instead of `sin` and `cos` to produce accurate results by avoiding floating-point inaccuracies to some extent. It also provides the constant `Pi` for convenience, defined as `PiTimes(1)`, which behaves like `pi` except it produces results with higher accuracy in certain trigonometric contexts.
10+
This package exports the type `PiExpTimes{N}` that behaves as a multipying factor of `π^N`, and the type `PiTimes` that is aliased to `PiExpTimes{1}`. It also provides the constant `Pi` for convenience, defined as `PiTimes(1)`, which behaves like `π` except it produces results with higher accuracy in certain trigonometric and algebraic contexts.
11+
12+
In most scenarios the numbers `Pi` and `pi` are interchangable.
13+
14+
```julia
15+
julia> Pi^2 == π^2
16+
true
17+
```
18+
19+
It's usually possible, and cleaner, to express mathematical relations in terms of `Pi` instead of the more cumbersome `PiExpTimes`, and is recommended unless it's specifically necessary.
1120

1221
## Rationale
1322

@@ -27,9 +36,36 @@ julia> (1//3)Pi + (4//3)Pi == (5//3)Pi
2736
true
2837
```
2938

39+
We may also simplify algebraic expressions involving powers of `Pi` as
40+
41+
```julia
42+
julia> (2Pi^2//3) // (4Pi//5)
43+
(5//6)Pi
44+
45+
julia> Pi^-2 / 4Pi^3
46+
0.25*Pi^-5
47+
```
48+
49+
The powers of `Pi` cancel as expected, and `Pi^0` is automatically converted to an ordinary real number wherever possible.
50+
51+
```julia
52+
julia> Pi^2 / Pi^2
53+
1.0
54+
```
55+
56+
Expressions involving `Pi` are automatically promoted to `Complex` as necessary, eg.
57+
58+
```julia
59+
julia> (1+im)Pi^3 / 2Pi^2
60+
0.5*Pi + 0.5*Pi*im
61+
62+
julia> (1+im)Pi^3 / 2Pi^2 * 2/Pi
63+
1.0 + 1.0im
64+
```
65+
3066
## Trigonometric functions
3167

32-
The `PiTimes` type uses `sinpi` and `cospi` under the hood when it is used as an argument to `sin` and `cos`. This results in exact results in several contexts where the inaccuracies arise from floating-point conversions.
68+
The type `PiTimes` uses `sinpi` and `cospi` under the hood when it is used as an argument to `sin` and `cos`. This results in exact results in several contexts where the inaccuracies arise from floating-point conversions.
3369

3470
```julia
3571
julia> cos(3π/2)
@@ -51,7 +87,7 @@ julia> tan(Pi/2)
5187
Inf
5288
```
5389

54-
It automatically promotes to `Complex` as necessary, so we may compute complex exponentials exactly for some arguments:
90+
We may compute complex exponential exactly:
5591

5692
```julia
5793
julia> exp(im*π/2)

src/MultiplesOfPi.jl

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -265,44 +265,45 @@ function Base.convert(::Type{PiExpTimes{N}},x::Real) where {N}
265265
den = N < 0 ? π^float(N) : π^N
266266
PiExpTimes{N}(x/den)
267267
end
268-
function Base.convert(::Type{PiExpTimes{N,T}},x::Real) where {N,T}
268+
function Base.convert(::Type{PiExpTimes{N,T}},x::Real) where {N,T<:Real}
269269
den = N < 0 ? π^float(N) : π^N
270270
PiExpTimes{N}(T(x/den))
271271
end
272272
function Base.convert(::Type{PiExpTimes{N}},::Irrational{:π}) where {N}
273273
den = N < 1 ? π^float(N-1) : π^(N-1)
274274
PiExpTimes{N}(1/den)
275275
end
276-
function Base.convert(::Type{PiExpTimes{N,T}},::Irrational{:π}) where {N,T}
276+
function Base.convert(::Type{PiExpTimes{N,T}},::Irrational{:π}) where {N,T<:Real}
277277
den = N < 1 ? π^float(N-1) : π^(N-1)
278278
PiExpTimes{N}(T(1/den))
279279
end
280280
function Base.convert(::Type{PiExpTimes{N}},p::PiExpTimes{M}) where {M,N}
281281
den = N < M ? π^float(N-M) : π^(N-M)
282282
PiExpTimes{N}(p.x/den)
283283
end
284-
function Base.convert(::Type{PiExpTimes{N,T}},p::PiExpTimes{M}) where {M,N,T}
284+
function Base.convert(::Type{PiExpTimes{N,T}},p::PiExpTimes{M}) where {M,N,T<:Real}
285285
den = N < M ? π^float(N-M) : π^(N-M)
286286
PiExpTimes{N}(T(p.x/den))
287287
end
288288
Base.convert(::Type{PiExpTimes{N}},p::PiExpTimes{N}) where {N} = p
289-
Base.convert(::Type{PiExpTimes{N,T}},p::PiExpTimes{N}) where {N,T} = PiExpTimes{N}(T(p.x))
290-
Base.convert(::Type{PiExpTimes{N,T}},p::PiExpTimes{N,T}) where {N,T} = p
289+
function Base.convert(::Type{PiExpTimes{N,T}},p::PiExpTimes{N}) where {N,T<:Real}
290+
PiExpTimes{N}(T(p.x))
291+
end
292+
Base.convert(::Type{PiExpTimes{N,T}},p::PiExpTimes{N,T}) where {N,T<:Real} = p
291293

292294
function Base.show(io::IO,p::PiExpTimes{N}) where {N}
293295
x = p.x
294-
function expstr(p)
295-
ifelse(isone(N),"Pi","Pi^"*string(N))
296-
end
296+
297+
expstr(p) = isone(N) ? "Pi" : "Pi^"*string(N)
297298

298-
xstrexp(x,p) = isone(x) ? expstr(p) : string(x)*"*"*expstr(p)
299-
xstrexp(x::Integer,p) = isone(x) ? expstr(p) : string(x)*expstr(p)
300-
xstrexp(x::AbstractFloat,p) = isone(x) ? expstr(p) :
299+
tostr(x,p) = isone(x) ? expstr(p) : string(x)*"*"*expstr(p)
300+
tostr(x::Integer,p) = isone(x) ? expstr(p) : string(x)*expstr(p)
301+
tostr(x::AbstractFloat,p) = isone(x) ? expstr(p) :
301302
isinf(x) || isnan(x) ? string(x) :
302303
string(x)*"*"*expstr(p)
303-
xstrexp(x::Rational,p) = "("*string(x)*")"*expstr(p)
304+
tostr(x::Rational,p) = "("*string(x)*")"*expstr(p)
304305

305-
str = iszero(x) ? string(x) : xstrexp(x,p)
306+
str = iszero(x) ? string(x) : tostr(x,p)
306307
print(io,str)
307308
end
308309

0 commit comments

Comments
 (0)