<p dir="auto">Running log2 on an array of zeros with float dtype results in small non-zero numbers and sometimes nan.</p>
<h3 dir="auto">Reproducing code example:</h3>

<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import numpy as np
x = np.zeros((1, 10), dtype=np.float)
print(x &gt; 0)
print(np.log2(x, where=x &gt; 0))"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">numpy</span> <span class="pl-k">as</span> <span class="pl-s1">np</span>
<span class="pl-s1">x</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">zeros</span>((<span class="pl-c1">1</span>, <span class="pl-c1">10</span>), <span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">np</span>.<span class="pl-s1">float</span>)
<span class="pl-en">print</span>(<span class="pl-s1">x</span> <span class="pl-c1">&gt;</span> <span class="pl-c1">0</span>)
<span class="pl-en">print</span>(<span class="pl-s1">np</span>.<span class="pl-en">log2</span>(<span class="pl-s1">x</span>, <span class="pl-s1">where</span><span class="pl-c1">=</span><span class="pl-s1">x</span> <span class="pl-c1">&gt;</span> <span class="pl-c1">0</span>))</pre></div>

<h3 dir="auto">Error message:</h3>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="[[False False False False False False False False False False]]
[[0.00000000e+000 0.00000000e+000 1.77229088e-310 3.50977866e+064
  0.00000000e+000 0.00000000e+000             nan             nan
  3.50977942e+064 2.23604912e-314]]"><pre class="notranslate">[[<span class="pl-c1">False</span> <span class="pl-v">False</span> <span class="pl-c1">False</span> <span class="pl-c1">False</span> <span class="pl-c1">False</span> <span class="pl-c1">False</span> <span class="pl-c1">False</span> <span class="pl-c1">False</span> <span class="pl-c1">False</span> <span class="pl-c1">False</span>]]
[[<span class="pl-c1">0.00000000e+000</span> <span class="pl-c1">0.00000000e+000</span> <span class="pl-c1">1.77229088e-310</span> <span class="pl-c1">3.50977866e+064</span>
  <span class="pl-c1">0.00000000e+000</span> <span class="pl-c1">0.00000000e+000</span>             <span class="pl-s1">nan</span>             <span class="pl-s1">nan</span>
  <span class="pl-c1">3.50977942e+064</span> <span class="pl-c1">2.23604912e-314</span>]]</pre></div>


<h3 dir="auto">Numpy/Python version information:</h3>

<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; import sys, numpy; print(numpy.__version__, sys.version)
1.15.4 3.6.6 |Anaconda custom (64-bit)| (default, Jun 28 2018, 11:07:29)
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]"><pre class="notranslate"><span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-k">import</span> <span class="pl-s1">sys</span>, <span class="pl-s1">numpy</span>; <span class="pl-en">print</span>(<span class="pl-s1">numpy</span>.<span class="pl-s1">__version__</span>, <span class="pl-s1">sys</span>.<span class="pl-s1">version</span>)
<span class="pl-c1">1.15</span>.<span class="pl-c1">4</span> <span class="pl-c1">3.6</span>.<span class="pl-c1">6</span> <span class="pl-c1">|</span><span class="pl-v">Anaconda</span> <span class="pl-s1">custom</span> (<span class="pl-c1">64</span><span class="pl-c1">-</span><span class="pl-s1">bit</span>)<span class="pl-c1">|</span> (<span class="pl-s1">default</span>, <span class="pl-v">Jun</span> <span class="pl-c1">28</span> <span class="pl-c1">2018</span>, <span class="pl-c1">11</span>:<span class="pl-c1">07</span>:<span class="pl-c1">29</span>)
[<span class="pl-v">GCC</span> <span class="pl-c1">4.2</span><span class="pl-c1">.1</span> <span class="pl-v">Compatible</span> <span class="pl-v">Clang</span> <span class="pl-c1">4.0</span>.<span class="pl-c1">1</span> (<span class="pl-s1">tags</span><span class="pl-c1">/</span><span class="pl-v">RELEASE_401</span><span class="pl-c1">/</span><span class="pl-s1">final</span>)]</pre></div>
<p dir="auto"><em>Original ticket <a href="http://projects.scipy.org/numpy/ticket/83" rel="nofollow">http://projects.scipy.org/numpy/ticket/83</a> on 2006-04-27 by <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/edschofield/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/edschofield">@edschofield</a>, assigned to unknown.</em></p>
<p dir="auto">As of SVN revision 2431, matrix objects preserve orientation in methods that take axis arguments for axis=0 and axis=1.  For axis=None, they return a matrix of shape (1, 1).  For example:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; x = asmatrix(random.uniform(0,1,(3,3)))
&gt;&gt;&gt; x.std()
matrix([[ 0.26890557]])

&gt;&gt;&gt; x.argmax()
matrix([[4]])"><pre class="notranslate"><code class="notranslate">&gt;&gt;&gt; x = asmatrix(random.uniform(0,1,(3,3)))
&gt;&gt;&gt; x.std()
matrix([[ 0.26890557]])

&gt;&gt;&gt; x.argmax()
matrix([[4]])
</code></pre></div>
<p dir="auto">I believe this behaviour is unfortunate, and that an operation aggregating a matrix over all dimensions should return a scalar.</p>
<p dir="auto">Arguments for reducing dimensionality upon aggregation have been presented in several numpy-discussion threads, most recently in [Broadcasting rules (Ticket 76)].</p>
<p dir="auto">This patch modifies this behaviour to return scalars (as rank-0 arrays) instead.  It also removes some code duplication.</p>
<p dir="auto">The behaviour with the patch is:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; x.std()
0.29610630190701492

&gt;&gt;&gt; x.std().shape
()

&gt;&gt;&gt; x.argmax()
3"><pre class="notranslate"><code class="notranslate">&gt;&gt;&gt; x.std()
0.29610630190701492

&gt;&gt;&gt; x.std().shape
()

&gt;&gt;&gt; x.argmax()
3
</code></pre></div>
<p dir="auto">A potential drawback to this patch is that matrix operations aggregating along all dimensions, which would now share the behaviour of numpy arrays, would be no longer be consistent with matrix operations that aggregate along only one dimension, which currently return matrices with height or width 1.  This could be an argument for introducing a new vector class to represent one-dimensional data with orientation.  Matrix objects, by contrast, are inherently 2-d.</p>