def tangent(x, null=(-np.inf, np.inf), rtol=default_rtol, atol=default_atol):
if sps.issparse(x):<EOL><INDENT>x = x.copy()<EOL>x.data = tangent(x.data, null=null, rtol=rtol, atol=atol)<EOL>return x<EOL><DEDENT>else: x = np.asarray(x)<EOL>if rtol is None: rtol = default_rtol<EOL>if atol is None: atol = default_atol<EOL>try:    (nln,nlp) = null<EOL>except Exception: (nln,nlp) = (null,null)<EOL>x = np.mod(x + pi, tau) - pi<EOL>ii = None if nln is None else np.where(np.isclose(x, neghpi, rtol=rtol, atol=atol))<EOL>jj = None if nlp is None else np.where(np.isclose(x, hpi,    rtol=rtol, atol=atol))<EOL>x = np.tan(x)<EOL>if ii: x[ii] = nln<EOL>if jj: x[jj] = nlp<EOL>return x<EOL>
tangent(x) is equivalent to tan(x) except that it also works on sparse arrays.

The optional argument null (default, (-numpy.inf, numpy.inf)) may be specified to indicate what
value(s) should be assigned when x == -pi/2 or -pi/2. If only one number is given, then it is
used for both values; otherwise the first value corresponds to -pi/2 and the second to pi/2.
A value of x is considered to be equal to one of these valids based on numpy.isclose. The
optional arguments rtol and atol are passed along to isclose. If null is None, then no
replacement is performed.