<p dir="auto">Dividing a nonzero value by 0 should give an infinite result. This works fine for floating point numbers, but not for complex:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; 1. / 0.
Inf

julia&gt; 1. / (0.+0.im)
NaN + NaN*im"><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-c1">1.</span> <span class="pl-k">/</span> <span class="pl-c1">0.</span>
<span class="pl-c1">Inf</span>

julia<span class="pl-k">&gt;</span> <span class="pl-c1">1.</span> <span class="pl-k">/</span> (<span class="pl-c1">0.</span><span class="pl-k">+</span><span class="pl-c1">0.im</span>)
<span class="pl-c1">NaN</span> <span class="pl-k">+</span> <span class="pl-c1">NaN</span><span class="pl-k">*</span>im</pre></div>
<p dir="auto">Similarly, dividing by infinity (with a finite numerator) should give 0. This isn't working entirely properly:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; 1/Inf
0.0

julia&gt; 1/(Inf*im)
0.0 - 0.0im

julia&gt; 1/(Inf + 0*im)
0.0 - 0.0im

julia&gt; 1/(Inf + Inf*im)
NaN + NaN*im         # this is wrong"><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-c1">1</span><span class="pl-k">/</span><span class="pl-c1">Inf</span>
<span class="pl-c1">0.0</span>

julia<span class="pl-k">&gt;</span> <span class="pl-c1">1</span><span class="pl-k">/</span>(<span class="pl-c1">Inf</span><span class="pl-k">*</span>im)
<span class="pl-c1">0.0</span> <span class="pl-k">-</span> <span class="pl-c1">0.0im</span>

julia<span class="pl-k">&gt;</span> <span class="pl-c1">1</span><span class="pl-k">/</span>(<span class="pl-c1">Inf</span> <span class="pl-k">+</span> <span class="pl-c1">0</span><span class="pl-k">*</span>im)
<span class="pl-c1">0.0</span> <span class="pl-k">-</span> <span class="pl-c1">0.0im</span>

julia<span class="pl-k">&gt;</span> <span class="pl-c1">1</span><span class="pl-k">/</span>(<span class="pl-c1">Inf</span> <span class="pl-k">+</span> <span class="pl-c1">Inf</span><span class="pl-k">*</span>im)
<span class="pl-c1">NaN</span> <span class="pl-k">+</span> <span class="pl-c1">NaN</span><span class="pl-k">*</span>im         <span class="pl-c"><span class="pl-c">#</span> this is wrong</span></pre></div>
<p dir="auto">Finally, in my opinion, there should be only a single <code class="notranslate">ComplexInf</code> value and not allow this:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; a = 3+Inf*im
3.0 + Inf*im

julia&gt; b = 4+Inf*im
4.0 + Inf*im

julia&gt; a==b
false"><pre class="notranslate">julia<span class="pl-k">&gt;</span> a <span class="pl-k">=</span> <span class="pl-c1">3</span><span class="pl-k">+</span><span class="pl-c1">Inf</span><span class="pl-k">*</span>im
<span class="pl-c1">3.0</span> <span class="pl-k">+</span> <span class="pl-c1">Inf</span><span class="pl-k">*</span>im

julia<span class="pl-k">&gt;</span> b <span class="pl-k">=</span> <span class="pl-c1">4</span><span class="pl-k">+</span><span class="pl-c1">Inf</span><span class="pl-k">*</span>im
<span class="pl-c1">4.0</span> <span class="pl-k">+</span> <span class="pl-c1">Inf</span><span class="pl-k">*</span>im

julia<span class="pl-k">&gt;</span> a<span class="pl-k">==</span>b
<span class="pl-c1">false</span></pre></div>
<p dir="auto">Both <code class="notranslate">a</code> and <code class="notranslate">b</code> should have evaluated to a common <code class="notranslate">ComplexInf</code> value. (We may also need a <code class="notranslate">ComplexNaN</code>.) Separate <code class="notranslate">+Inf</code> and <code class="notranslate">-Inf</code> is fine for <code class="notranslate">Real</code> values.</p>
<p dir="auto">(Context: this issue has come up recently in <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="23462533" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/4967" data-hovercard-type="pull_request" data-hovercard-url="/JuliaLang/julia/pull/4967/hovercard" href="https://github.com/JuliaLang/julia/pull/4967">#4967</a> and elsewhere)</p>
<p dir="auto">We currently don't treat the results of indeterminate computations consistently between real and complex arithmetic.</p>
<h2 dir="auto">Example 1: cosine</h2>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; cos(Inf)
ERROR: DomainError
 in cos at math.jl:277

julia&gt; cos(complex(Inf,0))
NaN - 0.0im"><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-c1">cos</span>(<span class="pl-c1">Inf</span>)
ERROR<span class="pl-k">:</span> DomainError
 <span class="pl-k">in</span> cos at math<span class="pl-k">.</span>jl<span class="pl-k">:</span><span class="pl-c1">277</span>

julia<span class="pl-k">&gt;</span> <span class="pl-c1">cos</span>(<span class="pl-c1">complex</span>(<span class="pl-c1">Inf</span>,<span class="pl-c1">0</span>))
<span class="pl-c1">NaN</span> <span class="pl-k">-</span> <span class="pl-c1">0.0im</span></pre></div>
<h2 dir="auto">Example 2: inverse</h2>
<h3 dir="auto">inverse of 0</h3>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; inv(0.0)
Inf

julia&gt; inv(complex(0.0, 0.0))
NaN + NaN*im"><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-c1">inv</span>(<span class="pl-c1">0.0</span>)
<span class="pl-c1">Inf</span>

julia<span class="pl-k">&gt;</span> <span class="pl-c1">inv</span>(<span class="pl-c1">complex</span>(<span class="pl-c1">0.0</span>, <span class="pl-c1">0.0</span>))
<span class="pl-c1">NaN</span> <span class="pl-k">+</span> <span class="pl-c1">NaN</span><span class="pl-k">*</span>im</pre></div>
<p dir="auto">This illustrates a problem with infinity and signed zero. Unlike real infinities, of which there are only two <code class="notranslate">FloatingPoint</code> values, you can have 13 possible representations of complex infinities which convey different information about the phase (argument) of the complex infinity:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="complex(+Inf, +0.0) #phase is exactly 0 or approaches 0 from the first quadrant
complex(+Inf, +Inf) #phase is in (0, pi/2), i.e. the first quadrant excluding the edges
complex(+0.0, +Inf) #phase is exactly pi/2 or approaches pi/2 from the first quadrant
complex(-0.0, +Inf) #phase approaches pi/2 from the second quadrant
complex(-Inf, +Inf) #phase is in (pi/2, pi), i.e. the second quadrant excluding the edges
complex(-Inf, +0.0) #phase is exactly pi or approaches pi from the second quadrant
complex(-Inf, -0.0) #phase approaches pi from the third quadrant
complex(-Inf, -Inf) #phase is in (pi, 3pi/2), i.e. the third quadrant excluding the edges
complex(-0.0, -Inf) #phase approaches 3pi/2 from the third quadrant
complex(+0.0, -Inf) #phase is exactly 3pi/2 or approaches 3pi/2 from the fourth quadrant
complex(+Inf, -Inf) #phase is in (3pi/2, 2pi), i.e. the fourth quadrant excluding the edges
complex(+Inf, -0.0) #phase approaches 2pi from the fourth quadrant
complex(NaN, NaN) #phase cannot be determined to lie in exactly one of the above regions
#                  and hence the infinity has no valid non-NaN representation in floating point"><pre class="notranslate"><span class="pl-c1">complex</span>(<span class="pl-k">+</span><span class="pl-c1">Inf</span>, <span class="pl-k">+</span><span class="pl-c1">0.0</span>) <span class="pl-c"><span class="pl-c">#</span>phase is exactly 0 or approaches 0 from the first quadrant</span>
<span class="pl-c1">complex</span>(<span class="pl-k">+</span><span class="pl-c1">Inf</span>, <span class="pl-k">+</span><span class="pl-c1">Inf</span>) <span class="pl-c"><span class="pl-c">#</span>phase is in (0, pi/2), i.e. the first quadrant excluding the edges</span>
<span class="pl-c1">complex</span>(<span class="pl-k">+</span><span class="pl-c1">0.0</span>, <span class="pl-k">+</span><span class="pl-c1">Inf</span>) <span class="pl-c"><span class="pl-c">#</span>phase is exactly pi/2 or approaches pi/2 from the first quadrant</span>
<span class="pl-c1">complex</span>(<span class="pl-k">-</span><span class="pl-c1">0.0</span>, <span class="pl-k">+</span><span class="pl-c1">Inf</span>) <span class="pl-c"><span class="pl-c">#</span>phase approaches pi/2 from the second quadrant</span>
<span class="pl-c1">complex</span>(<span class="pl-k">-</span><span class="pl-c1">Inf</span>, <span class="pl-k">+</span><span class="pl-c1">Inf</span>) <span class="pl-c"><span class="pl-c">#</span>phase is in (pi/2, pi), i.e. the second quadrant excluding the edges</span>
<span class="pl-c1">complex</span>(<span class="pl-k">-</span><span class="pl-c1">Inf</span>, <span class="pl-k">+</span><span class="pl-c1">0.0</span>) <span class="pl-c"><span class="pl-c">#</span>phase is exactly pi or approaches pi from the second quadrant</span>
<span class="pl-c1">complex</span>(<span class="pl-k">-</span><span class="pl-c1">Inf</span>, <span class="pl-k">-</span><span class="pl-c1">0.0</span>) <span class="pl-c"><span class="pl-c">#</span>phase approaches pi from the third quadrant</span>
<span class="pl-c1">complex</span>(<span class="pl-k">-</span><span class="pl-c1">Inf</span>, <span class="pl-k">-</span><span class="pl-c1">Inf</span>) <span class="pl-c"><span class="pl-c">#</span>phase is in (pi, 3pi/2), i.e. the third quadrant excluding the edges</span>
<span class="pl-c1">complex</span>(<span class="pl-k">-</span><span class="pl-c1">0.0</span>, <span class="pl-k">-</span><span class="pl-c1">Inf</span>) <span class="pl-c"><span class="pl-c">#</span>phase approaches 3pi/2 from the third quadrant</span>
<span class="pl-c1">complex</span>(<span class="pl-k">+</span><span class="pl-c1">0.0</span>, <span class="pl-k">-</span><span class="pl-c1">Inf</span>) <span class="pl-c"><span class="pl-c">#</span>phase is exactly 3pi/2 or approaches 3pi/2 from the fourth quadrant</span>
<span class="pl-c1">complex</span>(<span class="pl-k">+</span><span class="pl-c1">Inf</span>, <span class="pl-k">-</span><span class="pl-c1">Inf</span>) <span class="pl-c"><span class="pl-c">#</span>phase is in (3pi/2, 2pi), i.e. the fourth quadrant excluding the edges</span>
<span class="pl-c1">complex</span>(<span class="pl-k">+</span><span class="pl-c1">Inf</span>, <span class="pl-k">-</span><span class="pl-c1">0.0</span>) <span class="pl-c"><span class="pl-c">#</span>phase approaches 2pi from the fourth quadrant</span>
<span class="pl-c1">complex</span>(<span class="pl-c1">NaN</span>, <span class="pl-c1">NaN</span>) <span class="pl-c"><span class="pl-c">#</span>phase cannot be determined to lie in exactly one of the above regions</span>
<span class="pl-c"><span class="pl-c">#</span>                  and hence the infinity has no valid non-NaN representation in floating point</span></pre></div>
<p dir="auto">The result is correct <em>if</em> we work with unsigned zeros. However, after accounting for the signed zeros in <code class="notranslate">complex(+0.0, +0.0)</code>, this result should be <code class="notranslate">complex(+Inf, +Inf)</code>. A <code class="notranslate">DivideError</code> might also be a reasonable alternative here.</p>
<h3 dir="auto">inverse of infinities</h3>
<p dir="auto">The inverse mapping is also problematic:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; inv(Inf)
0.0

julia&gt; inv(complex(Inf,0))
0.0 - 0.0im

julia&gt; inv(complex(Inf,Inf))
NaN + NaN*im"><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-c1">inv</span>(<span class="pl-c1">Inf</span>)
<span class="pl-c1">0.0</span>

julia<span class="pl-k">&gt;</span> <span class="pl-c1">inv</span>(<span class="pl-c1">complex</span>(<span class="pl-c1">Inf</span>,<span class="pl-c1">0</span>))
<span class="pl-c1">0.0</span> <span class="pl-k">-</span> <span class="pl-c1">0.0im</span>

julia<span class="pl-k">&gt;</span> <span class="pl-c1">inv</span>(<span class="pl-c1">complex</span>(<span class="pl-c1">Inf</span>,<span class="pl-c1">Inf</span>))
<span class="pl-c1">NaN</span> <span class="pl-k">+</span> <span class="pl-c1">NaN</span><span class="pl-k">*</span>im</pre></div>
<h3 dir="auto">inverse of indeterminates</h3>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; inv(NaN)
NaN

julia&gt; inv(complex(0,NaN))
NaN + NaN*im

julia&gt; inv(complex(NaN, 0))
NaN + NaN*im

julia&gt; inv(complex(NaN, NaN))
NaN + NaN*im"><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-c1">inv</span>(<span class="pl-c1">NaN</span>)
<span class="pl-c1">NaN</span>

julia<span class="pl-k">&gt;</span> <span class="pl-c1">inv</span>(<span class="pl-c1">complex</span>(<span class="pl-c1">0</span>,<span class="pl-c1">NaN</span>))
<span class="pl-c1">NaN</span> <span class="pl-k">+</span> <span class="pl-c1">NaN</span><span class="pl-k">*</span>im

julia<span class="pl-k">&gt;</span> <span class="pl-c1">inv</span>(<span class="pl-c1">complex</span>(<span class="pl-c1">NaN</span>, <span class="pl-c1">0</span>))
<span class="pl-c1">NaN</span> <span class="pl-k">+</span> <span class="pl-c1">NaN</span><span class="pl-k">*</span>im

julia<span class="pl-k">&gt;</span> <span class="pl-c1">inv</span>(<span class="pl-c1">complex</span>(<span class="pl-c1">NaN</span>, <span class="pl-c1">NaN</span>))
<span class="pl-c1">NaN</span> <span class="pl-k">+</span> <span class="pl-c1">NaN</span><span class="pl-k">*</span>im</pre></div>
<p dir="auto">Is it meaningful to distinguish between these three possible complex NaNs? It seems silly in this example, but consider also:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; complex(0, NaN) + complex(0, NaN)
complex(0.0,NaN)

julia&gt; complex(0, NaN) * complex(0, NaN)
NaN + NaN*im"><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-c1">complex</span>(<span class="pl-c1">0</span>, <span class="pl-c1">NaN</span>) <span class="pl-k">+</span> <span class="pl-c1">complex</span>(<span class="pl-c1">0</span>, <span class="pl-c1">NaN</span>)
<span class="pl-c1">complex</span>(<span class="pl-c1">0.0</span>,<span class="pl-c1">NaN</span>)

julia<span class="pl-k">&gt;</span> <span class="pl-c1">complex</span>(<span class="pl-c1">0</span>, <span class="pl-c1">NaN</span>) <span class="pl-k">*</span> <span class="pl-c1">complex</span>(<span class="pl-c1">0</span>, <span class="pl-c1">NaN</span>)
<span class="pl-c1">NaN</span> <span class="pl-k">+</span> <span class="pl-c1">NaN</span><span class="pl-k">*</span>im</pre></div>
<p dir="auto">etc.</p>
<h2 dir="auto">Example 3: roots (nonintegral powers)</h2>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; sqrt(-1)
ERROR: DomainError

julia&gt; sqrt(complex(-1))
0.0 + 1.0im

julia&gt; (-1)^(-1/2)
NaN

julia&gt; complex(-1)^(-1/2)
6.123233995736766e-17 - 1.0im"><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-c1">sqrt</span>(<span class="pl-k">-</span><span class="pl-c1">1</span>)
ERROR<span class="pl-k">:</span> DomainError

julia<span class="pl-k">&gt;</span> <span class="pl-c1">sqrt</span>(<span class="pl-c1">complex</span>(<span class="pl-k">-</span><span class="pl-c1">1</span>))
<span class="pl-c1">0.0</span> <span class="pl-k">+</span> <span class="pl-c1">1.0im</span>

julia<span class="pl-k">&gt;</span> (<span class="pl-k">-</span><span class="pl-c1">1</span>)<span class="pl-k">^</span>(<span class="pl-k">-</span><span class="pl-c1">1</span><span class="pl-k">/</span><span class="pl-c1">2</span>)
<span class="pl-c1">NaN</span>

julia<span class="pl-k">&gt;</span> <span class="pl-c1">complex</span>(<span class="pl-k">-</span><span class="pl-c1">1</span>)<span class="pl-k">^</span>(<span class="pl-k">-</span><span class="pl-c1">1</span><span class="pl-k">/</span><span class="pl-c1">2</span>)
<span class="pl-c1">6.123233995736766e-17</span> <span class="pl-k">-</span> <span class="pl-c1">1.0im</span></pre></div>
<p dir="auto">Whereas <code class="notranslate">sqrt(-1)</code> returns the notorious <code class="notranslate">DomainError</code>, the inverse square root (as computed by <code class="notranslate">x-&gt;x^-1/2</code> does not, but returns a <code class="notranslate">NaN</code> instead. This use of <code class="notranslate">NaN</code> is sanctioned by IEEE 754 in the specific case of a real operation with no real output.</p>
<p dir="auto"><strong>tl;dr: if a floating-point computation returns an indeterminate value, when should it return a <code class="notranslate">NaN</code> (or any of its complex variants), and when should it throw an error like <code class="notranslate">DivideError</code> or <code class="notranslate">DomainError</code>?</strong> By my reading of IEEE 754, both of these behaviors are allowed (throwing an error would correspond to a signaling <code class="notranslate">NaN</code> which is trapped by the error handler). Each of these examples in isolation show valid behavior; however, we should be consistent.</p>