How torch.gradient function works?

ado_sar: <p>I am reading the docs for the <code>torch.gradient</code> function but I can’t understand how the gradient is calculated. Specifically, for the first example where gradient for <code>f(x) = x**2</code> is approximated, how we can compute a gradient without knowing the function value at <code>f(x+hl)</code> and <code>f(x+hr)</code>? The docs say that the function derivative is approximated with the following formula:<br>
<div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/3X/a/3/a3510124e527adc496ad4ed103575328372bc283.png" data-download-href="https://discuss.pytorch.org/uploads/default/a3510124e527adc496ad4ed103575328372bc283" title="Screenshot from 2023-04-08 01-02-44"><img src="https://discuss.pytorch.org/uploads/default/original/3X/a/3/a3510124e527adc496ad4ed103575328372bc283.png" alt="Screenshot from 2023-04-08 01-02-44" data-base62-sha1="niLnuIkdQ2LOpXk4w95udZBUJHR" width="690" height="110" data-dominant-color="F4F4F4"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">Screenshot from 2023-04-08 01-02-44</span><span class="informations">700×112 4.69 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div><br>
but we don’t know <code>f(x+hl)</code> and <code>f(x+hr)</code>.</p>

eqy: <p>Note that according to the docs you are passing the values of the function, which would be <code>f(x+...)</code></p>
<pre><code class="lang-auto">    input (Tensor) – the tensor that represents the values of the function
</code></pre>
<pre><code class="lang-auto">&gt;&gt;&gt; import torch
&gt;&gt;&gt; torch.gradient(torch.tensor([1, 2, 3, 4]))
(tensor([1., 1., 1., 1.]),)
&gt;&gt;&gt; torch.gradient(torch.tensor([1, 2, 3, 4]), spacing=(torch.tensor([1, 2, 3, 4]),))
(tensor([1., 1., 1., 1.]),)
&gt;&gt;&gt; torch.gradient(torch.tensor([1, 2, 3, 4]), spacing=(torch.tensor([2, 4, 6, 8]),))
(tensor([0.5000, 0.5000, 0.5000, 0.5000]),)
</code></pre>

ado_sar: <p>Still I don’t get how the derivative is calculated. In your examples basically we have the functions <code>y=x</code> and <code>y=0.5*x</code>. Lets focus on the first example where the first coordinate is 1 and the value is 1. I can’t understand how from just these values <code>torch.gradient</code> is able to calculate the derivative which equals 1.</p>

arunppsg: <p>For  <code>x[i]</code>  , <code>hr</code> is <code>x[i+1] - x[i]</code> and <code>hl</code> is <code>x[i] - x[i-1]</code>.</p>
<p>Correspondingly, <code>f(x[i] + hr)</code> is <code>f(x[i+1])</code> and <code>f(x[i] - hl</code>) is <code>f(x[i - 1])</code>.</p>
<p>In the below example, let’s say the gradient has to be computed at index 1 (x = -1).</p>
<pre><code class="lang-auto">x = (torch.tensor([-2., -1., 1., 4.]), )

y = torch.tensor([4., 1., 1., 16.])

torch.gradient(y, spacing = x)  # result: (tensor([-3., -2.,  2.,  5.]),)

# for index 1
x = -1
f_x = 1

hr = 2 # (-1 + 2 = 1)
f_x_hr = 1

hl = 1 # (-2 + 1 = -1)
f_x_hl = 4

# by the formula in the docs
g_f_x = ((hl ** 2) * f_x_hr - (hr ** 2) * f_x_hl + (hr ** 2 - hl ** 2) * f_x) / (hr * (hl ** 2) + hl * (hr ** 2))  # gives -2
</code></pre>
<p>For the edge cases, like index 0, the gradient seems to be computed <code>(y2 - y1) / (x2 - x1)</code> - the standard slope formula.</p>