def real_if_close(a, tol=100): """ If complex input returns a real array if complex parts are close to zero. "Close to zero" is defined as `tol` * (machine epsilon of the type for `a`). Parameters ---------- a : array_like Input array. tol : float Tolerance in machine epsilons for the complex part of the elements in the array. Returns ------- out : ndarray If `a` is real, the type of `a` is used for the output. If `a` has complex elements, the returned type is float. See Also -------- real, imag, angle Notes ----- Machine epsilon varies from machine to machine and between data types but Python floats on most platforms have a machine epsilon equal to 2.2204460492503131e-16. You can use 'np.finfo(float).eps' to print out the machine epsilon for floats. Examples -------- >>> np.finfo(float).eps 2.2204460492503131e-16 # may vary >>> np.real_if_close([2.1 + 4e-14j], tol=1000) array([2.1]) >>> np.real_if_close([2.1 + 4e-13j], tol=1000) array([2.1+4.e-13j]) """ a = asanyarray(a) if not issubclass(a.dtype.type, _nx.complexfloating): return a if tol > 1: from numpy.core import getlimits f = getlimits.finfo(a.dtype.type) tol = f.eps * tol if _nx.all(_nx.absolute(a.imag) < tol): a = a.real return a
def real_if_close(a, tol=100): """ If complex input returns a real array if complex parts are close to zero. "Close to zero" is defined as `tol` * (machine epsilon of the type for `a`). Parameters ---------- a : array_like Input array. tol : float Tolerance in machine epsilons for the complex part of the elements in the array. Returns ------- out : ndarray If `a` is real, the type of `a` is used for the output. If `a` has complex elements, the returned type is float. See Also -------- real, imag, angle Notes ----- Machine epsilon varies from machine to machine and between data types but Python floats on most platforms have a machine epsilon equal to 2.2204460492503131e-16. You can use 'np.finfo(float).eps' to print out the machine epsilon for floats. Examples -------- >>> np.finfo(float).eps 2.2204460492503131e-16 >>> np.real_if_close([2.1 + 4e-14j], tol=1000) array([ 2.1]) >>> np.real_if_close([2.1 + 4e-13j], tol=1000) array([ 2.1 +4.00000000e-13j]) """ a = asanyarray(a) if not issubclass(a.dtype.type, _nx.complexfloating): return a if tol > 1: from numpy.core import getlimits f = getlimits.finfo(a.dtype.type) tol = f.eps * tol if _nx.all(_nx.absolute(a.imag) < tol): a = a.real return a
def poly(seq_of_zeros): """ Find the coefficients of a polynomial with the given sequence of roots. Returns the coefficients of the polynomial whose leading coefficient is one for the given sequence of zeros (multiple roots must be included in the sequence as many times as their multiplicity; see Examples). A square matrix (or array, which will be treated as a matrix) can also be given, in which case the coefficients of the characteristic polynomial of the matrix are returned. Parameters ---------- seq_of_zeros : array_like, shape (N,) or (N, N) A sequence of polynomial roots, or a square array or matrix object. Returns ------- c : ndarray 1D array of polynomial coefficients from highest to lowest degree: ``c[0] * x**(N) + c[1] * x**(N-1) + ... + c[N-1] * x + c[N]`` where c[0] always equals 1. Raises ------ ValueError If input is the wrong shape (the input must be a 1-D or square 2-D array). See Also -------- polyval : Compute polynomial values. roots : Return the roots of a polynomial. polyfit : Least squares polynomial fit. poly1d : A one-dimensional polynomial class. Notes ----- Specifying the roots of a polynomial still leaves one degree of freedom, typically represented by an undetermined leading coefficient. [1]_ In the case of this function, that coefficient - the first one in the returned array - is always taken as one. (If for some reason you have one other point, the only automatic way presently to leverage that information is to use ``polyfit``.) The characteristic polynomial, :math:`p_a(t)`, of an `n`-by-`n` matrix **A** is given by :math:`p_a(t) = \\mathrm{det}(t\\, \\mathbf{I} - \\mathbf{A})`, where **I** is the `n`-by-`n` identity matrix. [2]_ References ---------- .. [1] M. Sullivan and M. Sullivan, III, "Algebra and Trignometry, Enhanced With Graphing Utilities," Prentice-Hall, pg. 318, 1996. .. [2] G. Strang, "Linear Algebra and Its Applications, 2nd Edition," Academic Press, pg. 182, 1980. Examples -------- Given a sequence of a polynomial's zeros: >>> np.poly((0, 0, 0)) # Multiple root example array([1, 0, 0, 0]) The line above represents z**3 + 0*z**2 + 0*z + 0. >>> np.poly((-1./2, 0, 1./2)) array([ 1. , 0. , -0.25, 0. ]) The line above represents z**3 - z/4 >>> np.poly((np.random.random(1.)[0], 0, np.random.random(1.)[0])) array([ 1. , -0.77086955, 0.08618131, 0. ]) #random Given a square array object: >>> P = np.array([[0, 1./3], [-1./2, 0]]) >>> np.poly(P) array([ 1. , 0. , 0.16666667]) Note how in all cases the leading coefficient is always 1. """ seq_of_zeros = atleast_1d(seq_of_zeros) sh = seq_of_zeros.shape if len(sh) == 2 and sh[0] == sh[1] and sh[0] != 0: seq_of_zeros = eigvals(seq_of_zeros) elif len(sh) == 1: dt = seq_of_zeros.dtype # Let object arrays slip through, e.g. for arbitrary precision if dt != object: seq_of_zeros = seq_of_zeros.astype(mintypecode(dt.char)) else: raise ValueError("input must be 1d or non-empty square 2d array.") if len(seq_of_zeros) == 0: return 1.0 dt = seq_of_zeros.dtype a = ones((1,), dtype=dt) for k in range(len(seq_of_zeros)): a = NX.convolve(a, array([1, -seq_of_zeros[k]], dtype=dt), mode='full') if issubclass(a.dtype.type, NX.complexfloating): # if complex roots are all complex conjugates, the roots are real. roots = NX.asarray(seq_of_zeros, complex) if NX.all(NX.sort(roots) == NX.sort(roots.conjugate())): a = a.real.copy() return a
def isclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False): """ Returns a boolean array where two arrays are element-wise equal within a tolerance. The tolerance values are positive, typically very small numbers. The relative difference (`rtol` * abs(`b`)) and the absolute difference `atol` are added together to compare against the absolute difference between `a` and `b`. Parameters ---------- a, b : array_like Input arrays to compare. rtol : float The relative tolerance parameter (see Notes). atol : float The absolute tolerance parameter (see Notes). equal_nan : bool Whether to compare NaN's as equal. If True, NaN's in `a` will be considered equal to NaN's in `b` in the output array. Returns ------- y : array_like Returns a boolean array of where `a` and `b` are equal within the given tolerance. If both `a` and `b` are scalars, returns a single boolean value. See Also -------- allclose Notes ----- .. versionadded:: 1.7.0 For finite values, isclose uses the following equation to test whether two floating point values are equivalent. absolute(`a` - `b`) <= (`atol` + `rtol` * absolute(`b`)) The above equation is not symmetric in `a` and `b`, so that `isclose(a, b)` might be different from `isclose(b, a)` in some rare cases. Examples -------- >>> np.isclose([1e10,1e-7], [1.00001e10,1e-8]) array([True, False]) >>> np.isclose([1e10,1e-8], [1.00001e10,1e-9]) array([True, True]) >>> np.isclose([1e10,1e-8], [1.0001e10,1e-9]) array([False, True]) >>> np.isclose([1.0, np.nan], [1.0, np.nan]) array([True, False]) >>> np.isclose([1.0, np.nan], [1.0, np.nan], equal_nan=True) array([True, True]) """ def within_tol(x, y, atol, rtol): with errstate(invalid='ignore'): result = less_equal(abs(x - y), atol + rtol * abs(y)) if isscalar(a) and isscalar(b): result = bool(result) return result x = array(a, copy=False, subok=True, ndmin=1) y = array(b, copy=False, subok=True, ndmin=1) # Make sure y is an inexact type to avoid bad behavior on abs(MIN_INT). # This will cause casting of x later. Also, make sure to allow subclasses # (e.g., for numpy.ma). dt = multiarray.result_type(y, 1.) y = array(y, dtype=dt, copy=False, subok=True) xfin = isfinite(x) yfin = isfinite(y) if all(xfin) and all(yfin): return within_tol(x, y, atol, rtol) else: finite = xfin & yfin cond = zeros_like(finite, subok=True) # Because we're using boolean indexing, x & y must be the same shape. # Ideally, we'd just do x, y = broadcast_arrays(x, y). It's in # lib.stride_tricks, though, so we can't import it here. x = x * ones_like(cond) y = y * ones_like(cond) # Avoid subtraction with infinite/nan values... cond[finite] = within_tol(x[finite], y[finite], atol, rtol) # Check for equality of infinite values... cond[~finite] = (x[~finite] == y[~finite]) if equal_nan: # Make NaN == NaN both_nan = isnan(x) & isnan(y) cond[both_nan] = both_nan[both_nan] if isscalar(a) and isscalar(b): return bool(cond) else: return cond