def trimcoef(c, tol=0): """Removes small trailing coefficients from a polynomial. Args: c(cupy.ndarray): 1d array of coefficients from lowest to highest order. tol(number, optional): trailing coefficients whose absolute value are less than or equal to ``tol`` are trimmed. Returns: cupy.ndarray: trimmed 1d array. .. seealso:: :func:`numpy.polynomial.polyutils.trimcoef` """ if tol < 0: raise ValueError('tol must be non-negative') if c.size == 0: raise ValueError('Coefficient array is empty') if c.ndim > 1: raise ValueError('Coefficient array is not 1-d') if c.dtype.kind == 'b': raise ValueError('bool inputs are not allowed') if c.ndim == 0: c = c.ravel() c = c.astype(cupy.common_type(c), copy=False) filt = (cupy.abs(c) > tol)[::-1] ind = c.size - cupy._manipulation.add_remove._first_nonzero_krnl( filt, c.size).item() if ind == 0: return cupy.zeros_like(c[:1]) return c[: ind]
def as_series(alist, trim=True): """Returns argument as a list of 1-d arrays. Args: alist (cupy.ndarray or list of cupy.ndarray): 1-D or 2-D input array. trim (bool, optional): trim trailing zeros. Returns: list of cupy.ndarray: list of 1-D arrays. .. seealso:: :func:`numpy.polynomial.polyutils.as_series` """ arrays = [] for a in alist: if a.size == 0: raise ValueError('Coefficient array is empty') if a.ndim > 1: raise ValueError('Coefficient array is not 1-d') if a.dtype.kind == 'b': raise ValueError('Coefficient arrays have no common type') a = a.ravel() if trim: a = trimseq(a) arrays.append(a) dtype = cupy.common_type(*arrays) ret = [a.astype(dtype, copy=False) for a in arrays] return ret
def interp(x, xp, fp, left=None, right=None, period=None): """ One-dimensional linear interpolation. Args: x (cupy.ndarray): a 1D array of points on which the interpolation is performed. xp (cupy.ndarray): a 1D array of points on which the function values (``fp``) are known. fp (cupy.ndarray): a 1D array containing the function values at the the points ``xp``. left (float or complex): value to return if ``x < xp[0]``. Default is ``fp[0]``. right (float or complex): value to return if ``x > xp[-1]``. Default is ``fp[-1]``. period (None or float): a period for the x-coordinates. Parameters ``left`` and ``right`` are ignored if ``period`` is specified. Default is ``None``. Returns: cupy.ndarray: The interpolated values, same shape as ``x``. .. note:: This function may synchronize if ``left`` or ``right`` is not already on the device. .. seealso:: :func:`numpy.interp` """ if xp.ndim != 1 or fp.ndim != 1: raise ValueError('xp and fp must be 1D arrays') if xp.size != fp.size: raise ValueError('fp and xp are not of the same length') if xp.size == 0: raise ValueError('array of sample points is empty') if not x.flags.c_contiguous: raise NotImplementedError('Non-C-contiguous x is currently not ' 'supported') x_dtype = cupy.common_type(x, xp) if not cupy.can_cast(x_dtype, cupy.float64): raise TypeError('Cannot cast array data from' ' {} to {} according to the rule \'safe\''.format( x_dtype, cupy.float64)) if period is not None: # The handling of "period" below is modified from NumPy's if period == 0: raise ValueError("period must be a non-zero value") period = abs(period) left = None right = None x = x.astype(cupy.float64) xp = xp.astype(cupy.float64) # normalizing periodic boundaries x %= period xp %= period asort_xp = cupy.argsort(xp) xp = xp[asort_xp] fp = fp[asort_xp] xp = cupy.concatenate((xp[-1:] - period, xp, xp[0:1] + period)) fp = cupy.concatenate((fp[-1:], fp, fp[0:1])) assert xp.flags.c_contiguous assert fp.flags.c_contiguous # NumPy always returns float64 or complex128, so we upcast all values # on the fly in the kernel out_dtype = 'D' if fp.dtype.kind == 'c' else 'd' output = cupy.empty(x.shape, dtype=out_dtype) idx = cupy.searchsorted(xp, x, side='right') left = fp[0] if left is None else cupy.array(left, fp.dtype) right = fp[-1] if right is None else cupy.array(right, fp.dtype) kern = _get_interp_kernel(out_dtype == 'D') kern(x, idx, xp, fp, xp.size, left, right, output) return output
def diags(diagonals, offsets=0, shape=None, format=None, dtype=None): """Construct a sparse matrix from diagonals. Args: diagonals (sequence of array_like): Sequence of arrays containing the matrix diagonals, corresponding to `offsets`. offsets (sequence of int or an int): Diagonals to set: - k = 0 the main diagonal (default) - k > 0 the k-th upper diagonal - k < 0 the k-th lower diagonal shape (tuple of int): Shape of the result. If omitted, a square matrix large enough to contain the diagonals is returned. format ({"dia", "csr", "csc", "lil", ...}): Matrix format of the result. By default (format=None) an appropriate sparse matrix format is returned. This choice is subject to change. dtype (dtype): Data type of the matrix. Returns: cupyx.scipy.sparse.spmatrix: Generated matrix. Notes: This function differs from `spdiags` in the way it handles off-diagonals. The result from `diags` is the sparse equivalent of:: cupy.diag(diagonals[0], offsets[0]) + ... + cupy.diag(diagonals[k], offsets[k]) Repeated diagonal offsets are disallowed. """ # if offsets is not a sequence, assume that there's only one diagonal if sputils.isscalarlike(offsets): # now check that there's actually only one diagonal if len(diagonals) == 0 or sputils.isscalarlike(diagonals[0]): diagonals = [cupy.atleast_1d(diagonals)] else: raise ValueError('Different number of diagonals and offsets.') else: diagonals = list(map(cupy.atleast_1d, diagonals)) if isinstance(offsets, cupy.ndarray): offsets = offsets.get() offsets = numpy.atleast_1d(offsets) # Basic check if len(diagonals) != len(offsets): raise ValueError('Different number of diagonals and offsets.') # Determine shape, if omitted if shape is None: m = len(diagonals[0]) + abs(int(offsets[0])) shape = (m, m) # Determine data type, if omitted if dtype is None: dtype = cupy.common_type(*diagonals) # Construct data array m, n = shape M = max([min(m + offset, n - offset) + max(0, offset) for offset in offsets]) M = max(0, M) data_arr = cupy.zeros((len(offsets), M), dtype=dtype) K = min(m, n) for j, diagonal in enumerate(diagonals): offset = offsets[j] k = max(0, offset) length = min(m + offset, n - offset, K) if length < 0: raise ValueError( 'Offset %d (index %d) out of bounds' % (offset, j)) try: data_arr[j, k:k+length] = diagonal[..., :length] except ValueError: if len(diagonal) != length and len(diagonal) != 1: raise ValueError( 'Diagonal length (index %d: %d at offset %d) does not ' 'agree with matrix size (%d, %d).' % ( j, len(diagonal), offset, m, n)) raise return dia.dia_matrix((data_arr, offsets), shape=(m, n)).asformat(format)