def where(condition, x=None, y=None): """Return elements, either from x or y, depending on condition. If only condition is given, return ``condition.nonzero()``. Args: condition (cupy.ndarray): When True, take x, otherwise take y. x (cupy.ndarray): Values from which to choose on ``True``. y (cupy.ndarray): Values from which to choose on ``False``. Returns: cupy.ndarray: Each element of output contains elements of ``x`` when ``condition`` is ``True``, otherwise elements of ``y``. If only ``condition`` is given, return the tuple ``condition.nonzero()``, the indices where ``condition`` is True. .. warning:: This function may synchronize the device if both ``x`` and ``y`` are omitted. .. seealso:: :func:`numpy.where` """ missing = (x is None, y is None).count(True) if missing == 1: raise ValueError('Must provide both \'x\' and \'y\' or neither.') if missing == 2: return nonzero(condition) # may synchronize if fusion._is_fusing(): return fusion._call_ufunc(_where_ufunc, condition, x, y) return _where_ufunc(condition.astype('?'), x, y)
def clip(a, a_min=None, a_max=None, out=None): """Clips the values of an array to a given interval. This is equivalent to ``maximum(minimum(a, a_max), a_min)``, while this function is more efficient. Args: a (cupy.ndarray): The source array. a_min (scalar, cupy.ndarray or None): The left side of the interval. When it is ``None``, it is ignored. a_max (scalar, cupy.ndarray or None): The right side of the interval. When it is ``None``, it is ignored. out (cupy.ndarray): Output array. Returns: cupy.ndarray: Clipped array. .. seealso:: :func:`numpy.clip` """ if fusion._is_fusing(): return fusion._call_ufunc(_math.clip, a, a_min, a_max, out=out) # TODO(okuta): check type return a.clip(a_min, a_max, out=out)
def copyto(dst, src, casting='same_kind', where=None): """Copies values from one array to another with broadcasting. This function can be called for arrays on different devices. In this case, casting, ``where``, and broadcasting is not supported, and an exception is raised if these are used. Args: dst (cupy.ndarray): Target array. src (cupy.ndarray): Source array. casting (str): Casting rule. See :func:`numpy.can_cast` for detail. where (cupy.ndarray of bool): If specified, this array acts as a mask, and an element is copied only if the corresponding element of ``where`` is True. .. seealso:: :func:`numpy.copyto` """ src_type = type(src) src_is_python_scalar = src_type in ( int, bool, float, complex, fusion._FusionVarScalar, _fusion_interface._ScalarProxy) if src_is_python_scalar: src_dtype = numpy.dtype(type(src)) can_cast = numpy.can_cast(src, dst.dtype, casting) else: src_dtype = src.dtype can_cast = numpy.can_cast(src_dtype, dst.dtype, casting) if not can_cast: raise TypeError('Cannot cast %s to %s in %s casting mode' % (src_dtype, dst.dtype, casting)) if fusion._is_fusing(): if where is None: _core.elementwise_copy(src, dst) else: fusion._call_ufunc(search._where_ufunc, where, src, dst, dst) return if where is not None: _core.elementwise_copy(src, dst, _where=where) return if dst.size == 0: return if src_is_python_scalar: dst.fill(src) return if _can_memcpy(dst, src): dst.data.copy_from_async(src.data, src.nbytes) return device = dst.device with device: if src.device != device: src = src.copy() _core.elementwise_copy(src, dst)
def copy(a, order='K'): """Creates a copy of a given array on the current device. This function allocates the new array on the current device. If the given array is allocated on the different device, then this function tries to copy the contents over the devices. Args: a (cupy.ndarray): The source array. order ({'C', 'F', 'A', 'K'}): Row-major (C-style) or column-major (Fortran-style) order. When ``order`` is ``'A'``, it uses ``'F'`` if ``a`` is column-major and uses ``'C'`` otherwise. And when ``order`` is ``'K'``, it keeps strides as closely as possible. Returns: cupy.ndarray: The copy of ``a`` on the current device. .. seealso:: :func:`numpy.copy`, :meth:`cupy.ndarray.copy` """ if fusion._is_fusing(): if order != 'K': raise NotImplementedError( 'cupy.copy does not support `order` in fusion yet.') return fusion._call_ufunc(_core.elementwise_copy, a) # If the current device is different from the device of ``a``, then this # function allocates a new array on the current device, and copies the # contents over the devices. return a.copy(order=order)
def imag(val): '''Returns the imaginary part of the elements of the array. .. seealso:: :func:`numpy.imag` ''' if fusion._is_fusing(): return fusion._call_ufunc(_imag_ufunc, val) if not isinstance(val, _core.ndarray): val = _core.array(val) return val.imag
def real(val): '''Returns the real part of the elements of the array. .. seealso:: :func:`numpy.real` ''' if fusion._is_fusing(): return fusion._call_ufunc(_real_ufunc, val) if not isinstance(val, _core.ndarray): val = _core.array(val) return val.real
def around(a, decimals=0, out=None): """Rounds to the given number of decimals. Args: a (cupy.ndarray): The source array. decimals (int): Number of decimal places to round to (default: 0). If decimals is negative, it specifies the number of positions to the left of the decimal point. out (cupy.ndarray): Output array. Returns: cupy.ndarray: Rounded array. .. seealso:: :func:`numpy.around` """ if fusion._is_fusing(): return fusion._call_ufunc(_core.core._round_ufunc, a, decimals, out=out) a = _core.array(a, copy=False) return a.round(decimals, out=out)
def copyto(dst, src, casting='same_kind', where=None): """Copies values from one array to another with broadcasting. This function can be called for arrays on different devices. In this case, casting, ``where``, and broadcasting is not supported, and an exception is raised if these are used. Args: dst (cupy.ndarray): Target array. src (cupy.ndarray): Source array. casting (str): Casting rule. See :func:`numpy.can_cast` for detail. where (cupy.ndarray of bool): If specified, this array acts as a mask, and an element is copied only if the corresponding element of ``where`` is True. .. seealso:: :func:`numpy.copyto` """ src_is_numpy_scalar = False src_type = type(src) src_is_python_scalar = src_type in ( int, bool, float, complex, fusion._FusionVarScalar, _fusion_interface._ScalarProxy) if src_is_python_scalar: src_dtype = numpy.dtype(type(src)) can_cast = numpy.can_cast(src, dst.dtype, casting) elif isinstance(src, numpy.ndarray) or numpy.isscalar(src): if src.size != 1: raise ValueError( 'non-scalar numpy.ndarray cannot be used for copyto') src_dtype = src.dtype can_cast = numpy.can_cast(src, dst.dtype, casting) src = src.item() src_is_numpy_scalar = True else: src_dtype = src.dtype can_cast = numpy.can_cast(src_dtype, dst.dtype, casting) if not can_cast: raise TypeError('Cannot cast %s to %s in %s casting mode' % (src_dtype, dst.dtype, casting)) if fusion._is_fusing(): # TODO(kataoka): NumPy allows stripping leading unit dimensions. # But fusion array proxy does not currently support # `shape` and `squeeze`. if where is None: _core.elementwise_copy(src, dst) else: fusion._call_ufunc(search._where_ufunc, where, src, dst, dst) return if not src_is_python_scalar and not src_is_numpy_scalar: # Check broadcast condition # - for fast-paths and # - for a better error message (than ufunc's). # NumPy allows stripping leading unit dimensions. if not all([ s in (d, 1) for s, d in itertools.zip_longest( reversed(src.shape), reversed(dst.shape), fillvalue=1) ]): raise ValueError( "could not broadcast input array " f"from shape {src.shape} into shape {dst.shape}") squeeze_ndim = src.ndim - dst.ndim if squeeze_ndim > 0: # always succeeds because broadcast conition is checked. src = src.squeeze(tuple(range(squeeze_ndim))) if where is not None: _core.elementwise_copy(src, dst, _where=where) return if dst.size == 0: return if src_is_python_scalar or src_is_numpy_scalar: _core.elementwise_copy(src, dst) return if _can_memcpy(dst, src): dst.data.copy_from_async(src.data, src.nbytes) return device = dst.device prev_device = runtime.getDevice() try: runtime.setDevice(device.id) if src.device != device: src = src.copy() _core.elementwise_copy(src, dst) finally: runtime.setDevice(prev_device)