docs: def zinv(x, null=0):
      '''
      zinv(x) yields 1/x if x is not close to 0 and 0 otherwise. Automatically threads over arrays and
        supports sparse-arrays.
  
      The optional argument null (default: 0) may be given to specify that zeros in the arary x should
      instead be replaced with the given value. Note that if this value is not equal to 0, then any
      sparse array passed to zinv must be reified.
  
      The zinv function never raises an error due to divide-by-zero; if you desire this behavior, use
      the inv function instead.
      '''
      if sps.issparse(x):
          if null != 0: return zinv(x.toarray(), null=null)
          x = x.copy()
          x.data = zinv(x.data)
          try: x.eliminate_zeros()
          except Exception: pass
          return x
      else:
          x = np.asarray(x)
          z = np.isclose(x, 0)
          r = np.logical_not(z) / (x + z)
          if null == 0: return r
          r[z] = null
          return r