From efcb565948036eb9e95220f20da85c57fd69dabc Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Tue, 21 Jan 2014 19:13:01 -0500 Subject: [PATCH 1/4] No more ImaginaryUnit: `const im = Complex(false,true)`. This change requires giving multiplition by Bools special behavior. Approximately, `true * x = x` and `false * x = zero(x)`, but a bit complicated for the sake of promotion, the only non-trivial example of which is `Bool * MathConst`, which is promoted to Float64. Idea originally due to @GunnarFarneback: https://groups.google.com/forum/#!topic/julia-dev/VkGrqnrAdaY https://github.com/JuliaLang/julia/issues/2980 https://github.com/JuliaLang/julia/issues/3728 --- base/bool.jl | 6 ++++++ base/complex.jl | 55 +++++++++++++---------------------------------- base/constants.jl | 3 --- base/exports.jl | 1 - 4 files changed, 21 insertions(+), 44 deletions(-) diff --git a/base/bool.jl b/base/bool.jl index 38223f7e46dc5..6adc8da4f5766 100644 --- a/base/bool.jl +++ b/base/bool.jl @@ -42,6 +42,12 @@ abs2(x::Bool) = x ^(x::Bool, y::Bool) = x|!y ^(x::Integer, y::Bool) = y ? x : one(x) +function *{T<:Number}(x::Bool, y::T) + S = promote_type(Bool,T) + ifelse(x, convert(S,y), convert(S,0)) +end +*(y::Number, x::Bool) = x * y + div(x::Bool, y::Bool) = y ? x : throw(DivideError()) fld(x::Bool, y::Bool) = div(x,y) rem(x::Bool, y::Bool) = y ? false : throw(DivideError()) diff --git a/base/complex.jl b/base/complex.jl index 50b6253e25540..7f4e53d3d0573 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -5,6 +5,8 @@ end Complex(x::Real, y::Real) = Complex(promote(x,y)...) Complex(x::Real) = Complex(x, zero(x)) +const im = Complex(false,true) + typealias Complex128 Complex{Float64} typealias Complex64 Complex{Float32} typealias Complex32 Complex{Float16} @@ -57,24 +59,20 @@ isfinite(z::Complex) = isfinite(real(z)) && isfinite(imag(z)) reim(z) = (real(z), imag(z)) function complex_show(io::IO, z::Complex, compact::Bool) + z === im && return print(io, "im") r, i = reim(z) - if isnan(r) || isfinite(i) - compact ? showcompact(io,r) : show(io,r) - if signbit(i)==1 && !isnan(i) - i = -i - print(io, compact ? "-" : " - ") - else - print(io, compact ? "+" : " + ") - end - compact ? showcompact(io, i) : show(io, i) - if !(isa(i,Integer) || isa(i,Rational) || - isa(i,FloatingPoint) && isfinite(i)) - print(io, "*") - end - print(io, "im") + compact ? showcompact(io,r) : show(io,r) + if signbit(i)==1 && !isnan(i) + i = -i + print(io, compact ? "-" : " - ") else - print(io, "complex(",r,",",i,")") + print(io, compact ? "+" : " + ") end + compact ? showcompact(io, i) : show(io, i) + if !(isa(i,Integer) && !isa(i,Bool) || isa(i,FloatingPoint) && isfinite(i)) + print(io, "*") + end + print(io, "im") end show(io::IO, z::Complex) = complex_show(io, z, false) showcompact(io::IO, z::Complex) = complex_show(io, z, true) @@ -90,23 +88,6 @@ function write(s::IO, z::Complex) end -## singleton type for imaginary unit constant ## - -type ImaginaryUnit <: Number end -const im = ImaginaryUnit() - -convert{T<:Real}(::Type{Complex{T}}, ::ImaginaryUnit) = Complex{T}(zero(T),one(T)) -convert(::Type{Complex}, ::ImaginaryUnit) = Complex(real(im),imag(im)) - -real(::ImaginaryUnit) = int(0) -imag(::ImaginaryUnit) = int(1) - -promote_rule{T<:Complex}(::Type{ImaginaryUnit}, ::Type{T}) = T -promote_rule{T<:Real}(::Type{ImaginaryUnit}, ::Type{T}) = Complex{T} - -show(io::IO, ::ImaginaryUnit) = print(io, "im") - - ## generic functions of complex numbers ## convert(::Type{Complex}, z::Complex) = z @@ -127,7 +108,6 @@ inv(z::Complex) = conj(z)/abs2(z) inv{T<:Integer}(z::Complex{T}) = inv(float(z)) sign(z::Complex) = z/abs(z) -(-)(::ImaginaryUnit) = complex(0, -1) -(z::Complex) = complex(-real(z), -imag(z)) +(z::Complex, w::Complex) = complex(real(z) + real(w), imag(z) + imag(w)) -(z::Complex, w::Complex) = complex(real(z) - real(w), imag(z) - imag(w)) @@ -135,6 +115,8 @@ sign(z::Complex) = z/abs(z) real(z) * imag(w) + imag(z) * real(w)) # adding or multiplying real & complex is common +*(x::Bool, z::Complex) = ifelse(x,z,zero(z)) +*(z::Complex, x::Bool) = x * z *(x::Real, z::Complex) = complex(x * real(z), x * imag(z)) *(z::Complex, x::Real) = complex(x * real(z), x * imag(z)) +(x::Real, z::Complex) = complex(x + real(z), imag(z)) @@ -142,13 +124,6 @@ sign(z::Complex) = z/abs(z) -(x::Real, z::Complex) = complex(x - real(z), -imag(z)) -(z::Complex, x::Real) = complex(real(z) - x, imag(z)) -# multiplying by im is common -*(z::ImaginaryUnit, w::ImaginaryUnit) = complex(-imag(z), real(z)) -*(z::ImaginaryUnit, x::Real) = complex(zero(x), x) -*(x::Real, z::ImaginaryUnit) = complex(zero(x), x) -*(z::ImaginaryUnit, w::Complex) = complex(-imag(w), real(w)) -*(w::Complex, z::ImaginaryUnit) = complex(-imag(w), real(w)) - /(z::Number, w::Complex) = z*inv(w) /(a::Real , w::Complex) = a*inv(w) /(z::Complex, x::Real) = complex(real(z)/x, imag(z)/x) diff --git a/base/constants.jl b/base/constants.jl index b6051900f333f..9f72b9dacd11b 100644 --- a/base/constants.jl +++ b/base/constants.jl @@ -18,9 +18,6 @@ for op in {:+, :-, :*, :/, :^} @eval $op(x::MathConst, y::MathConst) = $op(float64(x),float64(y)) end -*(x::MathConst, i::ImaginaryUnit) = float64(x)*i -*(i::ImaginaryUnit, x::MathConst) = i*float64(x) - macro math_const(sym, val, def) esym = esc(sym) qsym = esc(Expr(:quote, sym)) diff --git a/base/exports.jl b/base/exports.jl index b4d391e231f70..9c9f1a7dae727 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -51,7 +51,6 @@ export GeneralizedSVD, Hermitian, Hessenberg, - ImaginaryUnit, InsertionSort, IntSet, IO, From 3e8ba28b2b40fe45bf60bc9eaee42ae02df4273b Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Wed, 22 Jan 2014 06:30:28 -0500 Subject: [PATCH 2/4] base/complex.jl: show Complex{Bool}s as e.g. `Complex(true,false)`. --- base/complex.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/base/complex.jl b/base/complex.jl index 7f4e53d3d0573..8696b463d18c5 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -59,7 +59,6 @@ isfinite(z::Complex) = isfinite(real(z)) && isfinite(imag(z)) reim(z) = (real(z), imag(z)) function complex_show(io::IO, z::Complex, compact::Bool) - z === im && return print(io, "im") r, i = reim(z) compact ? showcompact(io,r) : show(io,r) if signbit(i)==1 && !isnan(i) @@ -74,6 +73,8 @@ function complex_show(io::IO, z::Complex, compact::Bool) end print(io, "im") end +complex_show(io::IO, z::Complex{Bool}, compact::Bool) = + print(io, z == im ? "im" : "Complex($(z.re),$(z.im))") show(io::IO, z::Complex) = complex_show(io, z, false) showcompact(io::IO, z::Complex) = complex_show(io, z, true) @@ -115,8 +116,8 @@ sign(z::Complex) = z/abs(z) real(z) * imag(w) + imag(z) * real(w)) # adding or multiplying real & complex is common -*(x::Bool, z::Complex) = ifelse(x,z,zero(z)) -*(z::Complex, x::Bool) = x * z +*(x::Bool, z::Complex) = ifelse(x, z, zero(z)) +*(z::Complex, x::Bool) = ifelse(x, z, zero(z)) *(x::Real, z::Complex) = complex(x * real(z), x * imag(z)) *(z::Complex, x::Real) = complex(x * real(z), x * imag(z)) +(x::Real, z::Complex) = complex(x + real(z), imag(z)) From 95bb03d92073ca0c704ed3e443bb753dd617c951 Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Wed, 22 Jan 2014 11:59:45 -0500 Subject: [PATCH 3/4] base/complex.jl: additional incidental cleanup and simplifications. --- base/complex.jl | 47 +++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/base/complex.jl b/base/complex.jl index 8696b463d18c5..db2ce500bcfdc 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -11,31 +11,35 @@ typealias Complex128 Complex{Float64} typealias Complex64 Complex{Float32} typealias Complex32 Complex{Float16} -sizeof(::Type{Complex128}) = 16 -sizeof(::Type{Complex64}) = 8 -sizeof(::Type{Complex32}) = 4 +sizeof{T<:Real}(::Type{Complex{T}}) = 2*sizeof(T) -real(z::Complex) = z.re -imag(z::Complex) = z.im -real(x::Real) = x -imag(x::Real) = zero(x) - -convert{T<:Real}(::Type{Complex{T}}, x::Real) = - Complex{T}(convert(T,x), convert(T,0)) -convert{T<:Real}(::Type{Complex{T}}, z::Complex{T}) = z -convert{T<:Real}(::Type{Complex{T}}, z::Complex) = - Complex{T}(convert(T,real(z)),convert(T,imag(z))) +convert{T<:Real}(::Type{Complex{T}}, x::Real) = Complex{T}(x,0) +convert{T<:Real}(::Type{Complex{T}}, z::Complex) = Complex{T}(real(z),imag(z)) +convert{T<:Real}(::Type{T}, z::Complex) = + isreal(z) ? convert(T,real(z)) : throw(InexactError()) -convert{T<:Real}(::Type{T}, z::Complex) = (imag(z)==0 ? convert(T,real(z)) : - throw(InexactError())) +convert(::Type{Complex}, z::Complex) = z +convert(::Type{Complex}, x::Real) = Complex(x) promote_rule{T<:Real,S<:Real}(::Type{Complex{T}}, ::Type{S}) = Complex{promote_type(T,S)} promote_rule{T<:Real,S<:Real}(::Type{Complex{T}}, ::Type{Complex{S}}) = Complex{promote_type(T,S)} -complex(x, y) = Complex(x, y) -complex(x) = Complex(x) +real(z::Complex) = z.re +imag(z::Complex) = z.im +real(x::Real) = x +imag(x::Real) = zero(x) +reim(z) = (real(z), imag(z)) + +isreal(x::Real) = true +isreal(z::Complex) = imag(z) == 0 +isimag(z::Number) = real(z) == 0 +isinteger(z::Complex) = isreal(z) && isinteger(real(z)) +isfinite(z::Complex) = isfinite(real(z)) && isfinite(imag(z)) + +complex(x::Real, y::Real) = Complex(x, y) +complex(x::Real) = Complex(x) complex(z::Complex) = z complex128(r::Float64, i::Float64) = Complex{Float64}(r, i) @@ -52,12 +56,6 @@ for fn in _numeric_conversion_func_names @eval $fn(z::Complex) = complex($fn(real(z)),$fn(imag(z))) end -isreal{T<:Real}(z::Complex{T}) = imag(z) == 0 -isinteger(z::Complex) = isreal(z) && isinteger(real(z)) - -isfinite(z::Complex) = isfinite(real(z)) && isfinite(imag(z)) -reim(z) = (real(z), imag(z)) - function complex_show(io::IO, z::Complex, compact::Bool) r, i = reim(z) compact ? showcompact(io,r) : show(io,r) @@ -91,9 +89,6 @@ end ## generic functions of complex numbers ## -convert(::Type{Complex}, z::Complex) = z -convert(::Type{Complex}, x::Real) = complex(x) - ==(z::Complex, w::Complex) = (real(z) == real(w)) & (imag(z) == imag(w)) ==(z::Complex, x::Real) = isreal(z) && real(z) == x ==(x::Real, z::Complex) = isreal(z) && real(z) == x From 7bd82cf4ece434e5eebae6e813689c60515d7916 Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Wed, 22 Jan 2014 12:42:06 -0500 Subject: [PATCH 4/4] base/bool.jl: false * -2.0 => -0.0, false * 2.0 => 0.0 --- base/bool.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/base/bool.jl b/base/bool.jl index 6adc8da4f5766..820b0f7e5e2fa 100644 --- a/base/bool.jl +++ b/base/bool.jl @@ -44,7 +44,9 @@ abs2(x::Bool) = x function *{T<:Number}(x::Bool, y::T) S = promote_type(Bool,T) - ifelse(x, convert(S,y), convert(S,0)) + z = convert(S,0) + z = ifelse(signbit(y)==0, z, -z) + ifelse(x, convert(S,y), z) end *(y::Number, x::Bool) = x * y