code: def forward(model, X, is_train):
      nF = model.get_dim("nF")
      nO = model.get_dim("nO")
      nP = model.get_dim("nP")
      nI = model.get_dim("nI")
      W = model.get_param("W")
      # Preallocate array for layer output, including padding.
      Yf = model.ops.alloc2f(X.shape[0] + 1, nF * nO * nP, zeros=False)
      model.ops.gemm(
          X, W.reshape((nF * nO * nP, nI)), trans2=True, out=Yf[1:]
      )
      Yf = Yf.reshape((Yf.shape[0], nF, nO, nP))
  
      # Set padding. Padding has shape (1, nF, nO, nP). Unfortunately, we cannot
      # change its shape to (nF, nO, nP) without breaking existing models. So
      # we'll squeeze the first dimension here.
      Yf[0] = model.ops.xp.squeeze(model.get_param("pad"), 0)
  
      def backward(dY_ids):
          # This backprop is particularly tricky, because we get back a different
          # thing from what we put out. We put out an array of shape:
          # (nB, nF, nO, nP), and get back:
          # (nB, nO, nP) and ids (nB, nF)
          # The ids tell us the values of nF, so we would have:
          #
          # dYf = zeros((nB, nF, nO, nP))
          # for b in range(nB):
          #     for f in range(nF):
          #         dYf[b, ids[b, f]] += dY[b]
          #
          # However, we avoid building that array for efficiency -- and just pass
          # in the indices.
          dY, ids = dY_ids
          assert dY.ndim == 3
          assert dY.shape[1] == nO, dY.shape
          assert dY.shape[2] == nP, dY.shape
          # nB = dY.shape[0]
          model.inc_grad(
              "pad",
              _backprop_precomputable_affine_padding(model, dY, ids),
          )
          Xf = X[ids]
          Xf = Xf.reshape((Xf.shape[0], nF * nI))
  
          model.inc_grad("b", dY.sum(axis=0))
          dY = dY.reshape((dY.shape[0], nO * nP))
  
          Wopfi = W.transpose((1, 2, 0, 3))
          Wopfi = Wopfi.reshape((nO * nP, nF * nI))
          dXf = model.ops.gemm(
              dY.reshape((dY.shape[0], nO * nP)), Wopfi
          )
  
          dWopfi = model.ops.gemm(dY, Xf, trans1=True)
          dWopfi = dWopfi.reshape((nO, nP, nF, nI))
          # (o, p, f, i) --> (f, o, p, i)
          dWopfi = dWopfi.transpose((2, 0, 1, 3))
          model.inc_grad("W", dWopfi)
          return dXf.reshape((dXf.shape[0], nF, nI))
  
      return Yf, backward
  
imports: from thinc.api import Model, normal_init
  from ..util import registry
label_desc: Use image node_id 2 for calling a global function with example usage: forward(model, X, is_train) and returns: Yf,  backward, dXf