I am trying to understand how the Conv2DBackpropInput op works. Since I could not find a description of the algorithm in TF’s API Docs, I am trying to implement it as sequential code and compare against the op itself:

```
input_backprop_gold = tf.raw_ops.Conv2DBackpropInput(
input_sizes=[N, H, W, C],
filter=filter,
out_backprop=out_backprop,
strides=[1, stride, stride, 1],
padding='VALID'
)
input_backprop_np = np.zeros(shape=(N, H, W, C), dtype=np.float32)
assert input_backprop_np.shape == input_backprop_gold.shape
for n in range(N):
for p in range(P):
for q in range(Q):
for k in range(K):
for r in range(R):
for s in range(S):
for c in range(C):
input_backprop_np[n, stride * p + r, stride * q + s, c] += filter_np[r, s, c, k] * \
out_backprop_np[n, p, q, k]
assert np.allclose(input_backprop_np, input_backprop_gold)
```

This seems to produce correct results, but I don’t understand why, because the description of conv2d backprop input as provided in How does Backpropagation work in a CNN? | Medium says it should be a normal convolution of the filter (rotated by 180°) and the `out_backprop`

.

Do you have any resource that describe how the Conv2DBackpropInput op is implemented in TF? (docs, sequential code, …)