changeset 13142:d803d2702a39

improve compatibility of concatenation (bug #33966) * op-cell.cc (oct_catop_cell_matrix, oct_catop_matrix_cell): Delete concatenation functions. (install_cell_ops): Don't install them. * ov-bool.h (octave_bool::int8_scalar_value, octave_bool::int16_scalar_value, octave_bool::int32_scalar_value, octave_bool::int64_scalar_value, octave_bool::uint8_scalar_value, octave_bool::uint16_scalar_value, octave_bool::uint32_scalar_value, octave_bool::uint64_scalar_value): New functions. * pt-mat.cc: New tests for concatentation. (tree_matrix::rvalue1): Special case cell concatentation. (eval_error): Don't print line and column info. Change all callers. (tm_row_const::tm_row_const_rep::do_init_element) (tm_row_const::tm_row_const_rep::any_cell, tm_row_const::tm_row_const_rep::first_elem_is_struct): New data members. Adjust constructor initialization lists. (tm_row_const::any_cell_p): New function. (get_concat_class): Give structs and cells proper precedence. Handle "class". (tm_row_const::tm_row_const_rep::do_init_element): Check for cells and whether the first element is a struct. Don't check dimensions here. (tm_row_const::tm_row_const_rep::init): Convert expressions to values here. Maybe convert list elements to cells. Check dimensions.
author John W. Eaton <jwe@octave.org>
date Thu, 15 Sep 2011 17:25:21 -0400
parents e81ddf9cacd5
children bda7b080f205
files src/OPERATORS/op-cell.cc src/ov-bool.h src/pt-mat.cc
diffstat 3 files changed, 284 insertions(+), 77 deletions(-) [+]
line wrap: on
line diff
--- a/src/OPERATORS/op-cell.cc	Thu Sep 15 12:51:10 2011 -0400
+++ b/src/OPERATORS/op-cell.cc	Thu Sep 15 17:25:21 2011 -0400
@@ -51,36 +51,6 @@
 
 DEFCATOP_FN (c_c, cell, cell, concat)
 
-static octave_value
-oct_catop_cell_matrix (octave_base_value& a1, const octave_base_value& a2,
-                         const Array<octave_idx_type>&)
-{
-  octave_value retval;
-  CAST_BINOP_ARGS (const octave_cell&, const octave_matrix&);
-  NDArray tmp = v2.array_value ();
-  dim_vector dv = tmp.dims ();
-  if (dv.all_zero ())
-    retval = octave_value (v1.cell_value ());
-  else
-    error ("invalid concatenation of cell array with matrix");
-  return retval;
-}
-
-static octave_value
-oct_catop_matrix_cell (octave_base_value& a1, const octave_base_value& a2,
-                         const Array<octave_idx_type>&)
-{
-  octave_value retval;
-  CAST_BINOP_ARGS (const octave_matrix&, const octave_cell&);
-  NDArray tmp = v1.array_value ();
-  dim_vector dv = tmp.dims ();
-  if (dv.all_zero ())
-    retval = octave_value (v2.cell_value ());
-  else
-    error ("invalid concatenation of cell array with matrix");
-  return retval;
-}
-
 DEFASSIGNANYOP_FN (assign, cell, assign);
 
 DEFNULLASSIGNOP_FN (null_assign, cell, delete_elements)
@@ -93,9 +63,6 @@
 
   INSTALL_CATOP (octave_cell, octave_cell, c_c);
 
-  INSTALL_CATOP (octave_cell, octave_matrix, cell_matrix);
-  INSTALL_CATOP (octave_matrix, octave_cell, matrix_cell);
-
   INSTALL_ASSIGNANYOP (op_asn_eq, octave_cell, assign);
 
   INSTALL_ASSIGNOP (op_asn_eq, octave_cell, octave_null_matrix, null_assign);
--- a/src/ov-bool.h	Thu Sep 15 12:51:10 2011 -0400
+++ b/src/ov-bool.h	Thu Sep 15 17:25:21 2011 -0400
@@ -119,6 +119,30 @@
   uint64_array_value (void) const
     { return uint64NDArray (dim_vector (1, 1), scalar); }
 
+  octave_int8
+  int8_scalar_value (void) const { return octave_int8 (scalar); }
+
+  octave_int16
+  int16_scalar_value (void) const { return octave_int16 (scalar); }
+
+  octave_int32
+  int32_scalar_value (void) const { return octave_int32 (scalar); }
+
+  octave_int64
+  int64_scalar_value (void) const { return octave_int64 (scalar); }
+
+  octave_uint8
+  uint8_scalar_value (void) const { return octave_uint8 (scalar); }
+
+  octave_uint16
+  uint16_scalar_value (void) const { return octave_uint16 (scalar); }
+
+  octave_uint32
+  uint32_scalar_value (void) const { return octave_uint32 (scalar); }
+
+  octave_uint64
+  uint64_scalar_value (void) const { return octave_uint64 (scalar); }
+
   double double_value (bool = false) const { return scalar; }
 
   float float_value (bool = false) const { return scalar; }
--- a/src/pt-mat.cc	Thu Sep 15 12:51:10 2011 -0400
+++ b/src/pt-mat.cc	Thu Sep 15 17:25:21 2011 -0400
@@ -68,15 +68,17 @@
       : count (1), dv (0, 0), all_str (false),
         all_sq_str (false), all_dq_str (false),
         some_str (false), all_real (false), all_cmplx (false),
-        all_mt (true), any_sparse (false), any_class (false),
-        all_1x1 (false), class_nm (), ok (false)
+        all_mt (true), any_cell (false), any_sparse (false),
+        any_class (false), all_1x1 (false),
+        first_elem_is_struct (false), class_nm (), ok (false)
     { }
 
     tm_row_const_rep (const tree_argument_list& row)
       : count (1), dv (0, 0), all_str (false), all_sq_str (false),
         some_str (false), all_real (false), all_cmplx (false),
-        all_mt (true), any_sparse (false), any_class (false),
-        all_1x1 (! row.empty ()), class_nm (), ok (false)
+        all_mt (true), any_cell (false), any_sparse (false),
+        any_class (false), all_1x1 (! row.empty ()),
+        first_elem_is_struct (false), class_nm (), ok (false)
     { init (row); }
 
     ~tm_row_const_rep (void) { }
@@ -92,15 +94,17 @@
     bool all_real;
     bool all_cmplx;
     bool all_mt;
+    bool any_cell;
     bool any_sparse;
     bool any_class;
     bool all_1x1;
+    bool first_elem_is_struct;
 
     std::string class_nm;
 
     bool ok;
 
-    bool do_init_element (tree_expression *, const octave_value&, bool&);
+    void do_init_element (const octave_value&, bool&);
 
     void init (const tree_argument_list&);
 
@@ -169,6 +173,7 @@
   bool all_real_p (void) const { return rep->all_real; }
   bool all_complex_p (void) const { return rep->all_cmplx; }
   bool all_empty_p (void) const { return rep->all_mt; }
+  bool any_cell_p (void) const { return rep->any_cell; }
   bool any_sparse_p (void) const { return rep->any_sparse; }
   bool any_class_p (void) const { return rep->any_class; }
   bool all_1x1_p (void) const { return rep->all_1x1; }
@@ -199,6 +204,8 @@
     retval = c2;
   else if (c2.empty ())
     retval = c1;
+  else if (c1 == "class" || c2 == "class")
+    retval = "class";
   else
     {
       bool c1_is_int = (c1 == "int8" || c1 == "uint8"
@@ -232,7 +239,11 @@
 
       // Order is important here...
 
-      if (c1_is_char && c2_is_built_in_type)
+      if (c1 == "struct" && c2 == c1)
+        retval = c1;
+      else if (c1 == "cell" || c2 == "cell")
+        retval = "cell";
+      else if (c1_is_char && c2_is_built_in_type)
         retval = c1;
       else if (c2_is_char && c1_is_built_in_type)
         retval = c2;
@@ -250,54 +261,38 @@
         retval = c2;
       else if (c1_is_logical && c2_is_logical)
         retval = c1;
-      else if (c1 == "struct" && c2 == c1)
-        retval = c1;
-      else if (c1 == "cell" && c2 == c1)
-        retval = c1;
     }
 
   return retval;
 }
 
 static void
-eval_error (const char *msg, int l, int c,
-            const dim_vector& x, const dim_vector& y)
+eval_error (const char *msg, const dim_vector& x, const dim_vector& y)
 {
-  if (l == -1 && c == -1)
-    {
-      ::error ("%s (%s vs %s)", msg, x.str ().c_str (), y.str ().c_str ());
-    }
-  else
-    {
-      ::error ("%s (%s vs %s) near line %d, column %d", msg,
-               x.str ().c_str (), y.str ().c_str (), l, c);
-    }
+  ::error ("%s (%s vs %s)", msg, x.str ().c_str (), y.str ().c_str ());
 }
 
-bool
-tm_row_const::tm_row_const_rep::do_init_element (tree_expression *elt,
-                                                 const octave_value& val,
+void
+tm_row_const::tm_row_const_rep::do_init_element (const octave_value& val,
                                                  bool& first_elem)
 {
-  std::string this_elt_class_nm = val.class_name ();
+  std::string this_elt_class_nm
+    = val.is_object () ? std::string ("class") : val.class_name ();
+
+  class_nm = get_concat_class (class_nm, this_elt_class_nm);
 
   dim_vector this_elt_dv = val.dims ();
 
-  class_nm = get_concat_class (class_nm, this_elt_class_nm);
-
   if (! this_elt_dv.zero_by_zero ())
     {
       all_mt = false;
 
       if (first_elem)
         {
+          if (val.is_map ())
+            first_elem_is_struct = true;
+
           first_elem = false;
-          dv = this_elt_dv;
-        }
-      else if (! dv.hvcat (this_elt_dv, 1))
-        {
-          eval_error ("horizontal dimensions mismatch", elt->line (), elt->column (), dv, this_elt_dv);
-          return false;
         }
     }
 
@@ -321,6 +316,9 @@
   if (all_cmplx && ! (val.is_complex_type () || val.is_real_type ()))
     all_cmplx = false;
 
+  if (!any_cell && val.is_cell ())
+    any_cell = true;
+
   if (!any_sparse && val.is_sparse_type ())
     any_sparse = true;
 
@@ -328,8 +326,6 @@
     any_class = true;
 
   all_1x1 = all_1x1 && val.numel () == 1;
-
-  return true;
 }
 
 void
@@ -340,6 +336,7 @@
   all_dq_str = true;
   all_real = true;
   all_cmplx = true;
+  any_cell = false;
   any_sparse = false;
   any_class = false;
 
@@ -356,7 +353,10 @@
       octave_value tmp = elt->rvalue1 ();
 
       if (error_state || tmp.is_undefined ())
-        break;
+        {
+          ok = ! error_state;
+          return;
+        }
       else
         {
           if (tmp.is_cs_list ())
@@ -367,20 +367,48 @@
                 {
                   octave_quit ();
 
-                  if (! do_init_element (elt, tlst(i), first_elem))
-                    goto done;
+                  do_init_element (tlst(i), first_elem);
                 }
             }
           else
+            do_init_element (tmp, first_elem);
+        }
+    }
+
+  if (any_cell && ! any_class && ! first_elem_is_struct)
+    {
+      for (iterator p = begin (); p != end (); p++)
+        {
+          if (! p->is_cell ())
+            *p = Cell (*p);
+        }
+    }
+
+  first_elem = true;
+
+  for (iterator p = begin (); p != end (); p++)
+    {
+      octave_value val = *p;
+
+      dim_vector this_elt_dv = val.dims ();
+
+      if (! this_elt_dv.zero_by_zero ())
+        {
+          all_mt = false;
+
+          if (first_elem)
             {
-              if (! do_init_element (elt, tmp, first_elem))
-                goto done;
+              first_elem = false;
+              dv = this_elt_dv;
+            }
+          else if (! dv.hvcat (this_elt_dv, 1))
+            {
+              eval_error ("horizontal dimensions mismatch", dv, this_elt_dv);
+              break;
             }
         }
     }
 
- done:
-
   ok = ! error_state;
 }
 
@@ -556,8 +584,7 @@
             }
           else if (! dv.hvcat (this_elt_dv, 0))
             {
-              eval_error ("vertical dimensions mismatch", -1, -1,
-                          dv, this_elt_dv);
+              eval_error ("vertical dimensions mismatch", dv, this_elt_dv);
               return;
             }
         }
@@ -928,6 +955,10 @@
                 ::error ("cannot find overloaded vertcat function");
             }
         }
+      else if (result_type == "cell")
+        {
+          retval = do_single_type_concat<Cell> (dv, tmp);
+        }
       else if (result_type == "double")
         {
           if (any_sparse_p)
@@ -1129,6 +1160,191 @@
 %% test concatenation with all zero matrices
 %!assert([ '' 65*ones(1,10) ], 'AAAAAAAAAA');
 %!assert([ 65*ones(1,10) '' ], 'AAAAAAAAAA');
+
+%!assert (class ([int64(1), int64(1)]), 'int64')
+%!assert (class ([int64(1), int32(1)]), 'int64')
+%!assert (class ([int64(1), int16(1)]), 'int64')
+%!assert (class ([int64(1), int8(1)]), 'int64')
+%!assert (class ([int64(1), uint64(1)]), 'int64')
+%!assert (class ([int64(1), uint32(1)]), 'int64')
+%!assert (class ([int64(1), uint16(1)]), 'int64')
+%!assert (class ([int64(1), uint8(1)]), 'int64')
+%!assert (class ([int64(1), single(1)]), 'int64')
+%!assert (class ([int64(1), double(1)]), 'int64')
+%!assert (class ([int64(1), cell(1)]), 'cell')
+%!assert (class ([int64(1), true]), 'int64')
+%!assert (class ([int64(1), 'a']), 'char')
+
+%!assert (class ([int32(1), int64(1)]), 'int32')
+%!assert (class ([int32(1), int32(1)]), 'int32')
+%!assert (class ([int32(1), int16(1)]), 'int32')
+%!assert (class ([int32(1), int8(1)]), 'int32')
+%!assert (class ([int32(1), uint64(1)]), 'int32')
+%!assert (class ([int32(1), uint32(1)]), 'int32')
+%!assert (class ([int32(1), uint16(1)]), 'int32')
+%!assert (class ([int32(1), uint8(1)]), 'int32')
+%!assert (class ([int32(1), single(1)]), 'int32')
+%!assert (class ([int32(1), double(1)]), 'int32')
+%!assert (class ([int32(1), cell(1)]), 'cell')
+%!assert (class ([int32(1), true]), 'int32')
+%!assert (class ([int32(1), 'a']), 'char')
+
+%!assert (class ([int16(1), int64(1)]), 'int16')
+%!assert (class ([int16(1), int32(1)]), 'int16')
+%!assert (class ([int16(1), int16(1)]), 'int16')
+%!assert (class ([int16(1), int8(1)]), 'int16')
+%!assert (class ([int16(1), uint64(1)]), 'int16')
+%!assert (class ([int16(1), uint32(1)]), 'int16')
+%!assert (class ([int16(1), uint16(1)]), 'int16')
+%!assert (class ([int16(1), uint8(1)]), 'int16')
+%!assert (class ([int16(1), single(1)]), 'int16')
+%!assert (class ([int16(1), double(1)]), 'int16')
+%!assert (class ([int16(1), cell(1)]), 'cell')
+%!assert (class ([int16(1), true]), 'int16')
+%!assert (class ([int16(1), 'a']), 'char')
+
+%!assert (class ([int8(1), int64(1)]), 'int8')
+%!assert (class ([int8(1), int32(1)]), 'int8')
+%!assert (class ([int8(1), int16(1)]), 'int8')
+%!assert (class ([int8(1), int8(1)]), 'int8')
+%!assert (class ([int8(1), uint64(1)]), 'int8')
+%!assert (class ([int8(1), uint32(1)]), 'int8')
+%!assert (class ([int8(1), uint16(1)]), 'int8')
+%!assert (class ([int8(1), uint8(1)]), 'int8')
+%!assert (class ([int8(1), single(1)]), 'int8')
+%!assert (class ([int8(1), double(1)]), 'int8')
+%!assert (class ([int8(1), cell(1)]), 'cell')
+%!assert (class ([int8(1), true]), 'int8')
+%!assert (class ([int8(1), 'a']), 'char')
+
+%!assert (class ([uint64(1), int64(1)]), 'uint64')
+%!assert (class ([uint64(1), int32(1)]), 'uint64')
+%!assert (class ([uint64(1), int16(1)]), 'uint64')
+%!assert (class ([uint64(1), int8(1)]), 'uint64')
+%!assert (class ([uint64(1), uint64(1)]), 'uint64')
+%!assert (class ([uint64(1), uint32(1)]), 'uint64')
+%!assert (class ([uint64(1), uint16(1)]), 'uint64')
+%!assert (class ([uint64(1), uint8(1)]), 'uint64')
+%!assert (class ([uint64(1), single(1)]), 'uint64')
+%!assert (class ([uint64(1), double(1)]), 'uint64')
+%!assert (class ([uint64(1), cell(1)]), 'cell')
+%!assert (class ([uint64(1), true]), 'uint64')
+%!assert (class ([uint64(1), 'a']), 'char')
+
+%!assert (class ([uint32(1), int64(1)]), 'uint32')
+%!assert (class ([uint32(1), int32(1)]), 'uint32')
+%!assert (class ([uint32(1), int16(1)]), 'uint32')
+%!assert (class ([uint32(1), int8(1)]), 'uint32')
+%!assert (class ([uint32(1), uint64(1)]), 'uint32')
+%!assert (class ([uint32(1), uint32(1)]), 'uint32')
+%!assert (class ([uint32(1), uint16(1)]), 'uint32')
+%!assert (class ([uint32(1), uint8(1)]), 'uint32')
+%!assert (class ([uint32(1), single(1)]), 'uint32')
+%!assert (class ([uint32(1), double(1)]), 'uint32')
+%!assert (class ([uint32(1), cell(1)]), 'cell')
+%!assert (class ([uint32(1), true]), 'uint32')
+%!assert (class ([uint32(1), 'a']), 'char')
+
+%!assert (class ([uint16(1), int64(1)]), 'uint16')
+%!assert (class ([uint16(1), int32(1)]), 'uint16')
+%!assert (class ([uint16(1), int16(1)]), 'uint16')
+%!assert (class ([uint16(1), int8(1)]), 'uint16')
+%!assert (class ([uint16(1), uint64(1)]), 'uint16')
+%!assert (class ([uint16(1), uint32(1)]), 'uint16')
+%!assert (class ([uint16(1), uint16(1)]), 'uint16')
+%!assert (class ([uint16(1), uint8(1)]), 'uint16')
+%!assert (class ([uint16(1), single(1)]), 'uint16')
+%!assert (class ([uint16(1), double(1)]), 'uint16')
+%!assert (class ([uint16(1), cell(1)]), 'cell')
+%!assert (class ([uint16(1), true]), 'uint16')
+%!assert (class ([uint16(1), 'a']), 'char')
+
+%!assert (class ([uint8(1), int64(1)]), 'uint8')
+%!assert (class ([uint8(1), int32(1)]), 'uint8')
+%!assert (class ([uint8(1), int16(1)]), 'uint8')
+%!assert (class ([uint8(1), int8(1)]), 'uint8')
+%!assert (class ([uint8(1), uint64(1)]), 'uint8')
+%!assert (class ([uint8(1), uint32(1)]), 'uint8')
+%!assert (class ([uint8(1), uint16(1)]), 'uint8')
+%!assert (class ([uint8(1), uint8(1)]), 'uint8')
+%!assert (class ([uint8(1), single(1)]), 'uint8')
+%!assert (class ([uint8(1), double(1)]), 'uint8')
+%!assert (class ([uint8(1), cell(1)]), 'cell')
+%!assert (class ([uint8(1), true]), 'uint8')
+%!assert (class ([uint8(1), 'a']), 'char')
+
+%!assert (class ([single(1), int64(1)]), 'int64')
+%!assert (class ([single(1), int32(1)]), 'int32')
+%!assert (class ([single(1), int16(1)]), 'int16')
+%!assert (class ([single(1), int8(1)]), 'int8')
+%!assert (class ([single(1), uint64(1)]), 'uint64')
+%!assert (class ([single(1), uint32(1)]), 'uint32')
+%!assert (class ([single(1), uint16(1)]), 'uint16')
+%!assert (class ([single(1), uint8(1)]), 'uint8')
+%!assert (class ([single(1), single(1)]), 'single')
+%!assert (class ([single(1), double(1)]), 'single')
+%!assert (class ([single(1), cell(1)]), 'cell')
+%!assert (class ([single(1), true]), 'single')
+%!assert (class ([single(1), 'a']), 'char')
+
+%!assert (class ([double(1), int64(1)]), 'int64')
+%!assert (class ([double(1), int32(1)]), 'int32')
+%!assert (class ([double(1), int16(1)]), 'int16')
+%!assert (class ([double(1), int8(1)]), 'int8')
+%!assert (class ([double(1), uint64(1)]), 'uint64')
+%!assert (class ([double(1), uint32(1)]), 'uint32')
+%!assert (class ([double(1), uint16(1)]), 'uint16')
+%!assert (class ([double(1), uint8(1)]), 'uint8')
+%!assert (class ([double(1), single(1)]), 'single')
+%!assert (class ([double(1), double(1)]), 'double')
+%!assert (class ([double(1), cell(1)]), 'cell')
+%!assert (class ([double(1), true]), 'double')
+%!assert (class ([double(1), 'a']), 'char')
+
+%!assert (class ([cell(1), int64(1)]), 'cell')
+%!assert (class ([cell(1), int32(1)]), 'cell')
+%!assert (class ([cell(1), int16(1)]), 'cell')
+%!assert (class ([cell(1), int8(1)]), 'cell')
+%!assert (class ([cell(1), uint64(1)]), 'cell')
+%!assert (class ([cell(1), uint32(1)]), 'cell')
+%!assert (class ([cell(1), uint16(1)]), 'cell')
+%!assert (class ([cell(1), uint8(1)]), 'cell')
+%!assert (class ([cell(1), single(1)]), 'cell')
+%!assert (class ([cell(1), double(1)]), 'cell')
+%!assert (class ([cell(1), cell(1)]), 'cell')
+%!assert (class ([cell(1), true]), 'cell')
+%!assert (class ([cell(1), 'a']), 'cell')
+
+%!assert (class ([true, int64(1)]), 'int64')
+%!assert (class ([true, int32(1)]), 'int32')
+%!assert (class ([true, int16(1)]), 'int16')
+%!assert (class ([true, int8(1)]), 'int8')
+%!assert (class ([true, uint64(1)]), 'uint64')
+%!assert (class ([true, uint32(1)]), 'uint32')
+%!assert (class ([true, uint16(1)]), 'uint16')
+%!assert (class ([true, uint8(1)]), 'uint8')
+%!assert (class ([true, single(1)]), 'single')
+%!assert (class ([true, double(1)]), 'double')
+%!assert (class ([true, cell(1)]), 'cell')
+%!assert (class ([true, true]), 'logical')
+%!assert (class ([true, 'a']), 'char')
+
+%!assert (class (['a', int64(1)]), 'char')
+%!assert (class (['a', int32(1)]), 'char')
+%!assert (class (['a', int16(1)]), 'char')
+%!assert (class (['a', int8(1)]), 'char')
+%!assert (class (['a', int64(1)]), 'char')
+%!assert (class (['a', int32(1)]), 'char')
+%!assert (class (['a', int16(1)]), 'char')
+%!assert (class (['a', int8(1)]), 'char')
+%!assert (class (['a', single(1)]), 'char')
+%!assert (class (['a', double(1)]), 'char')
+%!assert (class (['a', cell(1)]), 'cell')
+%!assert (class (['a', true]), 'char')
+%!assert (class (['a', 'a']), 'char')
+
+%!assert (class ([cell(1), struct('foo', 'bar')]), 'cell')
+%!error [struct('foo', 'bar'), cell(1)];
 */
 
 DEFUN (string_fill_char, args, nargout,