Re: [julia-users] Complex infinity

2015-01-10 Thread Jiahao Chen
Julia's support for complex arithmetic is written purely in Julia, so I
don't see how my suggestion to implement a new type is necessarily slower
than hard-coding in special values indicating complex infinity. The code
branches that one would need would simply be put in different places. Are
there LLVM intrinsics and/or hardware support for complex arithmetic? The
story would be different if there are (and I don't think we use them
currently).

The normalization of all complex infinities is essentially provided by the
C9X proposal's cproj function (which uses Inf + 0.0im as the representation
of ComplexInf). However, the C9X proposal acknowledges that there are use
cases for both topologies and thus avoids recommending one or the other. To
quote:

Two topologies are commonly used in complex mathematics: the complex plane
with its continuum of infinities and the Riemann sphere with its single
infinity. The complex plane is better suited for transcendental functions,
the Riemann sphere for algebraic functions. The complex types with their
multiplicity of infinities provide a useful (though imperfect) model for
the complex plane. The cproj function helps model the Riemann sphere by
mapping all infinities to one, and should be used just before any
operation, especially comparisons, that might give spurious results for any
of the other infinities.

In this proposal, the complex plane is clearly the more fundamental space.
The Riemann sphere cannot be worked with directly; one can only work with
the shadow of the Riemann sphere projected back onto the complex plane, one
particular projection of which is provided by cproj.

In contrast, it would be very Julian to represent the working topology with
types rather than explicitly forcing users to choose between the ordinary
complex plane and the Riemann sphere. The Riemann sphere would be a
first-class working algebra instead of being accessible indirectly via
cproj. The type model is also more composable, should there ever be a need
to intermix the two topologies.

The situation for zeros is less dire since they compare equal with ==,
whereas the various representations of complex infinity do not.

Thanks,

Jiahao Chen
Staff Research Scientist
MIT Computer Science and Artificial Intelligence Laboratory


Re: [julia-users] Complex infinity

2015-01-10 Thread Erik Schnetter
Instead of defining a new type, it should be faster to normalize complex 
numbers after every operation. The current, IEEE-based complex numbers not only 
have various representations of infinity, but also for zero, since they 
distinguish between +0.0 and -0.0. Thus, the normalization would map all of the 
four complex zeros to zero (e.g. +0.0+0.0im), and would also choose a single 
normalized representation of infinity (maybe inf+inf*im, where inf=1.0/0.0).

I would probably be necessary to redefine most complex number arithmetic to 
take these special cases into account.

If you do this for complex numbers, then you may also want to do it for real 
numbers, just for good measure. Currently, there is +0.0 and -0.0 (and +inf and 
-inf), and a real number corresponding to an extended complex number should 
probably not distinguish between these either.

-erik

 On Jan 10, 2015, at 14:37 , Jiahao Chen jia...@mit.edu wrote:
 
 You might be interested in Issue #5234, where I tried to catalogue issues 
 arising from nonfinite floating-point computations in the ordinary complex 
 plane (without closure on the Riemann sphere).
 
 Being able to switch between complex and extended complex (closed at 
 ComplexInf) would be interesting. I vaguely recall discussing complex 
 infinity with Mike Innes at some point, but I don't recall if we got anywhere.
 
 One solution is to wrap ordinary complex numbers in a new type representing 
 finite extended complex numbers, and create yet another new type representing 
 complex infinity. Define each function over the exted For each function, and 
 redefine each function you want to use by either wrapping a finite answer in 
 the new type, or otherwise checking if the answer is infinite and returning 
 another new type instead which represents complex infinity.
 
 
 
 abstract ExtendedComplex{T:Real}
 
 immutable ComplexInf{T:Real} : ExtendedComplex{T} end
 
 immutable FiniteExtendedComplex{T:Real} : ExtendedComplex{T}
 z :: Complex{T}
 end
 
 function ExtendedComplex{T:Real}(r::T, i::T)
 if isfinite(r)  isfinite(i))
 return ExtendedComplex(Complex(r, i))
 else
 return ComplexInf{T}()
 end
 end
 
 import Base./
 
 function /{T}(z:: ComplexInf{T}, w:: FiniteExtendedComplex{T})
 return z
 end
 
 function /{T}(z:: FiniteExtendedComplex{T}, w:: ComplexInf{T})
 return zero(z)
 end
 
 function /{T}(z:: FiniteExtendedComplex{T}, w:: FiniteExtendedComplex{T})
 a = z.z/w.z
 return isfinite(a) ? ExtendedComplex(a) : ComplexInf{T}
 end
 
 
 
 With these definitions you can compute as follows:
 
 julia FiniteExtendedComplex(2.0, 0.5)/FiniteExtendedComplex(0.5, 2.0)
 FiniteExtendedComplex{Float64}(0.47058823529411764 - 0.8823529411764706im)
 
 julia FiniteExtendedComplex(2.0, 0.3)/FiniteExtendedComplex(0.0, 0.0)
 ComplexInf{Float64}()
 
 julia ComplexInf{Float64}()/FiniteExtendedComplex(0.0, 0.0)
 ComplexInf{Float64}()
 
 julia ComplexInf{Float64}()/ComplexInf{Float64}() #Don't know how to do ∞/∞
 ERROR: `/` has no method matching /(::ComplexInf{Float64}, 
 ::ComplexInf{Float64})
 
 
 Thanks,
 
 Jiahao Chen
 Staff Research Scientist
 MIT Computer Science and Artificial Intelligence Laboratory
 
 On Sat, Jan 10, 2015 at 8:55 AM, Ed Scheinerman 
 edward.scheiner...@gmail.com wrote:
 Is there a way to have a single complex infinity? This may come at the cost 
 of computational efficiency I suppose, but I can think of situations where 
 all of the following give the same result:
 
 julia (1+1im)/0
 Inf + Inf*im
 
 julia 1im/0
 NaN + Inf*im
 
 julia 1/0 + im
 Inf + 1.0im
 
 It would be nice (sometimes) if these were all the same ComplexInf, say. 
 Perhaps there's an extended complex numbers module for this sort of work?
 

--
Erik Schnetter schnet...@gmail.com
http://www.perimeterinstitute.ca/personal/eschnetter/

My email is as private as my paper mail. I therefore support encrypting
and signing email messages. Get my PGP key from http://pgp.mit.edu/.



signature.asc
Description: Message signed with OpenPGP using GPGMail


Re: [julia-users] Complex infinity

2015-01-10 Thread Jiahao Chen
Whoops, that version didn't work. Try this version instead:



abstract ExtendedComplex{T:Real}

immutable ComplexInf{T:Real} : ExtendedComplex{T} end

immutable FiniteExtendedComplex{T:Real} : ExtendedComplex{T}
z :: Complex{T}
end

function FiniteExtendedComplex{T:Real}(r::T, i::T)
if isfinite(r)  isfinite(i)
return FiniteExtendedComplex(Complex(r, i))
else
return ComplexInf{T}()
end
end

import Base./

function /{T}(z:: ComplexInf{T}, w:: FiniteExtendedComplex{T})
return z
end

function /{T}(z:: FiniteExtendedComplex{T}, w:: ComplexInf{T})
return zero(z)
end

function /{T}(z:: FiniteExtendedComplex{T}, w:: FiniteExtendedComplex{T})
a = z.z/w.z
return isfinite(a) ? FiniteExtendedComplex(a) : ComplexInf{T}()
end


Re: [julia-users] Complex infinity

2015-01-10 Thread Jiahao Chen
You might be interested in Issue #5234
https://github.com/JuliaLang/julia/issues/5234, where I tried to
catalogue issues arising from nonfinite floating-point computations in the
ordinary complex plane (without closure on the Riemann sphere).

Being able to switch between complex and extended complex (closed at
ComplexInf) would be interesting. I vaguely recall discussing complex
infinity with Mike Innes at some point, but I don't recall if we got
anywhere.

One solution is to wrap ordinary complex numbers in a new type representing
finite extended complex numbers, and create yet another new type
representing complex infinity. Define each function over the exted For each
function, and redefine each function you want to use by either wrapping a
finite answer in the new type, or otherwise checking if the answer is
infinite and returning another new type instead which represents complex
infinity.



abstract ExtendedComplex{T:Real}

immutable ComplexInf{T:Real} : ExtendedComplex{T} end

immutable FiniteExtendedComplex{T:Real} : ExtendedComplex{T}
z :: Complex{T}
end

function ExtendedComplex{T:Real}(r::T, i::T)
if isfinite(r)  isfinite(i))
return ExtendedComplex(Complex(r, i))
else
return ComplexInf{T}()
end
end

import Base./

function /{T}(z:: ComplexInf{T}, w:: FiniteExtendedComplex{T})
return z
end

function /{T}(z:: FiniteExtendedComplex{T}, w:: ComplexInf{T})
return zero(z)
end

function /{T}(z:: FiniteExtendedComplex{T}, w:: FiniteExtendedComplex{T})
a = z.z/w.z
return isfinite(a) ? ExtendedComplex(a) : ComplexInf{T}
end



With these definitions you can compute as follows:

julia FiniteExtendedComplex(2.0, 0.5)/FiniteExtendedComplex(0.5, 2.0)
FiniteExtendedComplex{Float64}(0.47058823529411764 - 0.8823529411764706im)

julia FiniteExtendedComplex(2.0, 0.3)/FiniteExtendedComplex(0.0, 0.0)
ComplexInf{Float64}()

julia ComplexInf{Float64}()/FiniteExtendedComplex(0.0, 0.0)
ComplexInf{Float64}()

julia ComplexInf{Float64}()/ComplexInf{Float64}() #Don't know how to do ∞/∞
ERROR: `/` has no method matching /(::ComplexInf{Float64},
::ComplexInf{Float64})


Thanks,

Jiahao Chen
Staff Research Scientist
MIT Computer Science and Artificial Intelligence Laboratory

On Sat, Jan 10, 2015 at 8:55 AM, Ed Scheinerman 
edward.scheiner...@gmail.com wrote:

 Is there a way to have a single complex infinity? This may come at the
 cost of computational efficiency I suppose, but I can think of situations
 where all of the following give the same result:

 julia (1+1im)/0
 Inf + Inf*im

 julia 1im/0
 NaN + Inf*im

 julia 1/0 + im
 Inf + 1.0im

 It would be nice (sometimes) if these were all the same ComplexInf, say.
 Perhaps there's an extended complex numbers module for this sort of work?



Re: [julia-users] Complex infinity

2015-01-10 Thread Erik Schnetter
What I was imagining was a new type, called e.g. ExtendedComplex (or 
RiemannComplex) that substitutes for the current Complex type. I didn't know 
about cproj, but I was imagining something equivalent to RiemannComplex calls 
cproj after every complex number operation.

If a function can return two different types, this is called type 
instability. It requires the compiler (at least currently, but I know of no 
plans to change this) to return values in heap-allocated data structures 
instead of in registers. This is very expensive. See e.g. 
http://julia.readthedocs.org/en/latest/manual/performance-tips/ for a 
discussion on type instability. Without this problem, using a separate type to 
denote infinity would indeed not only be a very elegant but also efficient 
solution.

-erik

 On Jan 10, 2015, at 17:44 , Jiahao Chen jia...@mit.edu wrote:
 
 Julia's support for complex arithmetic is written purely in Julia, so I don't 
 see how my suggestion to implement a new type is necessarily slower than 
 hard-coding in special values indicating complex infinity. The code branches 
 that one would need would simply be put in different places. Are there LLVM 
 intrinsics and/or hardware support for complex arithmetic? The story would be 
 different if there are (and I don't think we use them currently).
 
 The normalization of all complex infinities is essentially provided by the 
 C9X proposal's cproj function (which uses Inf + 0.0im as the representation 
 of ComplexInf). However, the C9X proposal acknowledges that there are use 
 cases for both topologies and thus avoids recommending one or the other. To 
 quote:
 
 Two topologies are commonly used in complex mathematics: the complex plane 
 with its continuum of infinities and the Riemann sphere with its single 
 infinity. The complex plane is better suited for transcendental functions, 
 the Riemann sphere for algebraic functions. The complex types with their 
 multiplicity of infinities provide a useful (though imperfect) model for the 
 complex plane. The cproj function helps model the Riemann sphere by mapping 
 all infinities to one, and should be used just before any operation, 
 especially comparisons, that might give spurious results for any of the other 
 infinities.
 
 In this proposal, the complex plane is clearly the more fundamental space. 
 The Riemann sphere cannot be worked with directly; one can only work with the 
 shadow of the Riemann sphere projected back onto the complex plane, one 
 particular projection of which is provided by cproj.
 
 In contrast, it would be very Julian to represent the working topology with 
 types rather than explicitly forcing users to choose between the ordinary 
 complex plane and the Riemann sphere. The Riemann sphere would be a 
 first-class working algebra instead of being accessible indirectly via cproj. 
 The type model is also more composable, should there ever be a need to 
 intermix the two topologies.
 
 The situation for zeros is less dire since they compare equal with ==, 
 whereas the various representations of complex infinity do not.
 
 Thanks,
 
 Jiahao Chen
 Staff Research Scientist
 MIT Computer Science and Artificial Intelligence Laboratory
 

--
Erik Schnetter schnet...@gmail.com
http://www.perimeterinstitute.ca/personal/eschnetter/

My email is as private as my paper mail. I therefore support encrypting
and signing email messages. Get my PGP key from http://pgp.mit.edu/.



signature.asc
Description: Message signed with OpenPGP using GPGMail


Re: [julia-users] Complex infinity

2015-01-10 Thread Erik Schnetter
This may lead to problems with nans. For example, 1.0/(0.0, 0.0) is (inf, nan), 
and 1.0/(inf,nan) is (0.0, nan); multiply by (1, im) yields (nan, nan), and all 
information is lost. With a proper treatment, this would be (0.0, 0.0) instead.

-erik

 On Jan 10, 2015, at 18:07 , Jiahao Chen jia...@mit.edu wrote:
 
 Another possibility that occurs to me is to redefine the == equality 
 comparison. Currently this is defined as
 
 ==(z::Complex, w::Complex) = (real(z) == real(w))  (imag(z) == imag(w))
 
 but for some purposes it may be sufficient to redefine this as
 
 ==(z::Complex, w::Complex) = if isinf(z)  isinf(w)
 return true
 else
 return (real(z) == real(w))  (imag(z) == imag(w))
 end
 
 to model the topology of the Riemann sphere.
 
 With this redefinition:
 
 julia Complex(Inf, 0.0) == Complex(Inf, NaN)
 true
 
 julia Complex(Inf, 0.0) == Complex(Inf, 2.0)
 true

--
Erik Schnetter schnet...@gmail.com
http://www.perimeterinstitute.ca/personal/eschnetter/

My email is as private as my paper mail. I therefore support encrypting
and signing email messages. Get my PGP key from http://pgp.mit.edu/.



signature.asc
Description: Message signed with OpenPGP using GPGMail


Re: [julia-users] Complex infinity

2015-01-10 Thread Jiahao Chen
On Sat, Jan 10, 2015 at 6:12 PM, Erik Schnetter schnet...@gmail.com wrote:

 This may lead to problems with nans. For example, 1.0/(0.0, 0.0) is (inf,
 nan), and 1.0/(inf,nan) is (0.0, nan); multiply by (1, im) yields (nan,
 nan), and all information is lost. With a proper treatment, this would be
 (0.0, 0.0) instead.


We already have this problem.

julia 1.0/Complex(0.0, 0.0)
NaN + NaN*im

(essentially #9531)

I agree that (Inf, NaN) should be treated as a representation of complex
infinity. (Ref: #5234)


Re: [julia-users] Complex infinity

2015-01-10 Thread Jiahao Chen
Ah, I see your concern about the singleton ComplexInf type. This sounds
just like the very same design issue behind NA in DataArrays and Nullables
in 0.4.


Re: [julia-users] Complex infinity

2015-01-10 Thread Jiahao Chen
Another possibility that occurs to me is to redefine the == equality
comparison. Currently this is defined as

==(z::Complex, w::Complex) = (real(z) == real(w))  (imag(z) == imag(w))

but for some purposes it may be sufficient to redefine this as

==(z::Complex, w::Complex) = if isinf(z)  isinf(w)
return true
else
return (real(z) == real(w))  (imag(z) == imag(w))
end

to model the topology of the Riemann sphere.

With this redefinition:

julia Complex(Inf, 0.0) == Complex(Inf, NaN)
true

julia Complex(Inf, 0.0) == Complex(Inf, 2.0)
true


Re: [julia-users] Complex infinity

2015-01-10 Thread Erik Schnetter
On Jan 10, 2015, at 18:15 , Jiahao Chen jia...@mit.edu wrote:
 
 Ah, I see your concern about the singleton ComplexInf type. This sounds just 
 like the very same design issue behind NA in DataArrays and Nullables in 0.4.

Yes, it is. But no matter how efficient this will be -- this approach will 
always require at least one additional bit of storage to describe the type, 
whereas a representation purely in terms of two reals won't. This will always 
be slower.

-erik

--
Erik Schnetter schnet...@gmail.com
http://www.perimeterinstitute.ca/personal/eschnetter/

My email is as private as my paper mail. I therefore support encrypting
and signing email messages. Get my PGP key from http://pgp.mit.edu/.



signature.asc
Description: Message signed with OpenPGP using GPGMail


Re: [julia-users] Complex infinity

2015-01-10 Thread Erik Schnetter
On Jan 10, 2015, at 18:22 , Jiahao Chen jia...@mit.edu wrote:
 
 On Sat, Jan 10, 2015 at 6:12 PM, Erik Schnetter schnet...@gmail.com wrote:
 This may lead to problems with nans. For example, 1.0/(0.0, 0.0) is (inf, 
 nan), and 1.0/(inf,nan) is (0.0, nan); multiply by (1, im) yields (nan, nan), 
 and all information is lost. With a proper treatment, this would be (0.0, 
 0.0) instead.
 
 We already have this problem.
 
 julia 1.0/Complex(0.0, 0.0)
 NaN + NaN*im
 
 (essentially #9531)
 
 I agree that (Inf, NaN) should be treated as a representation of complex 
 infinity. (Ref: #5234)

This will either require normalizing the result of complex operations, or 
normalizing the input.

-erik

--
Erik Schnetter schnet...@gmail.com
http://www.perimeterinstitute.ca/personal/eschnetter/

My email is as private as my paper mail. I therefore support encrypting
and signing email messages. Get my PGP key from http://pgp.mit.edu/.



signature.asc
Description: Message signed with OpenPGP using GPGMail