def _comparison(self, other, op, op_name): if _util.isscalarlike(other): data = cupy.asarray(other, dtype=self.dtype).reshape(1) if numpy.isnan(data[0]): if op_name == '_ne_': return csr_matrix(cupy.ones(self.shape, dtype=numpy.bool_)) else: return csr_matrix(self.shape, dtype=numpy.bool_) indices = cupy.zeros((1, ), dtype=numpy.int32) indptr = cupy.arange(2, dtype=numpy.int32) other = csr_matrix((data, indices, indptr), shape=(1, 1)) return binopt_csr(self, other, op_name) elif _util.isdense(other): return op(self.todense(), other) elif isspmatrix_csr(other): self.sum_duplicates() other.sum_duplicates() if op_name in ('_ne_', '_lt_', '_gt_'): return binopt_csr(self, other, op_name) warnings.warn( "Comparing sparse matrices using ==, <=, and >= is " "inefficient, try using !=, <, or > instead.", SparseEfficiencyWarning) if op_name == '_eq_': opposite_op_name = '_ne_' elif op_name == '_le_': opposite_op_name = '_gt_' elif op_name == '_ge_': opposite_op_name = '_lt_' res = binopt_csr(self, other, opposite_op_name) out = cupy.logical_not(res.toarray()) return csr_matrix(out) raise NotImplementedError
def _maximum_minimum(self, other, cupy_op, op_name, dense_check): if _util.isscalarlike(other): other = cupy.asarray(other, dtype=self.dtype) if dense_check(other): dtype = self.dtype # Note: This is a work-around to make the output dtype the same # as SciPy. It might be SciPy version dependent. if dtype == numpy.float32: dtype = numpy.float64 elif dtype == numpy.complex64: dtype = numpy.complex128 dtype = cupy.result_type(dtype, other) other = other.astype(dtype, copy=False) # Note: The computation steps below are different from SciPy. new_array = cupy_op(self.todense(), other) return csr_matrix(new_array) else: self.sum_duplicates() new_data = cupy_op(self.data, other) return csr_matrix((new_data, self.indices, self.indptr), shape=self.shape, dtype=self.dtype) elif _util.isdense(other): self.sum_duplicates() other = cupy.atleast_2d(other) return cupy_op(self.todense(), other) elif isspmatrix_csr(other): self.sum_duplicates() other.sum_duplicates() return binopt_csr(self, other, op_name) raise NotImplementedError
def __truediv__(self, other): """Point-wise division by another matrix, vector or scalar""" if _util.isscalarlike(other): dtype = self.dtype if dtype == numpy.float32: # Note: This is a work-around to make the output dtype the same # as SciPy. It might be SciPy version dependent. dtype = numpy.float64 dtype = cupy.result_type(dtype, other) d = cupy.reciprocal(other, dtype=dtype) return multiply_by_scalar(self, d) elif _util.isdense(other): other = cupy.atleast_2d(other) check_shape_for_pointwise_op(self.shape, other.shape) return self.todense() / other elif base.isspmatrix(other): # Note: If broadcasting is needed, an exception is raised here for # compatibility with SciPy, as SciPy does not support broadcasting # in the "sparse / sparse" case. check_shape_for_pointwise_op(self.shape, other.shape, allow_broadcasting=False) dtype = numpy.promote_types(self.dtype, other.dtype) if dtype.char not in 'FD': dtype = numpy.promote_types(numpy.float64, dtype) # Note: The following implementation converts two sparse matrices # into dense matrices and then performs a point-wise division, # which can use lots of memory. self_dense = self.todense().astype(dtype, copy=False) return self_dense / other.todense() raise NotImplementedError
def __pow__(self, other): """Calculates n-th power of the matrix. This method calculates n-th power of a given matrix. The matrix must be a squared matrix, and a given exponent must be an integer. Args: other (int): Exponent. Returns: cupyx.scipy.sparse.spmatrix: A sparse matrix representing n-th power of this matrix. """ m, n = self.shape if m != n: raise TypeError('matrix is not square') if _util.isintlike(other): other = int(other) if other < 0: raise ValueError('exponent must be >= 0') if other == 0: import cupyx.scipy.sparse return cupyx.scipy.sparse.identity(m, dtype=self.dtype, format='csr') elif other == 1: return self.copy() else: tmp = self.__pow__(other // 2) if other % 2: return self * tmp * tmp else: return tmp * tmp elif _util.isscalarlike(other): raise ValueError('exponent must be an integer') else: return NotImplemented
def __rmatmul__(self, other): if _util.isscalarlike(other): raise ValueError('Scalar operands are not allowed, ' 'use \'*\' instead') return self.__rmul__(other)