code: def xprop_winograd(
      I, F, O, padding, minimal=False, trans=False, backward=False
  ):
      if backward:
          # C <=> K and mirror R,S
          F = np.transpose(F[:, ::-1, ::-1, :], (3, 1, 2, 0)).copy()
          # Invert padding
          padding = [2 - p for p in padding]
  
      C, Y, X, N = I.shape
      K, P, Q, N = O.shape
  
      B = 4
      D = B + 2
      Yw = ceil_div(P, B)
      Xw = ceil_div(Q, B)
  
      Fw = np.empty((D, D, C, K))
      Iw = np.empty((D, D, C, Yw, Xw, N))
      Mw = np.empty((D, D, K, Yw, Xw, N))  # , dtype=np.int64
  
      # Transform Filters
      for c in range(C):
          for k in range(K):
              trans_F_4x4_3x3(
                  Fw[:, :, c, k], F[c, :, :, k], minimal, trans
              )
  
      # Iterate over image transform dimensions and slice out tiles of the image
      for y in range(Yw):
          start_y, stop_y, pad_y = image_slice(y, Y, B, D, padding[0])
  
          for x in range(Xw):
              start_x, stop_x, pad_x = image_slice(
                  x, X, B, D, padding[1]
              )
  
              sliceI = I[:, start_y:stop_y, start_x:stop_x, :]
  
              # add any zero padding if needed
              if any(pad_y) or any(pad_x):
                  sliceI = np.pad(
                      sliceI, ((0, 0), pad_y, pad_x, (0, 0)), "constant"
                  )
  
              # Apply the Image transform
              for c in range(C):
                  for n in range(N):
                      trans_I_4x4_3x3(
                          Iw[:, :, c, y, x, n],
                          sliceI[c, :, :, n],
                          minimal,
                          trans,
                      )
  
      # print Iw[:,:,0,0,0,0]
      # print Fw[:,:,0,0].reshape(36,1)
      # exit()
  
      # Fw, scaleF = quantize(Fw, 16)
      # Iw, scaleI = quantize(Iw, 16)
  
      Fw = Fw.astype(np.float16).astype(np.float64)
      Iw = Iw.astype(np.float16).astype(np.float64)
  
      # Batched gemm for the pointwise multiplication step
      for s in range(D):
          for t in range(D):
              # [K,Yw,Xw,N] = [C,K].T . [C,YwXwN]
              Mw[s, t] = np.dot(
                  Fw[s, t].T, Iw[s, t].reshape(C, -1)
              ).reshape((K, Yw, Xw, N))
  
      # print Mw[:,:,0,0,0,0]
      # exit()
  
      # Mw = Mw.astype(np.float64) * scaleF * scaleI
  
      # Iterate over the convovled result in the pointwise space and apply inverse transform
      for y in range(Yw):
          p0, p1, plen = output_slice(y, P, B)
          for x in range(Xw):
              q0, q1, qlen = output_slice(x, Q, B)
              for k in range(K):
                  for n in range(N):
                      # Toss out any points that don't fit
                      # print y, x, plen, qlen
                      Out = trans_O_4x4_3x3(
                          Mw[:, :, k, y, x, n], minimal, trans
                      )
                      # print Out
                      # print Out[0:plen,0:qlen]
                      O[k, p0:p1, q0:q1, n] = Out[0:plen, 0:qlen]
  
imports: from __future__ import division
  import numpy
  from struct import pack, unpack
  from neon import logger
label_desc: Use image node_id 17 for calling a global function with example usage: xprop_winograd(I, F, O, padding, minimal, trans, backward) without return types