def compute_error(x_obj, x_approx): ''' Error absoluto o relativo entre x_obj y x_approx. ''' if cp.linalg.norm(x_obj) > cp.nextafter(0, 1): Err = cp.linalg.norm(x_obj - x_approx) / cp.linalg.norm(x_obj) else: Err = cp.linalg.norm(x_obj - x_approx) return Err
def histogram(x, bins=10, range=None, weights=None, density=False): """Computes the histogram of a set of data. Args: x (cupy.ndarray): Input array. bins (int or cupy.ndarray): If ``bins`` is an int, it represents the number of bins. If ``bins`` is an :class:`~cupy.ndarray`, it represents a bin edges. range (2-tuple of float, optional): The lower and upper range of the bins. If not provided, range is simply ``(x.min(), x.max())``. Values outside the range are ignored. The first element of the range must be less than or equal to the second. `range` affects the automatic bin computation as well. While bin width is computed to be optimal based on the actual data within `range`, the bin count will fill the entire range including portions containing no data. density (bool, optional): If False, the default, returns the number of samples in each bin. If True, returns the probability *density* function at the bin, ``bin_count / sample_count / bin_volume``. weights (cupy.ndarray, optional): An array of weights, of the same shape as `x`. Each value in `x` only contributes its associated weight towards the bin count (instead of 1). Returns: tuple: ``(hist, bin_edges)`` where ``hist`` is a :class:`cupy.ndarray` storing the values of the histogram, and ``bin_edges`` is a :class:`cupy.ndarray` storing the bin edges. .. warning:: This function may synchronize the device. .. seealso:: :func:`numpy.histogram` """ if x.dtype.kind == 'c': # TODO(unno): comparison between complex numbers is not implemented raise NotImplementedError('complex number is not supported') if not isinstance(x, cupy.ndarray): raise ValueError('x must be a cupy.ndarray') x, weights = _ravel_and_check_weights(x, weights) bin_edges = _get_bin_edges(x, bins, range) if weights is None: y = cupy.zeros(bin_edges.size - 1, dtype='l') for accelerator in _accelerator.get_routine_accelerators(): # CUB uses int for bin counts # TODO(leofang): support >= 2^31 elements in x? if (accelerator == _accelerator.ACCELERATOR_CUB and x.size <= 0x7fffffff and bin_edges.size <= 0x7fffffff): # Need to ensure the dtype of bin_edges as it's needed for both # the CUB call and the correction later assert isinstance(bin_edges, cupy.ndarray) if numpy.issubdtype(x.dtype, numpy.integer): bin_type = numpy.float else: bin_type = numpy.result_type(bin_edges.dtype, x.dtype) if (bin_type == numpy.float16 and not common._is_fp16_supported()): bin_type = numpy.float32 x = x.astype(bin_type, copy=False) acc_bin_edge = bin_edges.astype(bin_type, copy=True) # CUB's upper bin boundary is exclusive for all bins, including # the last bin, so we must shift it to comply with NumPy if x.dtype.kind in 'ui': acc_bin_edge[-1] += 1 elif x.dtype.kind == 'f': last = acc_bin_edge[-1] acc_bin_edge[-1] = cupy.nextafter(last, last + 1) if runtime.is_hip: y = y.astype(cupy.uint64, copy=False) y = cub.device_histogram(x, acc_bin_edge, y) if runtime.is_hip: y = y.astype(cupy.int64, copy=False) break else: _histogram_kernel(x, bin_edges, bin_edges.size, y) else: simple_weights = (cupy.can_cast(weights.dtype, cupy.float64) or cupy.can_cast(weights.dtype, cupy.complex128)) if not simple_weights: # object dtype such as Decimal are supported in NumPy, but not here raise NotImplementedError( 'only weights with dtype that can be cast to float or complex ' 'are supported') if weights.dtype.kind == 'c': y = cupy.zeros(bin_edges.size - 1, dtype=cupy.complex128) _weighted_histogram_kernel(x, bin_edges, bin_edges.size, weights.real, y.real) _weighted_histogram_kernel(x, bin_edges, bin_edges.size, weights.imag, y.imag) else: if weights.dtype.kind in 'bui': y = cupy.zeros(bin_edges.size - 1, dtype=int) else: y = cupy.zeros(bin_edges.size - 1, dtype=cupy.float64) _weighted_histogram_kernel(x, bin_edges, bin_edges.size, weights, y) if density: db = cupy.array(cupy.diff(bin_edges), cupy.float64) return y / db / y.sum(), bin_edges return y, bin_edges