code: def general_gradient_comp(
      layer,
      inp,
      epsilon=1.0e-5,
      loss_scale=None,
      lshape=None,
      pert_inds=None,
      pooling=False,
  ):
      # given a layer, test the bprop
      # using finite differences
  
      # run neon fprop
      layer.reset()
      inpa = layer.be.array(inp.copy())
      in_shape = lshape if lshape is not None else inpa.shape[0]
      layer.configure(in_shape)
      if layer.owns_delta:
          layer.prev_layer = True
      layer.allocate()
  
      dtree = DeltasTree()
      layer.allocate_deltas(dtree)
      dtree.allocate_buffers()
      layer.set_deltas(dtree)
  
      out = layer.fprop(inpa).get()
  
      out_shape = out.shape
  
      # scale out by random matrix...
      if loss_scale is None:
          loss_scale = np.random.random(out_shape) * 2.0 - 1.0
  
      # the loss function is:
      # loss_bl = np.sum(loss_scale * out)
  
      # run bprop, input deltas is rand_scale
      bprop_deltas = layer.bprop(
          layer.be.array(loss_scale.copy())
      ).get()
  
      max_abs_err = -1.0
      max_rel_err = -1.0
  
      inp_pert = inp.copy()
      if pert_inds is None:
          pert_inds = list(range(inp.size))
      for pert_ind in pert_inds:
          save_val = inp_pert.flat[pert_ind]
          # add/subtract perturbations to input
          inp_pert.flat[pert_ind] = save_val + epsilon
          # and run fprop on perturbed input
          layer.reset()
          layer.configure(in_shape)
          layer.allocate()
          inpa = layer.be.array(inp_pert.copy())
          out_pos = layer.fprop(inpa).get().copy()
  
          inp_pert.flat[pert_ind] = save_val - epsilon
          inpa = layer.be.array(inp_pert.copy())
          layer.reset()
          layer.configure(in_shape)
          layer.allocate()
          out_neg = layer.fprop(inpa).get().copy()
  
          # calculate the loss on outputs
          loss_pos = np.sum(loss_scale * out_pos)
          loss_neg = np.sum(loss_scale * out_neg)
          grad_est = 0.5 * (loss_pos - loss_neg) / epsilon
  
          # reset input
          inp_pert.flat[pert_ind] = save_val
  
          bprop_val = bprop_deltas.flat[pert_ind]
  
          abs_err = abs(grad_est - bprop_val)
          if abs_err > max_abs_err:
              max_abs_err = abs_err
              max_abs_vals = [grad_est, bprop_val]
  
          if (abs(grad_est) + abs(bprop_val)) == 0.0:
              rel_err = 0.0
          else:
              rel_err = float(abs_err) / (
                  abs(grad_est) + abs(bprop_val)
              )
          if rel_err > max_rel_err:
              max_rel_err = rel_err
              max_rel_vals = [grad_est, bprop_val]
  
      neon_logger.display(
          "Worst case diff %e, vals grad: %e, bprop: %e"
          % (max_abs_err, max_abs_vals[0], max_abs_vals[1])
      )
      neon_logger.display(
          "Worst case diff %e, vals grad: %e, bprop: %e"
          % (max_rel_err, max_rel_vals[0], max_rel_vals[1])
      )
      return (max_abs_err, max_rel_err)
  
imports: import numpy
  from neon import logger
  from neon.layers.container import DeltasTree
label_desc: Use image node_id 2 for calling a global function with example usage: general_gradient_comp(layer, inp, epsilon, loss_scale, lshape, pert_inds, pooling) and returns: max_abs_err,  max_rel_err