<h3 dir="auto">Describe the issue:</h3>
<p dir="auto">In a very specific context, numpy incorrectly asserts that <code class="notranslate">0 + 1 == 2</code>!</p>
<h3 dir="auto">Reproduce the 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

# only works in fresh interpreter, possibly uninitialized variable?
assert np.add(0., 1, where=False) == 2.
assert np.add(0., 1, where=False) == 1.
assert np.add(0., 1, where=False) == 1."><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-c"># only works in fresh interpreter, possibly uninitialized variable?</span>
<span class="pl-k">assert</span> <span class="pl-s1">np</span>.<span class="pl-en">add</span>(<span class="pl-c1">0.</span>, <span class="pl-c1">1</span>, <span class="pl-s1">where</span><span class="pl-c1">=</span><span class="pl-c1">False</span>) <span class="pl-c1">==</span> <span class="pl-c1">2.</span>
<span class="pl-k">assert</span> <span class="pl-s1">np</span>.<span class="pl-en">add</span>(<span class="pl-c1">0.</span>, <span class="pl-c1">1</span>, <span class="pl-s1">where</span><span class="pl-c1">=</span><span class="pl-c1">False</span>) <span class="pl-c1">==</span> <span class="pl-c1">1.</span>
<span class="pl-k">assert</span> <span class="pl-s1">np</span>.<span class="pl-en">add</span>(<span class="pl-c1">0.</span>, <span class="pl-c1">1</span>, <span class="pl-s1">where</span><span class="pl-c1">=</span><span class="pl-c1">False</span>) <span class="pl-c1">==</span> <span class="pl-c1">1.</span></pre></div>
<h3 dir="auto">Error message:</h3>
<p dir="auto"><em>No response</em></p>
<h3 dir="auto">NumPy/Python version information:</h3>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="1.21.2 3.9.5 (default, Jun 26 2021, 07:40:15) 
[GCC 6.3.0 20170516]"><pre class="notranslate"><code class="notranslate">1.21.2 3.9.5 (default, Jun 26 2021, 07:40:15) 
[GCC 6.3.0 20170516]
</code></pre></div>
<p dir="auto">Then I upgraded numpy to</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="1.22.4 3.9.5 (default, Jun 26 2021, 07:40:15) 
[GCC 6.3.0 20170516]"><pre class="notranslate"><code class="notranslate">1.22.4 3.9.5 (default, Jun 26 2021, 07:40:15) 
[GCC 6.3.0 20170516]
</code></pre></div>
<p dir="auto">and the problem persists.</p>
<p dir="auto">First of all, thank you so much for the work on Numpy--an incredible contribution to science and progress.</p>
<h3 dir="auto">Reproducing code example:</h3>
<p dir="auto">Numpy has excellent support for functional programming patterns, and the hundreds of <code class="notranslate">np.*</code> functions I regularly use act as pure functions with no side effects.</p>
<p dir="auto">The current behavior of <code class="notranslate">np.negative</code> breaks this pattern, and is not deterministic:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; import numpy as np
&gt;&gt;&gt; np.negative(np.arange(5), where=np.array([0,0,1,1,0],dtype=bool))
array([     94871006724704,        171798691860,                  -2,
                        -3, 4285579895102272626])
&gt;&gt;&gt; np.negative(np.arange(5), where=np.array([0,0,1,1,0],dtype=bool))
array([ 94871006750048, 140541164903200,              -2,              -3,
                    48])
&gt;&gt;&gt; x = np.arange(5)
&gt;&gt;&gt; np.negative(x,out=x, where=np.array([0,0,1,1,0],dtype=bool))
array([ 0,  1, -2, -3,  4])"><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">numpy</span> <span class="pl-k">as</span> <span class="pl-s1">np</span>
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">np</span>.<span class="pl-en">negative</span>(<span class="pl-s1">np</span>.<span class="pl-en">arange</span>(<span class="pl-c1">5</span>), <span class="pl-s1">where</span><span class="pl-c1">=</span><span class="pl-s1">np</span>.<span class="pl-en">array</span>([<span class="pl-c1">0</span>,<span class="pl-c1">0</span>,<span class="pl-c1">1</span>,<span class="pl-c1">1</span>,<span class="pl-c1">0</span>],<span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">bool</span>))
<span class="pl-en">array</span>([     <span class="pl-c1">94871006724704</span>,        <span class="pl-c1">171798691860</span>,                  <span class="pl-c1">-</span><span class="pl-c1">2</span>,
                        <span class="pl-c1">-</span><span class="pl-c1">3</span>, <span class="pl-c1">4285579895102272626</span>])
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">np</span>.<span class="pl-en">negative</span>(<span class="pl-s1">np</span>.<span class="pl-en">arange</span>(<span class="pl-c1">5</span>), <span class="pl-s1">where</span><span class="pl-c1">=</span><span class="pl-s1">np</span>.<span class="pl-en">array</span>([<span class="pl-c1">0</span>,<span class="pl-c1">0</span>,<span class="pl-c1">1</span>,<span class="pl-c1">1</span>,<span class="pl-c1">0</span>],<span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">bool</span>))
<span class="pl-en">array</span>([ <span class="pl-c1">94871006750048</span>, <span class="pl-c1">140541164903200</span>,              <span class="pl-c1">-</span><span class="pl-c1">2</span>,              <span class="pl-c1">-</span><span class="pl-c1">3</span>,
                    <span class="pl-c1">48</span>])
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">x</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">arange</span>(<span class="pl-c1">5</span>)
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">np</span>.<span class="pl-en">negative</span>(<span class="pl-s1">x</span>,<span class="pl-s1">out</span><span class="pl-c1">=</span><span class="pl-s1">x</span>, <span class="pl-s1">where</span><span class="pl-c1">=</span><span class="pl-s1">np</span>.<span class="pl-en">array</span>([<span class="pl-c1">0</span>,<span class="pl-c1">0</span>,<span class="pl-c1">1</span>,<span class="pl-c1">1</span>,<span class="pl-c1">0</span>],<span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">bool</span>))
<span class="pl-en">array</span>([ <span class="pl-c1">0</span>,  <span class="pl-c1">1</span>, <span class="pl-c1">-</span><span class="pl-c1">2</span>, <span class="pl-c1">-</span><span class="pl-c1">3</span>,  <span class="pl-c1">4</span>])</pre></div>
<p dir="auto">Thus, np.negative does not act as a mathematical function, which is confusing and error-prone. It's hard to imagine that a user would ever want uninitialized values in the returned values.</p>
<p dir="auto">A quick search on github reveals that there are thousands (if not hundreds of thousands) of instances where code introduces uninitialized values due to calls to <code class="notranslate">np.negative</code>: <a href="https://github.com/search?q=%22np.negative%22&amp;type=Code">https://github.com/search?q=%22np.negative%22&amp;type=Code</a></p>
<p dir="auto">Based on reading <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="130202287" data-permission-text="Title is private" data-url="https://github.com/numpy/numpy/issues/7158" data-hovercard-type="issue" data-hovercard-url="/numpy/numpy/issues/7158/hovercard" href="https://github.com/numpy/numpy/issues/7158">#7158</a>, I believe this issue applies to all <code class="notranslate">ufunc</code>. I understand in <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="322603885" data-permission-text="Title is private" data-url="https://github.com/numpy/numpy/issues/11086" data-hovercard-type="pull_request" data-hovercard-url="/numpy/numpy/pull/11086/hovercard" href="https://github.com/numpy/numpy/pull/11086">#11086</a> that the documentation was improved, but I wanted to open this issue to highlight both the danger of uninitialized values being returned, as well as how frequently in the wild these uninitialized values are silently corrupting data.</p>
<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.19.1 3.8.5 (default, Aug  5 2020, 08:36:46) 
[GCC 7.3.0]"><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.19</span>.<span class="pl-c1">1</span> <span class="pl-c1">3.8</span>.<span class="pl-c1">5</span> (<span class="pl-s1">default</span>, <span class="pl-v">Aug</span>  <span class="pl-c1">5</span> <span class="pl-c1">2020</span>, <span class="pl-c1">08</span>:<span class="pl-c1">36</span>:<span class="pl-c1">46</span>) 
[<span class="pl-v">GCC</span> <span class="pl-c1">7.3</span><span class="pl-c1">.0</span>]</pre></div>
<h3 dir="auto">(Edit) Proposed default behavior</h3>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; def wrapped_negative(x, out=None, where=True):
...  if (out is None):
...    temp = x[()]
...  else:
...    temp = out
...  return np.negative(x, out=temp, where=where)
&gt;&gt;&gt; wrapped_negative(np.arange(5), where=np.array([0,0,1,1,0],dtype=bool))
array([ 0,  1, -2, -3,  4])"><pre class="notranslate"><span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-k">def</span> <span class="pl-en">wrapped_negative</span>(<span class="pl-s1">x</span>, <span class="pl-s1">out</span><span class="pl-c1">=</span><span class="pl-c1">None</span>, <span class="pl-s1">where</span><span class="pl-c1">=</span><span class="pl-c1">True</span>):
...  <span class="pl-k">if</span> (<span class="pl-s1">out</span> <span class="pl-c1">is</span> <span class="pl-c1">None</span>):
...    <span class="pl-s1">temp</span> <span class="pl-c1">=</span> <span class="pl-s1">x</span>[()]
...  <span class="pl-s1">else</span>:
...    <span class="pl-s1">temp</span> <span class="pl-c1">=</span> <span class="pl-s1">out</span>
...  <span class="pl-s1">return</span> <span class="pl-s1">np</span>.<span class="pl-en">negative</span>(<span class="pl-s1">x</span>, <span class="pl-s1">out</span><span class="pl-c1">=</span><span class="pl-s1">temp</span>, <span class="pl-s1">where</span><span class="pl-c1">=</span><span class="pl-s1">where</span>)
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-en">wrapped_negative</span>(<span class="pl-s1">np</span>.<span class="pl-en">arange</span>(<span class="pl-c1">5</span>), <span class="pl-s1">where</span><span class="pl-c1">=</span><span class="pl-s1">np</span>.<span class="pl-en">array</span>([<span class="pl-c1">0</span>,<span class="pl-c1">0</span>,<span class="pl-c1">1</span>,<span class="pl-c1">1</span>,<span class="pl-c1">0</span>],<span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">bool</span>))
<span class="pl-en">array</span>([ <span class="pl-c1">0</span>,  <span class="pl-c1">1</span>, <span class="pl-c1">-</span><span class="pl-c1">2</span>, <span class="pl-c1">-</span><span class="pl-c1">3</span>,  <span class="pl-c1">4</span>])</pre></div>