def test_broadcast(self): a = testing.shaped_arange((2, 1, 3, 4)) b = testing.shaped_arange((3, 1, 4)) bc = cupy.broadcast(a, b) self.assertEqual((2, 3, 3, 4), bc.shape) self.assertEqual(2 * 3 * 3 * 4, bc.size) self.assertEqual(4, bc.nd)
def _broadcast(args, params, size_error=True): brod = cupy.broadcast( *[None if p.raw else a for p, a in six.moves.zip(params, args)]) if size_error and all(not isinstance(i, cupy.ndarray) for i in brod.values): raise ValueError('Loop size is Undecided') return brod, [b if a is None else a for a, b in six.moves.zip(brod.values, args)]
def __call__(self, *args, **kwargs): """Applies the universal function to arguments elementwise. Args: args: Input arguments. Each of them can be a cupy.ndarray object or a scalar. The output arguments can be omitted or be specified by the ``out`` argument. out (cupy.ndarray): Output array. It outputs to new arrays default. dtype: Data type specifier. Returns: Output array or a tuple of output arrays. """ out = kwargs.get('out', None) dtype = kwargs.get('dtype', None) if not (len(args) == self.nin or len(args) == self.nargs): raise TypeError('Wrong number of arguments for %s' % self.name) assert all(i is not None for i in args) brod = cupy.broadcast(*args) in_args = brod.values[:self.nin] out_args = list(args[self.nin:]) if out is not None: assert len(out_args) == 0 internal.check_args_device((out,)) out_args = [out] internal.check_args_device(in_args + out_args) in_types, out_types, routine = self._guess_routine(in_args, dtype) in_args = [x if isinstance(x, cupy.ndarray) else t.type(x) for x, t in six.moves.zip(in_args, in_types)] out_args = _get_out_args(in_args, out_args, out_types, brod.shape) if len(out_args) == 1: ret = out_args[0] else: ret = tuple(out_args) if 0 in brod.shape: return ret indexer = cindexer.Indexer(brod.shape) inout_args, is_ndarray = _get_inout_args( in_args + out_args, indexer, self._params, True) param_types = _get_kernel_param_types(inout_args) out_raw_types = tuple(x.dtype for x in out_args) kern = _get_ufunc_kernel( in_types, out_types, out_raw_types, is_ndarray, param_types, self._params, routine, self.name, self._preamble) kern.linear_launch(indexer.size, inout_args) return ret
def _broadcast(args, params, use_size): value = [a if not p.raw and isinstance(a, cupy.ndarray) else None for p, a in six_zip(params, args)] if use_size: for i in value: if i is None: break else: raise ValueError("Specified 'size' can be used only " "if all of the ndarray are 'raw'.") else: for i in value: if i is not None: break else: raise ValueError('Loop size is Undecided') brod = cupy.broadcast(*value) value = [b if a is None else a for a, b in six_zip(brod.values, args)] return value, brod.shape
def noncentral_chisquare(self, df, nonc, size=None, dtype=float): """Returns an array of samples drawn from the noncentral chi-square distribution. .. warning:: This function may synchronize the device. .. seealso:: :func:`cupy.random.noncentral_chisquare` for full documentation, :meth:`numpy.random.RandomState.noncentral_chisquare <numpy.random.mtrand.RandomState.noncentral_chisquare>` """ df, nonc = cupy.asarray(df), cupy.asarray(nonc) if cupy.any(df <= 0): # synchronize! raise ValueError('df <= 0') if cupy.any(nonc < 0): # synchronize! raise ValueError('nonc < 0') if size is None: size = cupy.broadcast(df, nonc).shape y = cupy.empty(shape=size, dtype=dtype) _kernels.noncentral_chisquare_kernel(df, nonc, self._rk_seed, y) self._update_seed(y.size) return y
def triangular(self, left, mode, right, size=None, dtype=float): """Returns an array of samples drawn from the triangular distribution. .. warning:: This function may synchronize the device. .. seealso:: :func:`cupy.random.triangular` for full documentation, :meth:`numpy.random.RandomState.triangular <numpy.random.mtrand.RandomState.triangular>` """ left, mode, right = \ cupy.asarray(left), cupy.asarray(mode), cupy.asarray(right) if cupy.any(left > mode): # synchronize! raise ValueError('left > mode') if cupy.any(mode > right): # synchronize! raise ValueError('mode > right') if cupy.any(left == right): # synchronize! raise ValueError('left == right') if size is None: size = cupy.broadcast(left, mode, right).shape x = self.random_sample(size=size, dtype=dtype) return RandomState._triangular_kernel(left, mode, right, x)
def cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None): """Returns the cross product of two vectors. The cross product of ``a`` and ``b`` in :math:`R^3` is a vector perpendicular to both ``a`` and ``b``. If ``a`` and ``b`` are arrays of vectors, the vectors are defined by the last axis of ``a`` and ``b`` by default, and these axes can have dimensions 2 or 3. Where the dimension of either ``a`` or ``b`` is 2, the third component of the input vector is assumed to be zero and the cross product calculated accordingly. In cases where both input vectors have dimension 2, the z-component of the cross product is returned. Args: a (cupy.ndarray): Components of the first vector(s). b (cupy.ndarray): Components of the second vector(s). axisa (int, optional): Axis of ``a`` that defines the vector(s). By default, the last axis. axisb (int, optional): Axis of ``b`` that defines the vector(s). By default, the last axis. axisc (int, optional): Axis of ``c`` containing the cross product vector(s). Ignored if both input vectors have dimension 2, as the return is scalar. By default, the last axis. axis (int, optional): If defined, the axis of ``a``, ``b`` and ``c`` that defines the vector(s) and cross product(s). Overrides ``axisa``, ``axisb`` and ``axisc``. Returns: cupy.ndarray : Vector cross product(s). .. seealso:: :func:`numpy.cross` """ if axis is not None: axisa, axisb, axisc = (axis,) * 3 a = cupy.asarray(a) b = cupy.asarray(b) # Check axisa and axisb are within bounds axisa = internal._normalize_axis_index(axisa, a.ndim) axisb = internal._normalize_axis_index(axisb, b.ndim) # Move working axis to the end of the shape a = cupy.moveaxis(a, axisa, -1) b = cupy.moveaxis(b, axisb, -1) if a.shape[-1] not in (2, 3) or b.shape[-1] not in (2, 3): msg = ('incompatible dimensions for cross product\n' '(dimension must be 2 or 3)') raise ValueError(msg) # Create the output array shape = cupy.broadcast(a[..., 0], b[..., 0]).shape if a.shape[-1] == 3 or b.shape[-1] == 3: shape += (3,) # Check axisc is within bounds axisc = internal._normalize_axis_index(axisc, len(shape)) dtype = cupy.promote_types(a.dtype, b.dtype) cp = cupy.empty(shape, dtype) # create local aliases for readability a0 = a[..., 0] a1 = a[..., 1] if a.shape[-1] == 3: a2 = a[..., 2] b0 = b[..., 0] b1 = b[..., 1] if b.shape[-1] == 3: b2 = b[..., 2] if cp.ndim != 0 and cp.shape[-1] == 3: cp0 = cp[..., 0] cp1 = cp[..., 1] cp2 = cp[..., 2] if a.shape[-1] == 2: if b.shape[-1] == 2: # a0 * b1 - a1 * b0 cupy.multiply(a0, b1, out=cp) cp -= a1 * b0 return cp else: assert b.shape[-1] == 3 # cp0 = a1 * b2 - 0 (a2 = 0) # cp1 = 0 - a0 * b2 (a2 = 0) # cp2 = a0 * b1 - a1 * b0 cupy.multiply(a1, b2, out=cp0) cupy.multiply(a0, b2, out=cp1) cupy.negative(cp1, out=cp1) cupy.multiply(a0, b1, out=cp2) cp2 -= a1 * b0 else: assert a.shape[-1] == 3 if b.shape[-1] == 3: # cp0 = a1 * b2 - a2 * b1 # cp1 = a2 * b0 - a0 * b2 # cp2 = a0 * b1 - a1 * b0 cupy.multiply(a1, b2, out=cp0) tmp = a2 * b1 cp0 -= tmp cupy.multiply(a2, b0, out=cp1) cupy.multiply(a0, b2, out=tmp) cp1 -= tmp cupy.multiply(a0, b1, out=cp2) cupy.multiply(a1, b0, out=tmp) cp2 -= tmp else: assert b.shape[-1] == 2 # cp0 = 0 - a2 * b1 (b2 = 0) # cp1 = a2 * b0 - 0 (b2 = 0) # cp2 = a0 * b1 - a1 * b0 cupy.multiply(a2, b1, out=cp0) cupy.negative(cp0, out=cp0) cupy.multiply(a2, b0, out=cp1) cupy.multiply(a0, b1, out=cp2) cp2 -= a1 * b0 return cupy.moveaxis(cp, -1, axisc)
def __call__(self, *args, **kwargs): """Applies the universal function to arguments elementwise. Args: args: Input arguments. Each of them can be a cupy.ndarray object or a scalar. The output arguments can be omitted or be specified by the ``out`` argument. out (cupy.ndarray): Output array. It outputs to new arrays default. dtype: Data type specifier. Returns: Output array or a tuple of output arrays. """ out = kwargs.pop('out', None) dtype = kwargs.pop('dtype', None) if dtype is not None: dtype = numpy.dtype(dtype).type if kwargs: raise TypeError('Wrong arguments %s' % kwargs) n_args = len(args) if n_args != self.nin and n_args != self.nargs: raise TypeError('Wrong number of arguments for %s' % self.name) if out is None: in_args = args[:self.nin] out_args = args[self.nin:] else: if self.nout != 1: raise ValueError("Cannot use 'out' in %s" % self.name) if n_args != self.nin: raise ValueError("Cannot specify 'out' as both " "a positional and keyword argument") in_args = args out_args = out, args += out_args _check_args(args) broad = cupy.broadcast(*args) shape = broad.shape in_types, out_types, routine = _guess_routine( self.name, self._routine_cache, self._ops, in_args, dtype) out_args = _get_out_args(out_args, out_types, shape) if self.nout == 1: ret = out_args[0] else: ret = tuple(out_args) if 0 in shape: return ret inout_args = [x if isinstance(x, cupy.ndarray) else t(x) for x, t in six_zip(broad.values, in_types)] inout_args.extend(out_args) inout_args, shape = _reduce_dims(inout_args, self._params, shape) indexer = carray.Indexer(shape) inout_args.append(indexer) args_info = _get_args_info(inout_args) out_raw_types = tuple([x.dtype.type for x in out_args]) kern = _get_ufunc_kernel( in_types, out_types, routine, args_info, out_raw_types, self._params, self.name, self._preamble) kern.linear_launch(indexer.size, inout_args) return ret
def wrapper(x, y): if x.value.shape != y.value.shape: shape = np.broadcast(x.value, y.value).shape x = _core_broadcast(x, shape) y = _core_broadcast(y, shape) return fn(x, y)