docs: def arctangent(y, x=None, null=0, broadcast=False, rtol=default_rtol, atol=default_atol):
      '''
      arctangent(x) is equivalent to atan(x) except that it also works on sparse arrays.
      arctangent(y,x) is equivalent to atan2(y,x) except that it also works on sparse arrays.
  
      The optional argument null (default: 0) specifies the result found when y and x both equal 0. If
      null is None, then an error is raised on this condition. Note that if null is not 0, then it is
      more likely that sparse arrays will have to be reified. If null is set to None, then no attempt
      is made to detect null values.
  
      The optional argument broadcast (default: False) specifies whether numpy-like (True) or
      Mathematica-like (False) broadcasting should be used. Broadcasting resolves ambiguous calls to
      arctangent, such as artangent([a,b,c], [[d,e,f],[g,h,i],[j,k,l]]). If broadcasting is True, 
      arctangent(y,x) behaves like numpy.arctan2(y,x), so [a,b,c] is interpreted like [[a,b,c],
      [a,b,c], [a,b,c]]. If broadcasting is False, [a,b,c] is interpreted like [[a,a,a], [b,b,b],
      [c,c,c]].
      '''
      if sps.issparse(y):
          if x is None:
              y = y.copy()
              y.data = np.arctan(y.data)
              return y
          elif null is not None and null != 0:
              # we need to reify anyway...
              y = y.toarray()
              if sps.issparse(x): x = x.toarray()
          else:
              # anywhere that y is zero must have an arctan of 0 or null (which is 0), so we only have
              # to look at those values that are non-zero in y
              (yr,yc,yv) = sps.find(y)
              xv = np.asarray(x[rr,rc].flat)
              res = y.copy()
              res.data = arctangent(yv, xv, null=null)
              res.eliminate_zeros()
              return res
      elif sps.issparse(x): x = x.toarray()
      # we should start by broadcasting if need be...
      if x is None: res = np.arctan(y)
      else:
          if not broadcast: (y,x) = unbroadcast(y,x)
          res = np.arctan2(y, x)
          # find the zeros, if need-be
          if null is not None:
              if rtol is None: rtol = default_rtol
              if atol is None: atol = default_atol
              # even if null is none, we do this because the rtol and atol may be more lenient than
              # the tolerance used by arctan2.
              z = np.isclose(y, 0, rtol=rtol, atol=atol) & np.isclose(x, 0, rtol=rtol, atol=atol)
              res[z] = null
      return res