@@ -16,25 +16,26 @@ julia> PiExpTimes(2, 3)
1616
1717See also: [`Pi`](@ref)
1818"""
19- struct PiExpTimes{T<: Real } <: AbstractIrrational
19+ struct PiExpTimes{T<: Real ,N <: Real } <: AbstractIrrational
2020 x :: T
21- n :: Int
22-
23- PiExpTimes {T} (x:: T , n:: Int ) where {T<: Real } = new (x, n)
24- PiExpTimes {PiExpTimes{T}} (p:: PiExpTimes{T} , n:: Int ) where {T<: Real } = new (p, n)
25- PiExpTimes {PiExpTimes} (p:: PiExpTimes , n:: Int ) = new (p, n)
26- PiExpTimes {Irrational{:π}} (p:: Irrational{:π} , n:: Int ) = new (p, n)
21+ n :: N
2722end
2823
29- PiExpTimes {T} (x:: Real , n:: Int ) where {T<: Real } = PiExpTimes {T} (T (x), n)
30- PiExpTimes {T} (:: Irrational{:π} , n:: Int ) where {T<: Real } = PiExpTimes {T} (T (1 ), n + 1 )
31- PiExpTimes {T} (p:: PiExpTimes , n:: Int ) where {T<: Real } = PiExpTimes {T} (p. x, p. n + n)
32- PiExpTimes {T} (x:: Real , n:: Integer = 0 ) where {T<: Real } = PiExpTimes {T} (x, Int (n))
24+ PiExpTimes {T,N} (x:: Real ) where {T,N} = PiExpTimes {T,N} (T (x), zero (N))
25+ PiExpTimes {T,N} (p:: PiExpTimes{S} ) where {T,S,N} = PiExpTimes {T,N} (T (p. x), N (p. n))
26+
27+ PiExpTimes {PiExpTimes{T}} (p:: PiExpTimes{T} , n:: Real ) where {T<: Real } = PiExpTimes {PiExpTimes{T}, typeof(n)} (p, n)
28+ PiExpTimes {PiExpTimes} (p:: PiExpTimes , n:: Real ) = PiExpTimes {PiExpTimes, typeof(n)} (p, n)
29+ PiExpTimes {Irrational{:π}} (p:: Irrational{:π} , n:: Real ) = PiExpTimes {Irrational{:π}, typeof(n)} (p, n)
3330
34- PiExpTimes (:: Irrational{:π} , n:: Integer = 0 ) = PiExpTimes {Int} (1 , Int (n) + 1 )
35- PiExpTimes (x:: Real , n:: Integer = 0 ) = PiExpTimes {typeof(x)} (x, Int (n))
31+ PiExpTimes {T} (x:: Real , n:: Real = 0 ) where {T<: Real } = PiExpTimes {T,typeof(n)} (T (x), n)
32+ PiExpTimes {T} (:: Irrational{:π} , n:: Real ) where {T<: Real } = PiExpTimes {T,typeof(n)} (T (1 ), n + 1 )
33+ PiExpTimes {T} (p:: PiExpTimes , n:: Real ) where {T<: Real } = PiExpTimes {T,typeof(n)} (p. x, p. n + n)
34+
35+ PiExpTimes (:: Irrational{:π} , n:: Real = 0 ) = PiExpTimes {Int} (1 , n + one (n))
3636# avoid nesting
37- PiExpTimes (p:: PiExpTimes , n:: Integer = 0 ) = PiExpTimes (p. x, p. n + n)
37+ PiExpTimes (p:: PiExpTimes , n:: Real = 0 ) = PiExpTimes (p. x, p. n + n)
38+ PiExpTimes (x:: Real ) = PiExpTimes (x, 0 )
3839
3940"""
4041 Pi
@@ -86,36 +87,39 @@ Base.:(==)(p::PiExpTimes, x::Real) = p == PiExpTimes(x, 0)
8687Base.:(== )(x:: Real , p:: PiExpTimes ) = p == x
8788
8889simplify (p) = p
90+ simplify (p:: PiExpTimes{Irrational{:π}} ) = PiExpTimes (1 , p. n + one (p. n))
8991simplify (p:: PiExpTimes{<:PiExpTimes} ) = simplify (p. x) * Pi^ (p. n)
9092
9193for f in [:(< ), :(== )]
9294 @eval Base.$ f (p:: PiExpTimes , :: Irrational{:π} ) = $ f (p, Pi)
9395 @eval Base.$ f (:: Irrational{:π} , p:: PiExpTimes ) = $ f (Pi, p)
9496end
9597
96- Base. promote_rule (:: Type{Irrational{:π}} , :: Type{PiExpTimes{T}} ) where {T} = PiExpTimes{T}
97- Base. promote_rule (:: Type{PiExpTimes{T}} , :: Type{Irrational{:π}} ) where {T} = PiExpTimes{T}
98+ Base. promote_rule (:: Type{Irrational{:π}} , :: Type{PiExpTimes{T,N}} ) where {T,N} = PiExpTimes{T,N}
99+ Base. promote_rule (:: Type{PiExpTimes{T,N}} , :: Type{Irrational{:π}} ) where {T,N} = PiExpTimes{T,N}
100+
101+ Base. promote_rule (:: Type{PiExpTimes{T,N}} , :: Type{Bool} ) where {T,N} = PiExpTimes{T,N}
102+ Base. promote_rule (:: Type{PiExpTimes{T,N}} , :: Type{S} ) where {T,S<: AbstractIrrational ,N} = PiExpTimes{promote_type (S,T),N}
103+ Base. promote_rule (:: Type{PiExpTimes{T,N}} , :: Type{S} ) where {T,S<: Real ,N} = PiExpTimes{promote_type (S,T),N}
104+ Base. promote_rule (:: Type{PiExpTimes{T,N}} , :: Type{Float16} ) where {T,N} = PiExpTimes{promote_type (Float16,T),N}
105+ Base. promote_rule (:: Type{PiExpTimes{T,N}} , :: Type{Float32} ) where {T,N} = PiExpTimes{promote_type (Float32,T),N}
98106
99- Base. promote_rule (:: Type{PiExpTimes{T}} , :: Type{Bool} ) where {T} = PiExpTimes{T}
100- Base. promote_rule (:: Type{PiExpTimes{T}} , :: Type{S} ) where {T,S<: AbstractIrrational } = PiExpTimes{promote_type (S,T)}
101- Base. promote_rule (:: Type{PiExpTimes{T}} , :: Type{S} ) where {T,S<: Real } = PiExpTimes{promote_type (S,T)}
102- Base. promote_rule (:: Type{PiExpTimes{T}} , :: Type{Float16} ) where {T} = PiExpTimes{promote_type (Float16,T)}
103- Base. promote_rule (:: Type{PiExpTimes{T}} , :: Type{Float32} ) where {T} = PiExpTimes{promote_type (Float32,T)}
107+ Base. promote_rule (:: Type{BigFloat} , :: Type{PiExpTimes{T,N}} ) where {T,N} = PiExpTimes{promote_type (BigFloat,T),N}
104108
105- Base. promote_rule (:: Type{PiExpTimes{T}} , :: Type{PiExpTimes{S}} ) where {T,S} = PiExpTimes{promote_type (T, S)}
109+ Base. promote_rule (:: Type{PiExpTimes{T,N }} , :: Type{PiExpTimes{S,M }} ) where {T,S,N,M } = PiExpTimes{promote_type (T, S), promote_type (M, N )}
106110
107- Base. promote_rule (:: Type{PiExpTimes{T}} , :: Type{Complex{S}} ) where {T<: Real ,S<: Real } = Complex{PiExpTimes{promote_type (T, S)}}
111+ Base. promote_rule (:: Type{PiExpTimes{T,N}} , :: Type{Complex{S}} ) where {T<: Real ,S<: Real ,N} = Complex{PiExpTimes{promote_type (T, S),N}}
112+
113+ Base. AbstractFloat (p:: PiExpTimes{T,N} ) where {T,N} = promote_type (T,N,Float64)(p)
108114
109115for T in (:Float64 ,:Float32 ,:Float16 )
110116 @eval begin
111117 function Base. $T (p:: PiExpTimes )
112118 n = p. n
113- if n == 0
119+ if iszero (n)
114120 return $ T (p. x)
115- elseif n > 0
116- return $ T (p. x* π^ n)
117121 else
118- return $ T (p. x* inv ( float (π)) ^- n)
122+ return $ T (p. x* float (pi ) ^ n)
119123 end
120124 end
121125 end
@@ -125,40 +129,41 @@ end
125129# Convert π to BigFloat before multiplying
126130function Base. BigFloat (p:: PiExpTimes )
127131 n = p. n
128- if n == 0
132+ if iszero (n)
129133 return BigFloat (p. x)
130- elseif n > 0
131- return BigFloat (p. x)* BigFloat (π)^ n
132134 else
133- return BigFloat (p. x) * inv ( BigFloat (π)) ^- n
135+ return BigFloat (p. x* BigFloat (π)^ n)
134136 end
135137end
136138
137- for f in (:iszero , :isfinite , :isnan )
138- @eval Base.$ f (p:: PiExpTimes ) = $ f (p. x)
139- end
139+ Base. iszero (p:: PiExpTimes{<:Real,Int} ) = iszero (p. x)
140+ Base. iszero (p:: PiExpTimes ) = iszero (float (p))
141+ Base. isfinite (p:: PiExpTimes ) = isfinite (float (p))
142+ Base. isnan (p:: PiExpTimes ) = isnan (float (p))
140143
141144# Unfortunately Irrational numbers do not have a multiplicative identity of the same type,
142145# so we make do with something that works
143- Base. one (:: Type{PiExpTimes} ) = true
146+ Base. one (:: Type{<: PiExpTimes} ) = true
144147Base. isone (p:: PiExpTimes ) = (x = simplify (p); isone (x. x) && iszero (x. n))
145148
146- Base. zero (p:: PiExpTimes{T} ) where {T} = PiExpTimes {T} (zero (T), p. n)
147- Base. zero (:: Type{PiExpTimes{T}} ) where {T} = PiExpTimes {T} (zero (T))
149+ Base. zero (p:: PiExpTimes{T,N } ) where {T,N } = PiExpTimes {T,N } (zero (T), p. n)
150+ Base. zero (:: Type{PiExpTimes{T,N }} ) where {T,N } = PiExpTimes {T,N } (zero (T), zero (N ))
148151
149152Base. sign (p:: PiExpTimes ) = sign (p. x)
150153Base. signbit (p:: PiExpTimes ) = signbit (p. x)
151154
152155# Define trigonometric functions
153156
154157# this is type-unstable, but Union splitting does its magic
155- @inline dividebypiexp (p:: PiExpTimes , n) = p. n == n ? p. x : p. x * float (π) ^ (p. n- n)
158+ @inline dividebypiexp (p:: PiExpTimes , n) = p. n == n ? p. x : p. x * π ^ float (p. n- n)
156159@inline dividebypi (p) = dividebypiexp (p, 1 )
157160
158- Base. sin (p:: PiExpTimes ) = p. n == 0 ? sin (p. x) : sinpi (dividebypi (p))
159- Base. cos (p:: PiExpTimes ) = p. n == 0 ? cos (p. x) : cospi (dividebypi (p))
161+ @inline _check_exp_apply (f, fzeroexp, p) = iszero (p. n) ? fzeroexp (p. x) : f (dividebypi (p))
162+ Base. sin (p:: PiExpTimes ) = _check_exp_apply (sinpi, sin, p)
163+ # Base.sin(p::PiExpTimes) = iszero(p.n) ? sin(p.x) : sinpi(dividebypi(p))
164+ Base. cos (p:: PiExpTimes ) = _check_exp_apply (cospi, cos, p)
160165if VERSION > v " 1.6.0"
161- Base. sincos (p:: PiExpTimes ) = p . n == 0 ? sincos (p . x) : sincospi ( dividebypi (p) )
166+ Base. sincos (p:: PiExpTimes ) = _check_exp_apply (sincospi, sincos, p )
162167else
163168 Base. sincos (p:: PiExpTimes ) = (sin (p),cos (p))
164169end
170175
171176@inline function Base. tan (p:: PiExpTimes{T} ) where {T}
172177 Tf = float (T)
173- if simplify (p). n == 1
178+ if isone ( simplify (p). n)
174179 r = abs (rem (p. x, one (p. x)))
175180 iszero (r) && return copysign (zero (Tf), p. x)
176181 2 r == one (r) && return copysign (Tf (Inf ), p. x)
224229Base.:(* )(b:: Bool , p:: PiExpTimes ) = ifelse (b, p, flipsign (zero (p), p. x))
225230Base.:(/ )(b:: Bool , p:: PiExpTimes ) = PiExpTimes (b / p. x, - p. n)
226231
227- Base.:(^ )(p:: PiExpTimes , n:: Integer ) = PiExpTimes (p. x^ n, n* p. n)
232+ Base.:(^ )(p:: PiExpTimes , q:: PiExpTimes ) = PiExpTimes (float (p. x)^ oftype (float (p. x), q), q* p. n)
233+ Base.:(^ )(:: Irrational{:π} , p:: PiExpTimes ) = Pi^ p
234+ Base.:(^ )(p:: PiExpTimes , :: Irrational{:π} ) = PiExpTimes (p. x^ π, Pi* p. n)
235+ _default_exp (p, n) = PiExpTimes (p. x^ n, n* p. n)
236+ # These methods need to be defined to handle ambiguities
237+ Base.:(^ )(p:: PiExpTimes , n:: AbstractIrrational ) = _default_exp (p, n)
238+ Base.:(^ )(p:: PiExpTimes , n:: Rational ) = _default_exp (p, n)
239+ Base.:(^ )(p:: PiExpTimes , n:: Integer ) = _default_exp (p, n)
240+ Base.:(^ )(p:: PiExpTimes , n:: Real ) = _default_exp (p, n)
228241
229242# Rational divide
230243Base.:(// )(p:: PiExpTimes , q:: PiExpTimes ) = PiExpTimes (p. x// q. x, p. n - q. n)
@@ -236,6 +249,10 @@ Base.:(//)(::Irrational{:π}, p::PiExpTimes) = PiExpTimes(1//p.x, -p.n+1)
236249# Pretty-printing
237250
238251function Base. show (io:: IO , p:: PiExpTimes )
252+ if ! isfinite (p)
253+ print (io, float (p))
254+ return
255+ end
239256 x = p. x
240257
241258 expstr (p) = isone (p. n) ? " Pi" : " Pi^" * string (p. n)
0 commit comments