Mercurial > octave
changeset 29845:2ef9080ca017
allow more mixed-type assignments to work for sparse matrices (bug #60859)
This change allows indexed assignment to work when the LHS is a sparse
matrix (real or complex) and the RHS is a single precision scalar or
matrix (real or complex).
* ov-base-sparse.h, ov-base-sparse.cc (octave_base_sparse<T>::assign):
Declare RHS as a template type separate from the type of the sparse
array itself. Move implementation to header file so that
instantiation will work automatically.
* Sparse.cc, Sparse.h (Sparse<T>::assign): Provide versions for scalar RHS.
* op-scm-cm.cc, op-scm-cs.cc, op-scm-m.cc, op-scm-s.cc, op-sm-cm.cc,
op-sm-cs.cc, op-sm-m.cc, op-sm-s.cc: Use DEFNDASSIGNOP_FN to define
functions for assignment. Define and install mixed-type assignment
operations for float and float complex scalar and array assignments to
complex and double sparse arrays.
* test/sparse-assign.tst: New tests.
* test/module.mk: Update.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Wed, 30 Jun 2021 17:52:03 -0400 |
parents | ceb2259f7c11 |
children | 449599fdbad8 |
files | libinterp/octave-value/ov-base-sparse.cc libinterp/octave-value/ov-base-sparse.h libinterp/operators/op-scm-cm.cc libinterp/operators/op-scm-cs.cc libinterp/operators/op-scm-m.cc libinterp/operators/op-scm-s.cc libinterp/operators/op-sm-cm.cc libinterp/operators/op-sm-cs.cc libinterp/operators/op-sm-m.cc libinterp/operators/op-sm-s.cc liboctave/array/Sparse.cc liboctave/array/Sparse.h test/module.mk test/sparse-assign.tst |
diffstat | 14 files changed, 448 insertions(+), 115 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/octave-value/ov-base-sparse.cc Thu Jul 01 15:28:17 2021 +0200 +++ b/libinterp/octave-value/ov-base-sparse.cc Wed Jun 30 17:52:03 2021 -0400 @@ -179,59 +179,6 @@ return retval; } -template <typename T> -void -octave_base_sparse<T>::assign (const octave_value_list& idx, const T& rhs) -{ - - octave_idx_type len = idx.length (); - - // If we catch an indexing error in index_vector, we flag an error in - // index k. Ensure it is the right value before each idx_vector call. - // Same variable as used in the for loop in the default case. - - octave_idx_type k = 0; - - try - { - switch (len) - { - case 1: - { - octave::idx_vector i = idx (0).index_vector (); - - matrix.assign (i, rhs); - - break; - } - - case 2: - { - octave::idx_vector i = idx (0).index_vector (); - - k = 1; - octave::idx_vector j = idx (1).index_vector (); - - matrix.assign (i, j, rhs); - - break; - } - - default: - error ("sparse indexing needs 1 or 2 indices"); - } - } - catch (octave::index_exception& ie) - { - // Rethrow to allow more info to be reported later. - ie.set_pos_if_unset (len, k+1); - throw; - } - - // Invalidate matrix type. - typ.invalidate_type (); -} - template <typename MT> void octave_base_sparse<MT>::delete_elements (const octave_value_list& idx)
--- a/libinterp/octave-value/ov-base-sparse.h Thu Jul 01 15:28:17 2021 +0200 +++ b/libinterp/octave-value/ov-base-sparse.h Wed Jun 30 17:52:03 2021 -0400 @@ -110,7 +110,56 @@ // can also cause some confusion. using octave_base_value::assign; - OCTINTERP_API void assign (const octave_value_list& idx, const T& rhs); + template <typename RHS_T> + OCTINTERP_API void assign (const octave_value_list& idx, const RHS_T& rhs) + { + octave_idx_type len = idx.length (); + + // If we catch an indexing error in index_vector, we flag an error in + // index k. Ensure it is the right value before each idx_vector call. + // Same variable as used in the for loop in the default case. + + octave_idx_type k = 0; + + try + { + switch (len) + { + case 1: + { + octave::idx_vector i = idx (0).index_vector (); + + matrix.assign (i, rhs); + + break; + } + + case 2: + { + octave::idx_vector i = idx (0).index_vector (); + + k = 1; + octave::idx_vector j = idx (1).index_vector (); + + matrix.assign (i, j, rhs); + + break; + } + + default: + error ("sparse indexing needs 1 or 2 indices"); + } + } + catch (octave::index_exception& ie) + { + // Rethrow to allow more info to be reported later. + ie.set_pos_if_unset (len, k+1); + throw; + } + + // Invalidate matrix type. + typ.invalidate_type (); + } OCTINTERP_API void delete_elements (const octave_value_list& idx);
--- a/libinterp/operators/op-scm-cm.cc Thu Jul 01 15:28:17 2021 +0200 +++ b/libinterp/operators/op-scm-cm.cc Wed Jun 30 17:52:03 2021 -0400 @@ -31,6 +31,7 @@ #include "ov.h" #include "ov-typeinfo.h" #include "ov-cx-mat.h" +#include "ov-flt-cx-mat.h" #include "ops.h" #include "xdiv.h" @@ -138,17 +139,8 @@ (v1.sparse_complex_matrix_value ().concat (tmp, ra_idx)); } -DEFASSIGNOP (assign, sparse_complex_matrix, complex_matrix) -{ - octave_sparse_complex_matrix& v1 - = dynamic_cast<octave_sparse_complex_matrix&> (a1); - const octave_complex_matrix& v2 - = dynamic_cast<const octave_complex_matrix&> (a2); - - SparseComplexMatrix tmp (v2.complex_matrix_value ()); - v1.assign (idx, tmp); - return octave_value (); -} +DEFNDASSIGNOP_FN (assign, sparse_complex_matrix, complex_matrix, complex_matrix, assign); +DEFNDASSIGNOP_FN (sgl_assign, sparse_complex_matrix, float_complex_matrix, complex_matrix, assign); void install_scm_cm_ops (octave::type_info& ti) @@ -199,4 +191,6 @@ INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix, octave_complex_matrix, assign); + INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix, + octave_float_complex_matrix, sgl_assign); }
--- a/libinterp/operators/op-scm-cs.cc Thu Jul 01 15:28:17 2021 +0200 +++ b/libinterp/operators/op-scm-cs.cc Wed Jun 30 17:52:03 2021 -0400 @@ -32,6 +32,7 @@ #include "ov-typeinfo.h" #include "ov-cx-mat.h" #include "ov-complex.h" +#include "ov-flt-complex.h" #include "ops.h" #include "xpow.h" @@ -125,16 +126,8 @@ (v1.sparse_complex_matrix_value ().concat (tmp, ra_idx)); } -DEFASSIGNOP (assign, sparse_complex_matrix, complex) -{ - octave_sparse_complex_matrix& v1 - = dynamic_cast<octave_sparse_complex_matrix&> (a1); - const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2); - - SparseComplexMatrix tmp (1, 1, v2.complex_value ()); - v1.assign (idx, tmp); - return octave_value (); -} +DEFNDASSIGNOP_FN (assign, sparse_complex_matrix, complex, complex, assign); +DEFNDASSIGNOP_FN (sgl_assign, sparse_complex_matrix, float_complex, complex, assign); void install_scm_cs_ops (octave::type_info& ti) @@ -173,6 +166,7 @@ INSTALL_CATOP_TI (ti, octave_sparse_complex_matrix, octave_complex, scm_cs); INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix, - octave_complex, - assign); + octave_complex, assign); + INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix, + octave_float_complex, sgl_assign); }
--- a/libinterp/operators/op-scm-m.cc Thu Jul 01 15:28:17 2021 +0200 +++ b/libinterp/operators/op-scm-m.cc Wed Jun 30 17:52:03 2021 -0400 @@ -31,6 +31,7 @@ #include "ov.h" #include "ov-typeinfo.h" #include "ov-re-mat.h" +#include "ov-flt-re-mat.h" #include "ov-cx-mat.h" #include "ops.h" #include "xdiv.h" @@ -131,16 +132,8 @@ (v1.sparse_complex_matrix_value ().concat (tmp, ra_idx)); } -DEFASSIGNOP (assign, sparse_complex_matrix, matrix) -{ - octave_sparse_complex_matrix& v1 - = dynamic_cast<octave_sparse_complex_matrix&> (a1); - const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2); - - SparseComplexMatrix tmp (v2.complex_matrix_value ()); - v1.assign (idx, tmp); - return octave_value (); -} +DEFNDASSIGNOP_FN (assign, sparse_complex_matrix, matrix, complex_matrix, assign); +DEFNDASSIGNOP_FN (sgl_assign, sparse_complex_matrix, float_matrix, complex_matrix, assign); void install_scm_m_ops (octave::type_info& ti) @@ -175,4 +168,6 @@ INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix, octave_matrix, assign); + INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix, octave_float_matrix, + sgl_assign); }
--- a/libinterp/operators/op-scm-s.cc Thu Jul 01 15:28:17 2021 +0200 +++ b/libinterp/operators/op-scm-s.cc Wed Jun 30 17:52:03 2021 -0400 @@ -32,6 +32,7 @@ #include "ov-typeinfo.h" #include "ov-cx-mat.h" #include "ov-scalar.h" +#include "ov-float.h" #include "ops.h" #include "xpow.h" @@ -133,16 +134,8 @@ (v1.sparse_complex_matrix_value ().concat (tmp, ra_idx)); } -DEFASSIGNOP (assign, sparse_complex_matrix, scalar) -{ - octave_sparse_complex_matrix& v1 - = dynamic_cast<octave_sparse_complex_matrix&> (a1); - const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2); - - SparseComplexMatrix tmp (1, 1, v2.complex_value ()); - v1.assign (idx, tmp); - return octave_value (); -} +DEFNDASSIGNOP_FN (assign, sparse_complex_matrix, scalar, scalar, assign); +DEFNDASSIGNOP_FN (sgl_assign, sparse_complex_matrix, float_scalar, scalar, assign); void install_scm_s_ops (octave::type_info& ti) @@ -177,4 +170,6 @@ INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix, octave_scalar, assign); + INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_complex_matrix, octave_float_scalar, + sgl_assign); }
--- a/libinterp/operators/op-sm-cm.cc Thu Jul 01 15:28:17 2021 +0200 +++ b/libinterp/operators/op-sm-cm.cc Wed Jun 30 17:52:03 2021 -0400 @@ -31,6 +31,7 @@ #include "ov.h" #include "ov-typeinfo.h" #include "ov-cx-mat.h" +#include "ov-flt-cx-mat.h" #include "ops.h" #include "xdiv.h" @@ -174,6 +175,9 @@ INSTALL_ASSIGNCONV_TI (ti, octave_sparse_matrix, octave_complex_matrix, octave_sparse_complex_matrix); + INSTALL_ASSIGNCONV_TI (ti, octave_sparse_matrix, octave_float_complex_matrix, + octave_sparse_complex_matrix); + INSTALL_WIDENOP_TI (ti, octave_sparse_matrix, octave_complex_matrix, sparse_complex_matrix_conv); }
--- a/libinterp/operators/op-sm-cs.cc Thu Jul 01 15:28:17 2021 +0200 +++ b/libinterp/operators/op-sm-cs.cc Wed Jun 30 17:52:03 2021 -0400 @@ -31,6 +31,7 @@ #include "ov.h" #include "ov-typeinfo.h" #include "ov-complex.h" +#include "ov-flt-complex.h" #include "ops.h" #include "xpow.h" @@ -148,4 +149,7 @@ INSTALL_ASSIGNCONV_TI (ti, octave_sparse_matrix, octave_complex, octave_sparse_complex_matrix); + + INSTALL_ASSIGNCONV_TI (ti, octave_sparse_matrix, octave_float_complex, + octave_sparse_complex_matrix); }
--- a/libinterp/operators/op-sm-m.cc Thu Jul 01 15:28:17 2021 +0200 +++ b/libinterp/operators/op-sm-m.cc Wed Jun 30 17:52:03 2021 -0400 @@ -31,6 +31,7 @@ #include "ov.h" #include "ov-typeinfo.h" #include "ov-re-mat.h" +#include "ov-flt-re-mat.h" #include "ops.h" #include "xdiv.h" @@ -124,15 +125,8 @@ return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx)); } -DEFASSIGNOP (assign, sparse_matrix, matrix) -{ - octave_sparse_matrix& v1 = dynamic_cast<octave_sparse_matrix&> (a1); - const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2); - - SparseMatrix tmp (v2.matrix_value ()); - v1.assign (idx, tmp); - return octave_value (); -} +DEFNDASSIGNOP_FN (assign, sparse_matrix, matrix, matrix, assign); +DEFNDASSIGNOP_FN (sgl_assign, sparse_matrix, float_matrix, matrix, assign); void install_sm_m_ops (octave::type_info& ti) @@ -164,4 +158,6 @@ INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_matrix, octave_matrix, assign); + INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_matrix, octave_float_matrix, + sgl_assign); }
--- a/libinterp/operators/op-sm-s.cc Thu Jul 01 15:28:17 2021 +0200 +++ b/libinterp/operators/op-sm-s.cc Wed Jun 30 17:52:03 2021 -0400 @@ -31,6 +31,7 @@ #include "ov.h" #include "ov-typeinfo.h" #include "ov-scalar.h" +#include "ov-float.h" #include "ops.h" #include "xpow.h" @@ -121,15 +122,8 @@ return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx)); } -DEFASSIGNOP (assign, sparse_matrix, scalar) -{ - octave_sparse_matrix& v1 = dynamic_cast<octave_sparse_matrix&> (a1); - const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2); - - SparseMatrix tmp (1, 1, v2.scalar_value ()); - v1.assign (idx, tmp); - return octave_value (); -} +DEFNDASSIGNOP_FN (assign, sparse_matrix, scalar, scalar, assign); +DEFNDASSIGNOP_FN (sgl_assign, sparse_matrix, float_scalar, scalar, assign); void install_sm_s_ops (octave::type_info& ti) @@ -158,4 +152,6 @@ INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_matrix, octave_scalar, assign); + INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_sparse_matrix, octave_float_scalar, + sgl_assign); }
--- a/liboctave/array/Sparse.cc Thu Jul 01 15:28:17 2021 +0200 +++ b/liboctave/array/Sparse.cc Wed Jun 30 17:52:03 2021 -0400 @@ -2020,6 +2020,18 @@ template <typename T> OCTAVE_API void +Sparse<T>::assign (const octave::idx_vector& idx, const T& rhs) +{ + // FIXME: Converting the RHS and forwarding to the sparse matrix + // assignment function is simpler, but it might be good to have a + // specialization... + + assign (idx, Sparse<T> (1, 1, rhs)); +} + +template <typename T> +OCTAVE_API +void Sparse<T>::assign (const octave::idx_vector& idx_i, const octave::idx_vector& idx_j, const Sparse<T>& rhs) { @@ -2255,6 +2267,19 @@ octave::err_nonconformant ("=", idx_i.length (nr), idx_j.length (nc), n, m); } +template <typename T> +OCTAVE_API +void +Sparse<T>::assign (const octave::idx_vector& idx_i, + const octave::idx_vector& idx_j, const T& rhs) +{ + // FIXME: Converting the RHS and forwarding to the sparse matrix + // assignment function is simpler, but it might be good to have a + // specialization... + + assign (idx_i, idx_j, Sparse<T> (1, 1, rhs)); +} + // Can't use versions of these in Array.cc due to duplication of the // instantiations for Array<double and Sparse<double>, etc template <typename T>
--- a/liboctave/array/Sparse.h Thu Jul 01 15:28:17 2021 +0200 +++ b/liboctave/array/Sparse.h Wed Jun 30 17:52:03 2021 -0400 @@ -525,10 +525,15 @@ OCTAVE_API void assign (const octave::idx_vector& i, const Sparse<T>& rhs); + OCTAVE_API void assign (const octave::idx_vector& i, const T& rhs); + OCTAVE_API void assign (const octave::idx_vector& i, const octave::idx_vector& j, const Sparse<T>& rhs); OCTAVE_API void + assign (const octave::idx_vector& i, const octave::idx_vector& j, const T& rhs); + + OCTAVE_API void print_info (std::ostream& os, const std::string& prefix) const; // Unsafe. These functions exist to support the MEX interface.
--- a/test/module.mk Thu Jul 01 15:28:17 2021 +0200 +++ b/test/module.mk Wed Jun 30 17:52:03 2021 -0400 @@ -48,6 +48,7 @@ %reldir%/return.tst \ %reldir%/single-index.tst \ %reldir%/slice.tst \ + %reldir%/sparse-assign.tst \ %reldir%/struct.tst \ %reldir%/switch.tst \ %reldir%/system.tst \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sparse-assign.tst Wed Jun 30 17:52:03 2021 -0400 @@ -0,0 +1,328 @@ +######################################################################## +## +## Copyright (C) 2021 The Octave Project Developers +## +## See the file COPYRIGHT.md in the top-level directory of this +## distribution or <https://octave.org/copyright/>. +## +## This file is part of Octave. +## +## Octave is free software: you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## <https://www.gnu.org/licenses/>. +## +######################################################################## + +## FIXME: will also need tests for if assignment of integer values +## once that is implemented. The pattern can be the same. + +%!shared lr, lc, rr, rc, si, sj, mi, mj, sm_lhs, csm_lhs, s, m, sm, cs, cm, csm +%! lr = 6; +%! lc = 8; +%! rr = 2; +%! rc = 3; +%! si = 2; +%! sj = 3; +%! mi = (1:rr)+2; +%! mj = (1:rc)+3; +%! sm_lhs = sprand (lr, lc, 0.1); +%! csm_lhs = sm_lhs + 1i * sprand (lr, lc, 0.1); +%! s = rand (); +%! m = rand (rr, rc); +%! sm = sprand (rr, rc, 0.1); +%! cs = s + 1i * rand (); +%! cm = m + 1i * rand (rr, rc); +%! csm = cm + 1i * sprand (rr, rc, 0.1); + +%% Indexed assignment of double scalar, sparse with a single element, +%% complex scalar, and sparse complex with a single element to sparse matrix. + +%!test +%! lhs = sm_lhs; +%! rhs = s; +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(si,sj) = rhs; +%! flhs(si,sj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = sm_lhs; +%! rhs = sparse (s); +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(si,sj) = rhs; +%! flhs(si,sj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = sm_lhs; +%! rhs = cs; +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(si,sj) = rhs; +%! flhs(si,sj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = sm_lhs; +%! rhs = sparse (cs); +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(si,sj) = rhs; +%! flhs(si,sj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%% Indexed assignment of double scalar, sparse with a single element, +%% complex scalar, and sparse complex with a single element to complex +%% sparse matrix. + +%!test +%! lhs = csm_lhs; +%! rhs = s; +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(si,sj) = rhs; +%! flhs(si,sj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = csm_lhs; +%! rhs = sparse (s); +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(si,sj) = rhs; +%! flhs(si,sj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = csm_lhs; +%! rhs = cs; +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(si,sj) = rhs; +%! flhs(si,sj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = csm_lhs; +%! rhs = sparse (cs); +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(si,sj) = rhs; +%! flhs(si,sj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%% Indexed assignment of matrix, sparse matrix, complex matrix, +%% and complex sparse matrix to sparse matrix. + +%!test +%! lhs = sm_lhs; +%! rhs = m; +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(mi,mj) = rhs; +%! flhs(mi,mj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = sm_lhs; +%! rhs = sm; +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(mi,mj) = rhs; +%! flhs(mi,mj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = sm_lhs; +%! rhs = cm; +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(mi,mj) = rhs; +%! flhs(mi,mj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = sm_lhs; +%! rhs = csm; +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(mi,mj) = rhs; +%! flhs(mi,mj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%% Indexed assignment of matrix, sparse matrix, complex matrix, +%% and complex sparse matrix to complex sparse matrix. + +%!test +%! lhs = csm_lhs; +%! rhs = m; +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(mi,mj) = rhs; +%! flhs(mi,mj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = csm_lhs; +%! rhs = sm; +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(mi,mj) = rhs; +%! flhs(mi,mj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = csm_lhs; +%! rhs = cm; +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(mi,mj) = rhs; +%! flhs(mi,mj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = csm_lhs; +%! rhs = csm; +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(mi,mj) = rhs; +%! flhs(mi,mj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%% Indexed assignment of float scalar, float complex scalar, float matrix, +%% and float complex matrix to sparse matrix. + +%!test +%! lhs = sm_lhs; +%! rhs = single (s); +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(si,sj) = rhs; +%! flhs(si,sj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = sm_lhs; +%! rhs = single (cs); +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(si,sj) = rhs; +%! flhs(si,sj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = sm_lhs; +%! rhs = single (m); +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(mi,mj) = rhs; +%! flhs(mi,mj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = sm_lhs; +%! rhs = single (cm); +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(mi,mj) = rhs; +%! flhs(mi,mj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%% Indexed assignment of float scalar, float complex scalar, float matrix, +%% and float complex matrix to complex sparse matrix. + +%!test +%! lhs = csm_lhs; +%! rhs = single (s); +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(si,sj) = rhs; +%! flhs(si,sj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = csm_lhs; +%! rhs = single (cs); +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(si,sj) = rhs; +%! flhs(si,sj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = csm_lhs; +%! rhs = single (m); +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(mi,mj) = rhs; +%! flhs(mi,mj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs)); + +%!test +%! lhs = csm_lhs; +%! rhs = single (cm); +%! flhs = full (lhs); +%! frhs = full (rhs); +%! lhs(mi,mj) = rhs; +%! flhs(mi,mj) = frhs; +%! assert (issparse (lhs)); +%! assert (full (lhs), flhs); +%! assert (iscomplex (lhs), iscomplex (lhs) || iscomplex (rhs));