changeset 15430:4db96357fec9

maint: periodic merge of stable to default
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Fri, 21 Sep 2012 17:24:46 -0400
parents 6823ad7a25b1 (current diff) fd5c0159b588 (diff)
children 21467c7fc08f
files libinterp/interpfcn/data.cc libinterp/octave-value/ov-base-diag.cc libinterp/octave-value/ov-base-diag.h libinterp/octave-value/ov.cc libinterp/octave-value/ov.h liboctave/array/DiagArray2.cc liboctave/array/DiagArray2.h
diffstat 7 files changed, 73 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/interpfcn/data.cc
+++ b/libinterp/interpfcn/data.cc
@@ -1338,6 +1338,11 @@
 %!assert (diag (int8 ([0, 1, 0, 0; 0, 0, 2, 0; 0, 0, 0, 3; 0, 0, 0, 0]), 1), int8 ([1; 2; 3]))
 %!assert (diag (int8 ([0, 0, 0, 0; 1, 0, 0, 0; 0, 2, 0, 0; 0, 0, 3, 0]), -1), int8 ([1; 2; 3]))
 
+## bug #37411
+%!assert (diag (diag ([5, 2, 3])(:,1)), diag([5 0 0 ]))
+%!assert (diag (diag ([5, 2, 3])(:,1), 2),  [0 0 5 0 0; zeros(4, 5)])
+%!assert (diag (diag ([5, 2, 3])(:,1), -2), [[0 0 5 0 0]', zeros(5, 4)])
+
 ## Test non-square size
 %!assert (diag ([1,2,3], 6, 3), [1 0 0; 0 2 0; 0 0 3; 0 0 0; 0 0 0; 0 0 0])
 %!assert (diag (1, 2, 3), [1,0,0; 0,0,0]);
--- a/libinterp/octave-value/ov-base-diag.cc
+++ b/libinterp/octave-value/ov-base-diag.cc
@@ -68,6 +68,32 @@
   return retval.next_subsref (type, idx);
 }
 
+
+template <class DMT, class MT>
+octave_value
+octave_base_diag<DMT,MT>::diag (octave_idx_type k) const
+{
+  octave_value retval;
+  if (matrix.rows () == 1 || matrix.cols () == 1)
+    {
+      // Rather odd special case. This is a row or column vector
+      // represented as a diagonal matrix with a single nonzero entry, but
+      // Fdiag semantics are to product a diagonal matrix for vector
+      // inputs.
+      if (k == 0)
+        // Returns Diag2Array<T> with nnz <= 1.
+        retval = matrix.build_diag_matrix ();
+      else
+        // Returns Array<T> matrix
+        retval = matrix.array_value ().diag (k);
+    }
+  else
+    // Returns Array<T> vector
+    retval = matrix.extract_diag (k);
+  return retval;
+}
+
+
 template <class DMT, class MT>
 octave_value
 octave_base_diag<DMT, MT>::do_index_op (const octave_value_list& idx,
--- a/libinterp/octave-value/ov-base-diag.h
+++ b/libinterp/octave-value/ov-base-diag.h
@@ -97,8 +97,7 @@
   MatrixType matrix_type (const MatrixType&) const
     { return matrix_type (); }
 
-  octave_value diag (octave_idx_type k = 0) const
-    { return octave_value (matrix.diag (k)); }
+  octave_value diag (octave_idx_type k = 0) const;
 
   octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const
     { return to_dense ().sort (dim, mode); }
--- a/libinterp/octave-value/ov.cc
+++ b/libinterp/octave-value/ov.cc
@@ -669,6 +669,30 @@
   maybe_mutate ();
 }
 
+octave_value::octave_value (const DiagArray2<double>& d)
+  : rep (new octave_diag_matrix (d))
+{
+  maybe_mutate ();
+}
+
+octave_value::octave_value (const DiagArray2<float>& d)
+  : rep (new octave_float_diag_matrix (d))
+{
+  maybe_mutate ();
+}
+
+octave_value::octave_value (const DiagArray2<Complex>& d)
+  : rep (new octave_complex_diag_matrix (d))
+{
+  maybe_mutate ();
+}
+
+octave_value::octave_value (const DiagArray2<FloatComplex>& d)
+  : rep (new octave_float_complex_diag_matrix (d))
+{
+  maybe_mutate ();
+}
+
 octave_value::octave_value (const DiagMatrix& d)
   : rep (new octave_diag_matrix (d))
 {
--- a/libinterp/octave-value/ov.h
+++ b/libinterp/octave-value/ov.h
@@ -203,6 +203,10 @@
   octave_value (const Array<double>& m);
   octave_value (const Array<float>& m);
   octave_value (const DiagMatrix& d);
+  octave_value (const DiagArray2<double>& d);
+  octave_value (const DiagArray2<float>& d);
+  octave_value (const DiagArray2<Complex>& d);
+  octave_value (const DiagArray2<FloatComplex>& d);
   octave_value (const FloatDiagMatrix& d);
   octave_value (const RowVector& v);
   octave_value (const FloatRowVector& v);
--- a/liboctave/array/DiagArray2.cc
+++ b/liboctave/array/DiagArray2.cc
@@ -48,6 +48,13 @@
 
 template <class T>
 Array<T>
+DiagArray2<T>::extract_diag (octave_idx_type k) const
+{
+  return diag (k);
+}
+
+template <class T>
+Array<T>
 DiagArray2<T>::diag (octave_idx_type k) const
 {
   Array<T> d;
--- a/liboctave/array/DiagArray2.h
+++ b/liboctave/array/DiagArray2.h
@@ -64,7 +64,7 @@
 
   template <class U>
   DiagArray2 (const DiagArray2<U>& a)
-    : Array<T> (a.diag ()), d1 (a.dim1 ()), d2 (a.dim2 ()) { }
+    : Array<T> (a.extract_diag ()), d1 (a.dim1 ()), d2 (a.dim2 ()) { }
 
   ~DiagArray2 (void) { }
 
@@ -98,6 +98,11 @@
   dim_vector dims (void) const { return dim_vector (d1, d2); }
 
   Array<T> diag (octave_idx_type k = 0) const;
+  Array<T> extract_diag (octave_idx_type k = 0) const;
+  DiagArray2<T> build_diag_matrix () const
+  {
+    return DiagArray2<T> (array_value ());
+  }
 
   // Warning: the non-const two-index versions will silently ignore assignments
   // to off-diagonal elements.