code: def xprop_direct(I, F, O, padding, strides, backward=False):
      if all(x == 1 for x in F.shape[1:3]):
          C = F.shape[0]
          if backward:
              # CxHWN = CxK . KxHWN
              O[:] = np.dot(
                  F.reshape((C, -1)), I.reshape((C, -1))
              ).reshape((O.shape))
          else:
              # KxHWN = CxK.T . CxHWN
              O[:] = np.dot(
                  F.reshape((C, -1)).T, I.reshape((C, -1))
              ).reshape((O.shape))
          return
  
      if backward:
          # C <=> K and mirror R,S
          F = np.transpose(F[:, ::-1, ::-1, :], (3, 1, 2, 0)).copy()
          xconv_slice = bconv_slice
      else:
          xconv_slice = fconv_slice
  
      C, Y, X, N = I.shape
      C, R, S, K = F.shape
      K, P, Q, N = O.shape
  
      qSlice = [
          xconv_slice(q, S, X, padding[0], strides[0]) for q in range(Q)
      ]
  
      for p in range(P):
          sliceR, sliceY, _ = xconv_slice(
              p, R, Y, padding[1], strides[1]
          )
  
          for q in range(Q):
              sliceS, sliceX, _ = qSlice[q]
  
              slicedF = F[:, sliceR, sliceS, :].reshape((-1, K))
              slicedI = I[:, sliceY, sliceX, :].reshape((-1, N))
  
              O[:, p, q, :] = np.dot(slicedF.T, slicedI)
  
imports: from __future__ import division
  import numpy
  from struct import pack, unpack
  from neon import logger
label_desc: Use image node_id 7 for calling a global function with example usage: xprop_direct(I, F, O, padding, strides, backward) without return types