iconv2dBackward :: KernelProgram '[TensorCL [k, k, c1, c2],
                                  MTensorCL [ow + k - 1, oh + k - 1, c1],
                                  TensorCL [ow, oh, c2]]
iconv2dBackward = compile $ \flt d_input d_output -> do
  ~[ix, iy, ic] <- traverse get_global_id [0, 1, 2]
  let [kw, kh, c1, c2] = dimsOf flt
  let [iw, ih, _] = dimsOf d_input
  acc <- eval 0
  kernel_x1 <- eval $ fmax 0 (kw - (iw - ix))
  kernel_x2 <- eval $ fmin kw (ix + 1)
  kernel_y1 <- eval $ fmax 0 (kh - (ih - iy))
  kernel_y2 <- eval $ fmin kh (iy + 1)
  forEach kernel_x1 kernel_x2 $ \kx -> do
    forEach kernel_y1 kernel_y2 $ \ky -> do
      forEach 0 c2 $ \oc -> do
        acc .= acc + flt![kx, ky, ic, oc] * d_output![ix - kx, iy - ky, oc]
  d_input![ix, iy, ic] .= acc


iconv2dBackward :: KernelProgram '[TensorCL [k, k, c1, c2],
                                  MTensorCL [ow + k - 1, oh + k - 1, c1],
                                  TensorCL [ow, oh, c2]]
iconv2dBackward = compile $ \flt d_input d_output -> do
  ~[ix, iy, ic] <- traverse get_global_id [0, 1, 2]
  let [kw, kh, c1, c2] = dimsOf flt
  let [iw, ih, _] = dimsOf d_input
  acc <- eval 0
  kernel_x1 <- eval $ fmax 0 (kw - (iw - ix))
  kernel_x2 <- eval $ fmin kw (ix + 1)
  kernel_y1 <- eval $ fmax 0 (kh - (ih - iy))
  kernel_y2 <- eval $ fmin kh (iy + 1)
  forEach kernel_x1 kernel_x2 $ \kx -> do
    forEach kernel_y1 kernel_y2 $ \ky -> do
      forEach 0 c2 $ \oc -> do
        acc .= acc + flt![kx, ky, ic, oc] * d_output![ix - kx, iy - ky, oc]
  d_input![ix, iy, ic] .= acc


iconv2dBackward = compile $ \flt d_input d_output -> do
  ~[ix, iy, ic] <- traverse get_global_id [0, 1, 2]
  let [kw, kh, c1, c2] = dimsOf flt
  let [iw, ih, _] = dimsOf d_input
  acc <- eval 0
  kernel_x1 <- eval $ fmax 0 (kw - (iw - ix))
  kernel_x2 <- eval $ fmin kw (ix + 1)
  kernel_y1 <- eval $ fmax 0 (kh - (ih - iy))
  kernel_y2 <- eval $ fmin kh (iy + 1)
  forEach kernel_x1 kernel_x2 $ \kx -> do
    forEach kernel_y1 kernel_y2 $ \ky -> do
      forEach 0 c2 $ \oc -> do
        acc .= acc + flt![kx, ky, ic, oc] * d_output![ix - kx, iy - ky, oc]
  d_input![ix, iy, ic] .= acc

