<p dir="auto">I tried to find any kind of documentation on how numpy implements inequality comparison between complex numbers, but I found none.</p>
<p dir="auto">It seems like <code class="notranslate">__lt__</code> is implemented as <code class="notranslate">(lhs.real, lhs.imag) &lt; (rhs.real, rhs.imag)</code>, or in other words</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="if lhs.real &lt; rhs.real:
    return True
if lhs.real &gt; rhs.real:
    return False
return lhs.imag &lt; rhs.imag"><pre class="notranslate"><code class="notranslate">if lhs.real &lt; rhs.real:
    return True
if lhs.real &gt; rhs.real:
    return False
return lhs.imag &lt; rhs.imag
</code></pre></div>
<p dir="auto">Tests that brought me to this conclusion:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; numpy.array(9+999j) &lt; numpy.array(10+10j)
True
&gt;&gt;&gt; numpy.array(11+1j) &lt; numpy.array(10+10j)
False
&gt;&gt;&gt; numpy.array(10+1j) &lt; numpy.array(10+10j)
True
&gt;&gt;&gt; numpy.array(10+11j) &lt; numpy.array(10+10j)
False"><pre class="notranslate"><code class="notranslate">&gt;&gt;&gt; numpy.array(9+999j) &lt; numpy.array(10+10j)
True
&gt;&gt;&gt; numpy.array(11+1j) &lt; numpy.array(10+10j)
False
&gt;&gt;&gt; numpy.array(10+1j) &lt; numpy.array(10+10j)
True
&gt;&gt;&gt; numpy.array(10+11j) &lt; numpy.array(10+10j)
False
</code></pre></div>
<p dir="auto">Is this correct? If so it would at the bare minimum require some formal documentation, as another perfectly valid implementation could have been <code class="notranslate">abs(lhs) &lt; abs(rhs)</code>.</p>
<p dir="auto">Also, <code class="notranslate">arange</code> behaves weirdly and I can't put any sense in it. I would have expected it to be coherent with <code class="notranslate">__lt__</code>, that is</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="i = start
while (i &lt; stop if step &gt; 0 else i &gt; stop):
    yield i
    i += step"><pre class="notranslate"><code class="notranslate">i = start
while (i &lt; stop if step &gt; 0 else i &gt; stop):
    yield i
    i += step
</code></pre></div>
<p dir="auto">but it isn't:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; numpy.arange(0+1j, 4+1j, 1)
array([], dtype=complex128)
&gt;&gt;&gt; numpy.arange(0+1j, 4+4j, 1)
array([0.+1.j, 1.+1.j, 2.+1.j])
&gt;&gt;&gt; numpy.arange(0, 4j, 1j)
array([], dtype=complex128)
&gt;&gt;&gt; numpy.arange(0, 8+4j, 1)
array([0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j])"><pre class="notranslate"><code class="notranslate">&gt;&gt;&gt; numpy.arange(0+1j, 4+1j, 1)
array([], dtype=complex128)
&gt;&gt;&gt; numpy.arange(0+1j, 4+4j, 1)
array([0.+1.j, 1.+1.j, 2.+1.j])
&gt;&gt;&gt; numpy.arange(0, 4j, 1j)
array([], dtype=complex128)
&gt;&gt;&gt; numpy.arange(0, 8+4j, 1)
array([0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j])
</code></pre></div>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; np.arange(0, 10, 2)
array([0, 2, 4, 6, 8])

# as above, cast to complex
&gt;&gt;&gt; np.arange(0 + 0j, 10 + 0j, 2 + 0j)
array([], dtype=complex128)  #what?

# bizarre input needed to give expected output
&gt;&gt;&gt; np.arange(0 + 0j, 10 + 10j, 2 + 0j)
# array([ 0.+0.j,  2.+0.j,  4.+0.j,  6.+0.j,  8.+0.j])"><pre class="notranslate"><span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">np</span>.<span class="pl-en">arange</span>(<span class="pl-c1">0</span>, <span class="pl-c1">10</span>, <span class="pl-c1">2</span>)
<span class="pl-en">array</span>([<span class="pl-c1">0</span>, <span class="pl-c1">2</span>, <span class="pl-c1">4</span>, <span class="pl-c1">6</span>, <span class="pl-c1">8</span>])

<span class="pl-c"># as above, cast to complex</span>
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">np</span>.<span class="pl-en">arange</span>(<span class="pl-c1">0</span> <span class="pl-c1">+</span> <span class="pl-c1">0j</span>, <span class="pl-c1">10</span> <span class="pl-c1">+</span> <span class="pl-c1">0j</span>, <span class="pl-c1">2</span> <span class="pl-c1">+</span> <span class="pl-c1">0j</span>)
<span class="pl-en">array</span>([], <span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">complex128</span>)  <span class="pl-c">#what?</span>

<span class="pl-c"># bizarre input needed to give expected output</span>
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">np</span>.<span class="pl-en">arange</span>(<span class="pl-c1">0</span> <span class="pl-c1">+</span> <span class="pl-c1">0j</span>, <span class="pl-c1">10</span> <span class="pl-c1">+</span> <span class="pl-c1">10j</span>, <span class="pl-c1">2</span> <span class="pl-c1">+</span> <span class="pl-c1">0j</span>)
<span class="pl-c"># array([ 0.+0.j,  2.+0.j,  4.+0.j,  6.+0.j,  8.+0.j])</span></pre></div>
<p dir="auto">For some reason, it deliberately computes len as (<a class="commit-link" data-hovercard-type="commit" data-hovercard-url="https://github.com/numpy/numpy/commit/c14792d056422fe02219efc600ca9d67c4bbd56d/hovercard" href="https://github.com/numpy/numpy/commit/c14792d056422fe02219efc600ca9d67c4bbd56d"><tt>c14792d</tt></a>)</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="c_len = (start - stop) / step
len = min(ceil(c_len.real), ceil(c_len.imag))"><pre class="notranslate"><code class="notranslate">c_len = (start - stop) / step
len = min(ceil(c_len.real), ceil(c_len.imag))
</code></pre></div>
<p dir="auto">which for real-only values, gives <code class="notranslate">0</code>.</p>
<p dir="auto">I think a better approach would be to use one of</p>
<ol dir="auto">
<li>
<p dir="auto"><code class="notranslate">ceil(abs(c_len))</code> - has semantics "use the circle centered at <code class="notranslate">start</code> and passing through <code class="notranslate">end</code>" as the end point</p>
</li>
<li>
<p dir="auto"><code class="notranslate">ceil(c_len.real)</code> - has semantics "use the projection of <code class="notranslate">end</code> onto the line <code class="notranslate">start + k*step</code> as the endpoint"</p>
</li>
<li>
<p dir="auto">above with <code class="notranslate">assert c_len.imag == 0</code> - requires that <code class="notranslate">end</code> lies on that line, but prone to rounding error</p>
</li>
<li>
<p dir="auto">Project <code class="notranslate">step</code> onto the line between <code class="notranslate">start</code> and <code class="notranslate">end</code>, and use that instead</p>
</li>
</ol>
<p dir="auto">I like the look of 2 and 4</p>