Complex autograd is wrong for z*z in current nightly

KFrank: <p>Hello Forum!</p>
<p>The current nightly build, version 1.8.0.dev20201208, gives the<br>
wrong autograd result for the square of a complex tensor.  This<br>
very simple case is handled correctly in version 1.6.0.</p>
<p>A quick look at github didn’t turn up any issues that seemed<br>
directly relevant to this change.</p>
<p>For complex <code>z</code>, the complex derivative of its square is given by</p>
<pre><code class="lang-plaintext">d z*z / d z  =  2 * z
</code></pre>
<p>(just as it would be if <code>z</code> were real).  It appears that the current<br>
nightly build incorrectly returns <code>2 * z.conj()</code> as the derivative.</p>
<p>Here are the new and old pytorch results:</p>
<p>Version 1.8.0.dev20201208:</p>
<pre><code class="lang-plaintext">&gt;&gt;&gt; import torch
&gt;&gt;&gt; torch.__version__
'1.8.0.dev20201208'
&gt;&gt;&gt; z = torch.tensor ([2. + 1.j], requires_grad = True)
&gt;&gt;&gt; zsq = z * z
&gt;&gt;&gt; zsq.backward()
&gt;&gt;&gt; z.grad
tensor([4.-2.j])
</code></pre>
<p>(The result for <code>z.grad</code> should be <code>2 * z = tensor([4.+2.j])</code>.)</p>
<p>Version 1.6.0:</p>
<pre><code class="lang-plaintext">&gt;&gt;&gt; import torch
&gt;&gt;&gt; torch.__version__
'1.6.0'
&gt;&gt;&gt; z = torch.tensor ([2. + 1.j], requires_grad = True)
&gt;&gt;&gt; zsq = z * z
&gt;&gt;&gt; zsq.backward()
/home/user/miniconda3/lib/python3.8/site-packages/torch/autograd/__init__.py:125: UserWarning: Complex backward is not fully supported yet and could lead to wrong gradients for functions we have not fixed yet (Triggered internally at  /opt/conda/conda-bld/pytorch_1595629395347/work/torch/csrc/autograd/python_engine.cpp:157.)
  Variable._execution_engine.run_backward(
&gt;&gt;&gt; z.grad
tensor([4.+2.j])
</code></pre>
<p>(Here, <code>z.grad</code> is correct.)</p>
<p>The same thing happens using <code>z.pow (2.0)</code> in place of <code>z * z</code>.</p>
<p>In the following post, I link to a potentially-relevant discussion about<br>
generalized complex differentiation.</p>
<aside class="quote quote-modified" data-post="1" data-topic="105602">
  <div class="title">
    <div class="quote-controls"></div>
    <img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/letter_avatar_proxy/v4/letter/k/ecb155/48.png" class="avatar">
    <a href="https://discuss.pytorch.org/t/how-might-autograd-differentiate-complex-functions-that-are-not-complex-differentiable/105602">How might autograd differentiate complex functions that are not complex-differentiable?</a> <a class="badge-category__wrapper " href="/c/complex/22"><span data-category-id="22" data-drop-close="true" class="badge-category "><span class="badge-category__name">complex</span></span></a>
  </div>
  <blockquote>
    Hello Forum! 
There are useful functions of a complex variable, z, that are not 
“complex-differentiable,” that is, they are not analytic functions. 
Two examples would be z.conj() and |z|**2 = z * z.conj(). 
Note that these functions are differentiable when viewed as real 
functions of two real variables, x and y, where z = x + yj. 
I think that when a function is analytic, autograd should return 
its conventional complex derivative.  However, we would like 
autograd also to do something “usefu…
  </blockquote>
</aside>

<p>Best.</p>
<p>K. Frank</p>