def test_isscalarlike(self): assert_equal(sputils.isscalarlike(3.0),True) assert_equal(sputils.isscalarlike(-4),True) assert_equal(sputils.isscalarlike(2.5),True) assert_equal(sputils.isscalarlike(1 + 3j),True) assert_equal(sputils.isscalarlike(np.array(3)),True) assert_equal(sputils.isscalarlike( "16" ), True) assert_equal(sputils.isscalarlike( np.array([3])), False) assert_equal(sputils.isscalarlike( [[3]] ), False) assert_equal(sputils.isscalarlike( (1,) ), False) assert_equal(sputils.isscalarlike( (1,2) ), False)
def test_isscalarlike(self): assert_equal(sputils.isscalarlike(3.0), True) assert_equal(sputils.isscalarlike(-4), True) assert_equal(sputils.isscalarlike(2.5), True) assert_equal(sputils.isscalarlike(1 + 3j), True) assert_equal(sputils.isscalarlike(np.array(3)), True) assert_equal(sputils.isscalarlike("16"), True) assert_equal(sputils.isscalarlike(np.array([3])), False) assert_equal(sputils.isscalarlike([[3]]), False) assert_equal(sputils.isscalarlike((1, )), False) assert_equal(sputils.isscalarlike((1, 2)), False)
def __radd__(self, other): # First check if argument is a scalar if isscalarlike(other): new = dok_matrix(self.shape, dtype=self.dtype) # Add this scalar to every element. M, N = self.shape for i in xrange(M): for j in xrange(N): aij = self.get((i, j), 0) + other if aij != 0: new[i, j] = aij elif isinstance(other, dok_matrix): if other.shape != self.shape: raise ValueError("matrix dimensions are not equal") new = dok_matrix(self.shape, dtype=self.dtype) new.update(self) for key in other: new[key] += other[key] elif isspmatrix(other): csc = self.tocsc() new = csc + other elif isdense(other): new = other + self.todense() else: raise TypeError("data type not understood") return new
def __add__(self, other): # First check if argument is a scalar if isscalarlike(other): res_dtype = upcast_scalar(self.dtype, other) new = dok_matrix(self.shape, dtype=res_dtype) # Add this scalar to every element. M, N = self.shape for i in xrange(M): for j in xrange(N): aij = self.get((i, j), 0) + other if aij != 0: new[i, j] = aij # new.dtype.char = self.dtype.char elif isinstance(other, dok_matrix): if other.shape != self.shape: raise ValueError("matrix dimensions are not equal") # We could alternatively set the dimensions to the largest of # the two matrices to be summed. Would this be a good idea? res_dtype = upcast(self.dtype, other.dtype) new = dok_matrix(self.shape, dtype=res_dtype) new.update(self) for key in other.keys(): new[key] += other[key] elif isspmatrix(other): csc = self.tocsc() new = csc + other elif isdense(other): new = self.todense() + other else: raise TypeError("data type not understood") return new
def _inequality(self, other, op, op_name, bad_scalar_msg): # Scalar other. if isscalarlike(other): if 0 == other and op_name in ('_le_', '_ge_'): raise NotImplementedError(" >= and <= don't work with 0.") elif op(0, other): warn(bad_scalar_msg, SparseEfficiencyWarning) other_arr = np.empty(self.shape, dtype=np.result_type(other)) other_arr.fill(other) other_arr = csr_matrix(other_arr) return self._binopt(other_arr, op_name) else: return self._scalar_binopt(other, op) # Dense other. elif isdense(other): return op(self.todense(), other) # Sparse other. elif isspmatrix(other): #TODO sparse broadcasting if self.shape != other.shape: raise ValueError("inconsistent shapes") elif self.format != other.format: other = other.asformat(self.format) if op_name not in ('_ge_', '_le_'): return self._binopt(other, op_name) warn( "Comparing sparse matrices using >= and <= is inefficient, " "using <, >, or !=, instead.", SparseEfficiencyWarning) all_true = _all_true(self.shape) res = self._binopt(other, '_gt_' if op_name == '_le_' else '_lt_') return all_true - res else: raise ValueError("Operands could not be compared.")
def __eq__(self, other): # Scalar other. if isscalarlike(other): if np.isnan(other): return csr_matrix(self.shape, dtype=np.bool_) if other == 0: warn("Comparing a sparse matrix with 0 using == is inefficient" ", try using != instead.", SparseEfficiencyWarning) all_true = _all_true(self.shape) inv = self._scalar_binopt(other, operator.ne) return all_true - inv else: return self._scalar_binopt(other, operator.eq) # Dense other. elif isdense(other): return self.todense() == other # Sparse other. elif isspmatrix(other): warn("Comparing sparse matrices using == is inefficient, try using" " != instead.", SparseEfficiencyWarning) #TODO sparse broadcasting if self.shape != other.shape: return False elif self.format != other.format: other = other.asformat(self.format) res = self._binopt(other,'_ne_') all_true = _all_true(self.shape) return all_true - res else: return False
def __ne__(self, other): # Scalar other. if isscalarlike(other): if np.isnan(other): warn("Comparing a sparse matrix with nan using != is inefficient", SparseEfficiencyWarning) all_true = _all_true(self.shape) return all_true elif other != 0: warn("Comparing a sparse matrix with a nonzero scalar using !=" " is inefficient, try using == instead.", SparseEfficiencyWarning) all_true = _all_true(self.shape) inv = self._scalar_binopt(other, operator.eq) return all_true - inv else: return self._scalar_binopt(other, operator.ne) # Dense other. elif isdense(other): return self.todense() != other # Sparse other. elif isspmatrix(other): #TODO sparse broadcasting if self.shape != other.shape: return True elif self.format != other.format: other = other.asformat(self.format) return self._binopt(other,'_ne_') else: return True
def __ne__(self, other): # Scalar other. if isscalarlike(other): if np.isnan(other): warn( "Comparing a sparse matrix with nan using != is inefficient", SparseEfficiencyWarning) all_true = _all_true(self.shape) return all_true elif other != 0: warn( "Comparing a sparse matrix with a nonzero scalar using !=" " is inefficient, try using == instead.", SparseEfficiencyWarning) all_true = _all_true(self.shape) inv = self._scalar_binopt(other, operator.eq) return all_true - inv else: return self._scalar_binopt(other, operator.ne) # Dense other. elif isdense(other): return self.todense() != other # Sparse other. elif isspmatrix(other): #TODO sparse broadcasting if self.shape != other.shape: return True elif self.format != other.format: other = other.asformat(self.format) return self._binopt(other, '_ne_') else: return True
def __eq__(self, other): # Scalar other. if isscalarlike(other): if np.isnan(other): return csr_matrix(self.shape, dtype=np.bool_) if other == 0: warn( "Comparing a sparse matrix with 0 using == is inefficient" ", try using != instead.", SparseEfficiencyWarning) all_true = _all_true(self.shape) inv = self._scalar_binopt(other, operator.ne) return all_true - inv else: return self._scalar_binopt(other, operator.eq) # Dense other. elif isdense(other): return self.todense() == other # Sparse other. elif isspmatrix(other): warn( "Comparing sparse matrices using == is inefficient, try using" " != instead.", SparseEfficiencyWarning) #TODO sparse broadcasting if self.shape != other.shape: return False elif self.format != other.format: other = other.asformat(self.format) res = self._binopt(other, '_ne_') all_true = _all_true(self.shape) return all_true - res else: return False
def __ne__(self, other): # Scalar other. if isscalarlike(other): if np.isnan(other): warn("Comparing a sparse matrix with nan using != is inefficient", SparseEfficiencyWarning) all_true = self.__class__(np.ones(self.shape, dtype=np.bool_)) return all_true elif other != 0: warn("Comparing a sparse matrix with a nonzero scalar using !=" " is inefficient, try using == instead.", SparseEfficiencyWarning) all_true = self.__class__(np.ones(self.shape), dtype=np.bool_) res = (self == other) return all_true - res else: other_arr = self._copy_with_const(other) return self._binopt(other_arr,'_ne_') # Dense other. elif isdense(other): return self.todense() != other # Sparse other. elif isspmatrix(other): #TODO sparse broadcasting if self.shape != other.shape: return True elif self.format != other.format: other = other.asformat(self.format) return self._binopt(other,'_ne_') else: return True
def __eq__(self, other): # Scalar other. if isscalarlike(other): if np.isnan(other): return self.__class__(self.shape, dtype=np.bool_) other_arr = self._copy_with_const(other) res = self._binopt(other_arr,'_ne_') if other == 0: warn("Comparing a sparse matrix with 0 using == is inefficient" ", try using != instead.", SparseEfficiencyWarning) all_true = self.__class__(np.ones(self.shape, dtype=np.bool_)) return all_true - res else: sparsity_pattern = self._copy_with_const(True) return sparsity_pattern - res # Dense other. elif isdense(other): return self.todense() == other # Sparse other. elif isspmatrix(other): warn("Comparing sparse matrices using == is inefficient, try using" " != instead.", SparseEfficiencyWarning) #TODO sparse broadcasting if self.shape != other.shape: return False elif self.format != other.format: other = other.asformat(self.format) res = self._binopt(other,'_ne_') all_true = self.__class__(np.ones(self.shape, dtype=np.bool_)) return all_true - res else: return False
def _is_symmetric_numerically(mat): # Note: this check is expensive flag = False if isinstance(mat, np.ndarray): flag = is_symmetric_dense(mat) elif isscalarlike(mat): flag = True elif isinstance(mat, SparseBase): if mat.is_symmetric: flag = mat.is_symmetric else: if mat.shape[0] != mat.shape[1]: flag = False else: # get upper and lower triangular from pyomo.contrib.pynumero.sparse.block_matrix import BlockMatrix if isinstance(mat, BlockMatrix): mat = mat.tofullmatrix() l = tril(mat) u = triu(mat) diff = l - u.transpose() z = np.zeros(diff.nnz) flag = np.allclose(diff.data, z, atol=1e-6) else: if mat.shape[0] != mat.shape[1]: flag = False else: # get upper and lower triangular l = tril(mat) u = triu(mat) diff = l - u.transpose() z = np.zeros(diff.nnz) flag = np.allclose(diff.data, z, atol=1e-6) return flag
def _inequality(self, other, op, op_name, bad_scalar_msg): # Scalar other. if isscalarlike(other): if 0 == other and op_name in ('_le_', '_ge_'): raise NotImplementedError(" >= and <= don't work with 0.") elif op(0, other): warn(bad_scalar_msg, SparseEfficiencyWarning) other_arr = np.empty(self.shape, dtype=np.result_type(other)) other_arr.fill(other) other_arr = csr_matrix(other_arr) return self._binopt(other_arr, op_name) else: return self._scalar_binopt(other, op) # Dense other. elif isdense(other): return op(self.todense(), other) # Sparse other. elif isspmatrix(other): #TODO sparse broadcasting if self.shape != other.shape: raise ValueError("inconsistent shapes") elif self.format != other.format: other = other.asformat(self.format) if op_name not in ('_ge_', '_le_'): return self._binopt(other, op_name) warn("Comparing sparse matrices using >= and <= is inefficient, " "using <, >, or !=, instead.", SparseEfficiencyWarning) all_true = _all_true(self.shape) res = self._binopt(other, '_gt_' if op_name == '_le_' else '_lt_') return all_true - res else: raise ValueError("Operands could not be compared.")
def _maximum_minimum(self, other, npop, op_name, dense_check): if isscalarlike(other): if dense_check(other): warn( "Taking maximum (minimum) with > 0 (< 0) number results" " to a dense matrix.", SparseEfficiencyWarning, stacklevel=3) other_arr = np.empty(self.shape, dtype=np.asarray(other).dtype) other_arr.fill(other) other_arr = self.__class__(other_arr) return self._binopt(other_arr, op_name) else: self.sum_duplicates() new_data = npop(self.data, np.asarray(other)) mat = self.__class__((new_data, self.indices, self.indptr), dtype=new_data.dtype, shape=self.shape) return mat elif isdense(other): return npop(self.todense(), other) elif isspmatrix(other): return self._binopt(other, op_name) else: raise ValueError("Operands not compatible.")
def __itruediv__(self, other): if isscalarlike(other): # Multiply this scalar by every element. for (key, val) in iteritems(self): self[key] = val / other return self else: raise NotImplementedError
def multiply(self, other): """Point-wise multiplication by another matrix, vector, or scalar. """ # Scalar multiplication. if isscalarlike(other): return self._mul_scalar(other) # Sparse matrix or vector. if isspmatrix(other): if self.shape == other.shape: if not isinstance(other, fast_csr_matrix): other = csr_matrix(other) return self._binopt(other, '_elmul_') # Single element. elif other.shape == (1,1): return self._mul_scalar(other.toarray()[0, 0]) elif self.shape == (1,1): return other._mul_scalar(self.toarray()[0, 0]) # A row times a column. elif self.shape[1] == other.shape[0] and self.shape[1] == 1: return self._mul_sparse_matrix(other.tocsc()) elif self.shape[0] == other.shape[1] and self.shape[0] == 1: return other._mul_sparse_matrix(self.tocsc()) # Row vector times matrix. other is a row. elif other.shape[0] == 1 and self.shape[1] == other.shape[1]: other = dia_matrix((other.toarray().ravel(), [0]), shape=(other.shape[1], other.shape[1])) return self._mul_sparse_matrix(other) # self is a row. elif self.shape[0] == 1 and self.shape[1] == other.shape[1]: copy = dia_matrix((self.toarray().ravel(), [0]), shape=(self.shape[1], self.shape[1])) return other._mul_sparse_matrix(copy) # Column vector times matrix. other is a column. elif other.shape[1] == 1 and self.shape[0] == other.shape[0]: other = dia_matrix((other.toarray().ravel(), [0]), shape=(other.shape[0], other.shape[0])) return other._mul_sparse_matrix(self) # self is a column. elif self.shape[1] == 1 and self.shape[0] == other.shape[0]: copy = dia_matrix((self.toarray().ravel(), [0]), shape=(self.shape[0], self.shape[0])) return copy._mul_sparse_matrix(other) else: raise ValueError("inconsistent shapes") # Dense matrix. if isdense(other): if self.shape == other.shape: ret = self.tocoo() ret.data = np.multiply(ret.data, other[ret.row, ret.col] ).view(np.ndarray).ravel() return ret # Single element. elif other.size == 1: return self._mul_scalar(other.flat[0]) # Anything else. return np.multiply(self.todense(), other)
def multiply(self, other): """Point-wise multiplication by another matrix, vector, or scalar. """ # Scalar multiplication. if isscalarlike(other): return self._mul_scalar(other) # Sparse matrix or vector. if isspmatrix(other): if self.shape == other.shape: if not isinstance(other, fast_csr_matrix): other = csr_matrix(other) return self._binopt(other, '_elmul_') # Single element. elif other.shape == (1, 1): return self._mul_scalar(other.toarray()[0, 0]) elif self.shape == (1, 1): return other._mul_scalar(self.toarray()[0, 0]) # A row times a column. elif self.shape[1] == other.shape[0] and self.shape[1] == 1: return self._mul_sparse_matrix(other.tocsc()) elif self.shape[0] == other.shape[1] and self.shape[0] == 1: return other._mul_sparse_matrix(self.tocsc()) # Row vector times matrix. other is a row. elif other.shape[0] == 1 and self.shape[1] == other.shape[1]: other = dia_matrix((other.toarray().ravel(), [0]), shape=(other.shape[1], other.shape[1])) return self._mul_sparse_matrix(other) # self is a row. elif self.shape[0] == 1 and self.shape[1] == other.shape[1]: copy = dia_matrix((self.toarray().ravel(), [0]), shape=(self.shape[1], self.shape[1])) return other._mul_sparse_matrix(copy) # Column vector times matrix. other is a column. elif other.shape[1] == 1 and self.shape[0] == other.shape[0]: other = dia_matrix((other.toarray().ravel(), [0]), shape=(other.shape[0], other.shape[0])) return other._mul_sparse_matrix(self) # self is a column. elif self.shape[1] == 1 and self.shape[0] == other.shape[0]: copy = dia_matrix((self.toarray().ravel(), [0]), shape=(self.shape[0], self.shape[0])) return copy._mul_sparse_matrix(other) else: raise ValueError("inconsistent shapes") # Dense matrix. if isdense(other): if self.shape == other.shape: ret = self.tocoo() ret.data = np.multiply(ret.data, other[ret.row, ret.col]).view( np.ndarray).ravel() return ret # Single element. elif other.size == 1: return self._mul_scalar(other.flat[0]) # Anything else. return np.multiply(self.todense(), other)
def __imul__(self, other): if isscalarlike(other): # Multiply this scalar by every element. for (key, val) in iteritems(self): self[key] = val * other # new.dtype.char = self.dtype.char return self else: raise NotImplementedError
def __truediv__(self, other): if isscalarlike(other): res_dtype = upcast_scalar(self.dtype, other) new = dok_matrix(self.shape, dtype=res_dtype) # Multiply this scalar by every element. for (key, val) in iteritems(self): new[key] = val / other # new.dtype.char = self.dtype.char return new else: return self.tocsr() / other
def is_symmetric_dense(mat): flag = False if isinstance(mat, np.ndarray): if mat.ndim == 2 and mat.shape[0] == mat.shape[1]: if np.allclose(mat, mat.T, atol=1e-6): flag = True elif isscalarlike(mat): flag = True else: raise RuntimeError("Format not recognized {}".format(type(mat))) return flag
def __rsub__(self,other): # other - self # note: this can't be replaced by other + (-self) for unsigned types if isscalarlike(other): if other == 0: return -self.copy() else: # Now we would add this scalar to every element. raise NotImplementedError('adding a nonzero scalar to a ' 'sparse matrix is not supported') elif isdense(other): # Convert this matrix to a dense matrix and subtract them return other - self.todense() else: return NotImplemented
def __binary_op__(self, other, operand): """ Generic binary op (+,-,/,*) implementation """ M, N = self.shape operand = getattr(self.data, operand) mask = self.mask if isscalarlike(other): operand(other) return self elif sp.issparse(other): if other.shape != self.shape: raise ValueError, "inconsistent shapes" data = np.array(sp.lil_matrix(other)[mask].todense()) operand(data.reshape(data.size)) return self try: other.shape except AttributeError: other = np.asanyarray(other) other = np.asanyarray(other) if other.size == 1: operand(other[0]) return self if other.ndim == 1 or other.ndim == 2 and other.shape[0] == 1: if other.shape == (N, ): operand(other[mask[1]]) elif other.shape == (1, N): operand(other[0, mask[1]]) # elif len(self.data) == other.size: # operand(other.flatten()) else: raise ValueError('dimension mismatch') elif other.ndim == 2: if other.shape == (M, 1): operand(other[mask[0], 0]) elif other.shape == (M, N): operand(other[mask[0], mask[1]]) else: raise ValueError('dimension mismatch') else: raise ValueError('could not interpret dimensions') return self
def __sub__(self,other): # First check if argument is a scalar if isscalarlike(other): if other == 0: return self.copy() else: # Now we would add this scalar to every element. raise NotImplementedError('adding a nonzero scalar to a ' 'sparse matrix is not supported') elif isspmatrix(other): if (other.shape != self.shape): raise ValueError("inconsistent shapes") return self._binopt(other,'_minus_') elif isdense(other): # Convert this matrix to a dense matrix and subtract them return self.todense() - other else: return NotImplemented
def __binary_op__ (self, other, operand): """ Generic binary op (+,-,/,*) implementation """ M,N = self.shape operand = getattr(self.data, operand) mask = self.mask if isscalarlike(other): operand(other) return self elif sp.issparse(other): if other.shape != self.shape: raise ValueError, "inconsistent shapes" data = np.array(sp.lil_matrix(other)[mask].todense()) operand(data.reshape(data.size)) return self try: other.shape except AttributeError: other = np.asanyarray(other) other = np.asanyarray(other) if other.size == 1: operand(other[0]) return self if other.ndim == 1 or other.ndim == 2 and other.shape[0] == 1: if other.shape == (N,): operand(other[mask[1]]) elif other.shape == (1,N): operand(other[0,mask[1]]) # elif len(self.data) == other.size: # operand(other.flatten()) else: raise ValueError('dimension mismatch') elif other.ndim == 2: if other.shape == (M,1): operand(other[mask[0],0]) elif other.shape == (M,N): operand(other[mask[0],mask[1]]) else: raise ValueError('dimension mismatch') else: raise ValueError('could not interpret dimensions') return self
def __ne__(self, other): # Scalar other. if isscalarlike(other): if np.isnan(other): warn( "Comparing a sparse matrix with nan using != is" " inefficient", SparseEfficiencyWarning, stacklevel=3) all_true = self.__class__(np.ones(self.shape, dtype=np.bool_)) return all_true elif other != 0: warn( "Comparing a sparse matrix with a nonzero scalar using !=" " is inefficient, try using == instead.", SparseEfficiencyWarning, stacklevel=3) all_true = self.__class__(np.ones(self.shape), dtype=np.bool_) inv = self._scalar_binopt(other, operator.eq) return all_true - inv else: return self._scalar_binopt(other, operator.ne) # Dense other. elif isdense(other): return self.todense() != other # Pydata sparse other. elif is_pydata_spmatrix(other): return NotImplemented # Sparse other. elif isspmatrix(other): # TODO sparse broadcasting if self.shape != other.shape: return True elif self.format != other.format: other = other.asformat(self.format) return self._binopt(other, '_ne_') else: return True
def is_symmetric_sparse(mat): from pyomo.contrib.pynumero.sparse.block_matrix import BlockMatrix # Note: this check is expensive flag = False if isinstance(mat, np.ndarray): flag = is_symmetric_dense(mat) elif isscalarlike(mat): flag = True elif isspmatrix(mat) or isinstance(mat, BlockMatrix): if mat.shape[0] != mat.shape[1]: flag = False else: if isinstance(mat, BlockMatrix): mat = mat.tocoo() # get upper and lower triangular l = tril(mat) u = triu(mat) diff = l - u.transpose() z = np.zeros(diff.nnz) flag = np.allclose(diff.data, z, atol=1e-6) else: raise RuntimeError("Format not recognized {}".format(type(mat))) return flag
def multiply(self, other): """Point-wise multiplication by another matrix, vector, or scalar. """ # print("multiply") # Scalar multiplication. if isscalarlike(other): return self._mul_scalar(other) # Sparse matrix or vector. if isspmatrix(other): if self.shape == other.shape: other = self.__class__(other) return self._binopt(other, '_elmul_') # Single element. elif other.shape == (1, 1): return self._mul_scalar(other.toarray()[0, 0]) elif self.shape == (1, 1): return other._mul_scalar(self.toarray()[0, 0]) # A row times a column. elif self.shape[1] == 1 and other.shape[0] == 1: return self._mul_sparse_matrix(other.tocsc()) elif self.shape[0] == 1 and other.shape[1] == 1: return other._mul_sparse_matrix(self.tocsc()) # Row vector times matrix. other is a row. elif other.shape[0] == 1 and self.shape[1] == other.shape[1]: other = dia_matrix((other.toarray().ravel(), [0]), shape=(other.shape[1], other.shape[1])) return self._mul_sparse_matrix(other) # self is a row. elif self.shape[0] == 1 and self.shape[1] == other.shape[1]: copy = dia_matrix((self.toarray().ravel(), [0]), shape=(self.shape[1], self.shape[1])) return other._mul_sparse_matrix(copy) # Column vector times matrix. other is a column. elif other.shape[1] == 1 and self.shape[0] == other.shape[0]: other = dia_matrix((other.toarray().ravel(), [0]), shape=(other.shape[0], other.shape[0])) return other._mul_sparse_matrix(self) # self is a column. elif self.shape[1] == 1 and self.shape[0] == other.shape[0]: copy = dia_matrix((self.toarray().ravel(), [0]), shape=(self.shape[0], self.shape[0])) return copy._mul_sparse_matrix(other) else: raise ValueError("inconsistent shapes") # Assume other is a dense matrix/array, which produces a single-item # object array if other isn't convertible to ndarray. other = np.atleast_2d(other) if other.ndim != 2: return np.multiply(self.toarray(), other) # Single element / wrapped object. if other.size == 1: return self._mul_scalar(other.flat[0]) # Fast case for trivial sparse matrix. elif self.shape == (1, 1): return np.multiply(self.toarray()[0, 0], other) from scipy.sparse.coo import coo_matrix ret = self.tocoo() # Matching shapes. if self.shape == other.shape: data = np.multiply(ret.data, other[ret.row, ret.col]) # Sparse row vector times... elif self.shape[0] == 1: if other.shape[1] == 1: # Dense column vector. data = np.multiply(ret.data, other) elif other.shape[1] == self.shape[1]: # Dense matrix. data = np.multiply(ret.data, other[:, ret.col]) else: raise ValueError("inconsistent shapes") row = np.repeat(np.arange(other.shape[0]), len(ret.row)) col = np.tile(ret.col, other.shape[0]) return coo_matrix((data.view(np.ndarray).ravel(), (row, col)), shape=(other.shape[0], self.shape[1]), copy=False) # Sparse column vector times... elif self.shape[1] == 1: if other.shape[0] == 1: # Dense row vector. data = np.multiply(ret.data[:, None], other) elif other.shape[0] == self.shape[0]: # Dense matrix. data = np.multiply(ret.data[:, None], other[ret.row]) else: raise ValueError("inconsistent shapes") row = np.repeat(ret.row, other.shape[1]) col = np.tile(np.arange(other.shape[1]), len(ret.col)) return coo_matrix((data.view(np.ndarray).ravel(), (row, col)), shape=(self.shape[0], other.shape[1]), copy=False) # Sparse matrix times dense row vector. elif other.shape[0] == 1 and self.shape[1] == other.shape[1]: data = np.multiply(ret.data, other[:, ret.col].ravel()) # Sparse matrix times dense column vector. elif other.shape[1] == 1 and self.shape[0] == other.shape[0]: data = np.multiply(ret.data, other[ret.row].ravel()) else: raise ValueError("inconsistent shapes") ret.data = data.view(np.ndarray).ravel() return ret