changeset 32129:13fbc97f9362

new functions to initialize a tree_matrix matrix object * pt-tm-const.h, pt-tm-const.cc (tm_row_const::tm_row_const, tm_const::tm_const, tm_row_const::init, tm_const::init): New constructors and overloaded init methods that accept pointers to the beginning and end of a contiguous range of octave_value objects.
author Petter T. <petter.vilhelm@gmail.com>
date Thu, 15 Jun 2023 14:08:45 -0400
parents d3023141b792
children dedc746ecd58
files libinterp/parse-tree/pt-tm-const.cc libinterp/parse-tree/pt-tm-const.h
diffstat 2 files changed, 361 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/parse-tree/pt-tm-const.cc	Thu Jun 15 15:46:59 2023 -0400
+++ b/libinterp/parse-tree/pt-tm-const.cc	Thu Jun 15 14:08:45 2023 -0400
@@ -160,6 +160,13 @@
   m_all_1x1 = m_all_1x1 && ! val.issparse () && val.numel () == 1;
 }
 
+// FIXME: This function is mostly a duplicate of
+//
+//   void tm_row_const::init (const octave_value *, const octave_value *)
+//
+// The common parts should be factored out into a single function that
+// is used by the others.
+
 void tm_row_const::init (const tree_argument_list& row, tree_evaluator& tw)
 {
   bool first_elem = true;
@@ -214,6 +221,68 @@
     }
 }
 
+// FIXME: This function is mostly a duplicate of
+//
+//   void tm_row_const::init (const tree_argument_list&, tree_evaluator&)
+//
+// The common parts should be factored out into a single function that
+// is used by the others.
+
+void tm_row_const::init (const octave_value *beg, const octave_value *end)
+{
+  bool first_elem = true;
+
+  for (; beg != end; beg++)
+    {
+      octave_quit ();
+
+      octave_value tmp = *beg;
+
+      if (tmp.is_undefined ())
+        error ("undefined element in matrix list");
+
+      if (tmp.is_cs_list ())
+        {
+          octave_value_list tlst = tmp.list_value ();
+
+          for (octave_idx_type i = 0; i < tlst.length (); i++)
+            {
+              octave_quit ();
+
+              init_element (tlst(i), first_elem);
+            }
+        }
+      else
+        init_element (tmp, first_elem);
+    }
+
+  if (m_any_cell && ! m_any_class && ! m_first_elem_is_struct)
+    cellify ();
+
+  first_elem = true;
+
+  for (const auto& val : m_values)
+    {
+      octave_quit ();
+
+      dim_vector this_elt_dv = val.dims ();
+
+      if (! this_elt_dv.zero_by_zero ())
+        {
+          m_all_empty = false;
+
+          if (first_elem)
+            {
+              first_elem = false;
+              m_dv = this_elt_dv;
+            }
+          else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 1)))
+            eval_error ("horizontal dimensions mismatch", m_dv, this_elt_dv);
+        }
+    }
+}
+
+
 octave_value tm_const::concat (char string_fill_char) const
 {
   if (m_tm_rows.empty ())
@@ -295,6 +364,16 @@
     return generic_concat ();
 }
 
+// FIXME: This function is mostly a duplicate of both of the functions
+//
+//   void tm_const::init (const octave_value *, const octave_value *,
+//                        const std::vector<int>&)
+//   void tm_const::init (const octave_value *, const octave_value *,
+//                        octave_idx_type)
+//
+// The common parts should be factored out into a single function that
+// is used by the others.
+
 void tm_const::init (const tree_matrix& tm)
 {
   bool first_elem = true;
@@ -410,6 +489,261 @@
     }
 }
 
+// FIXME: This function is mostly a duplicate of both of the functions
+//
+//   void tm_const::init (const tree_matrix&)
+//   void tm_const::init (const octave_value *, const octave_value *,
+//                        octave_idx_type)
+//
+// The common parts should be factored out into a single function that
+// is used by the others.
+
+// For variable length rows
+void tm_const::init (const octave_value *beg, const octave_value *end,
+                     const std::vector<int>& row_lengths)
+{
+  bool first_elem = true;
+  bool first_elem_is_struct = false;
+
+  // Just eval and figure out if what we have is complex or all strings.
+  // We can't check columns until we know that this is a numeric matrix --
+  // collections of strings can have elements of different lengths.
+
+  for (int i = 0; beg != end; beg += row_lengths[i++])
+    {
+      octave_quit ();
+
+      if (beg + row_lengths[i] > end)
+        error ("invalid call to tm_const::init");
+
+      tm_row_const row (beg, beg + row_lengths[i]);
+
+      if (first_elem)
+        {
+          first_elem_is_struct = row.first_elem_struct_p ();
+
+          first_elem = false;
+        }
+
+      if (row.empty ())
+        continue;
+
+      if (m_all_strings && ! row.all_strings_p ())
+        m_all_strings = false;
+
+      if (m_all_sq_strings && ! row.all_sq_strings_p ())
+        m_all_sq_strings = false;
+
+      if (m_all_dq_strings && ! row.all_dq_strings_p ())
+        m_all_dq_strings = false;
+
+      if (! m_some_strings && row.some_strings_p ())
+        m_some_strings = true;
+
+      if (m_all_real && ! row.all_real_p ())
+        m_all_real = false;
+
+      if (m_all_complex && ! row.all_complex_p ())
+        m_all_complex = false;
+
+      if (m_all_empty && ! row.all_empty_p ())
+        m_all_empty = false;
+
+      if (! m_any_cell && row.any_cell_p ())
+        m_any_cell = true;
+
+      if (! m_any_sparse && row.any_sparse_p ())
+        m_any_sparse = true;
+
+      if (! m_any_class && row.any_class_p ())
+        m_any_class = true;
+
+      m_all_1x1 = m_all_1x1 && row.all_1x1_p ();
+
+      m_tm_rows.push_back (row);
+    }
+
+  if (m_any_cell && ! m_any_class && ! first_elem_is_struct)
+    {
+      for (auto& elt : m_tm_rows)
+        {
+          octave_quit ();
+
+          elt.cellify ();
+        }
+    }
+
+  first_elem = true;
+
+  for (const auto& elt : m_tm_rows)
+    {
+      octave_quit ();
+
+      octave_idx_type this_elt_nr = elt.rows ();
+      octave_idx_type this_elt_nc = elt.cols ();
+
+      std::string this_elt_class_name = elt.class_name ();
+      m_class_name = get_concat_class (m_class_name, this_elt_class_name);
+
+      dim_vector this_elt_dv = elt.dims ();
+
+      m_all_empty = false;
+
+      if (first_elem)
+        {
+          first_elem = false;
+
+          m_dv = this_elt_dv;
+        }
+      else if (m_all_strings && m_dv.ndims () == 2
+               && this_elt_dv.ndims () == 2)
+        {
+          // This is Octave's specialty.
+          // Character matrices support rows of unequal length.
+          if (m_dv.any_zero ())
+            {
+              // Empty existing element (bug #52542).
+              // Replace empty element with non-empty one.
+              m_dv = this_elt_dv;
+            }
+          else
+            {
+              if (this_elt_nc > cols ())
+                m_dv(1) = this_elt_nc;
+              m_dv(0) += this_elt_nr;
+            }
+        }
+      else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 0)))
+        eval_error ("vertical dimensions mismatch", m_dv, this_elt_dv);
+    }
+}
+
+// FIXME: This function is mostly a duplicate of both of the functions
+//
+//   void tm_const::init (const tree_matrix&)
+//   void tm_const::init (const octave_value *, const octave_value *,
+//                        const std::vector<int>&)
+//
+// The common parts should be factored out into a single function that
+// is used by the others.
+
+// Fixed row size
+void tm_const::init (const octave_value *beg, const octave_value *end,
+                     octave_idx_type row_length)
+{
+  bool first_elem = true;
+  bool first_elem_is_struct = false;
+
+  // Just eval and figure out if what we have is complex or all strings.
+  // We can't check columns until we know that this is a numeric matrix --
+  // collections of strings can have elements of different lengths.
+
+  for (;beg != end; beg += row_length)
+    {
+      octave_quit ();
+
+      tm_row_const row (beg, beg + row_length);
+
+      if (first_elem)
+        {
+          first_elem_is_struct = row.first_elem_struct_p ();
+
+          first_elem = false;
+        }
+
+      if (row.empty ())
+        continue;
+
+      if (m_all_strings && ! row.all_strings_p ())
+        m_all_strings = false;
+
+      if (m_all_sq_strings && ! row.all_sq_strings_p ())
+        m_all_sq_strings = false;
+
+      if (m_all_dq_strings && ! row.all_dq_strings_p ())
+        m_all_dq_strings = false;
+
+      if (! m_some_strings && row.some_strings_p ())
+        m_some_strings = true;
+
+      if (m_all_real && ! row.all_real_p ())
+        m_all_real = false;
+
+      if (m_all_complex && ! row.all_complex_p ())
+        m_all_complex = false;
+
+      if (m_all_empty && ! row.all_empty_p ())
+        m_all_empty = false;
+
+      if (! m_any_cell && row.any_cell_p ())
+        m_any_cell = true;
+
+      if (! m_any_sparse && row.any_sparse_p ())
+        m_any_sparse = true;
+
+      if (! m_any_class && row.any_class_p ())
+        m_any_class = true;
+
+      m_all_1x1 = m_all_1x1 && row.all_1x1_p ();
+
+      m_tm_rows.push_back (row);
+    }
+
+  if (m_any_cell && ! m_any_class && ! first_elem_is_struct)
+    {
+      for (auto& elt : m_tm_rows)
+        {
+          octave_quit ();
+
+          elt.cellify ();
+        }
+    }
+
+  first_elem = true;
+
+  for (const auto& elt : m_tm_rows)
+    {
+      octave_quit ();
+
+      octave_idx_type this_elt_nr = elt.rows ();
+      octave_idx_type this_elt_nc = elt.cols ();
+
+      std::string this_elt_class_name = elt.class_name ();
+      m_class_name = get_concat_class (m_class_name, this_elt_class_name);
+
+      dim_vector this_elt_dv = elt.dims ();
+
+      m_all_empty = false;
+
+      if (first_elem)
+        {
+          first_elem = false;
+
+          m_dv = this_elt_dv;
+        }
+      else if (m_all_strings && m_dv.ndims () == 2
+               && this_elt_dv.ndims () == 2)
+        {
+          // This is Octave's specialty.
+          // Character matrices support rows of unequal length.
+          if (m_dv.any_zero ())
+            {
+              // Empty existing element (bug #52542).
+              // Replace empty element with non-empty one.
+              m_dv = this_elt_dv;
+            }
+          else
+            {
+              if (this_elt_nc > cols ())
+                m_dv(1) = this_elt_nc;
+              m_dv(0) += this_elt_nr;
+            }
+        }
+      else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 0)))
+        eval_error ("vertical dimensions mismatch", m_dv, this_elt_dv);
+    }
+}
+
 octave_value tm_const::char_array_concat (char string_fill_char) const
 {
   char type = (m_all_dq_strings ? '"' : '\'');
--- a/libinterp/parse-tree/pt-tm-const.h	Thu Jun 15 15:46:59 2023 -0400
+++ b/libinterp/parse-tree/pt-tm-const.h	Thu Jun 15 14:08:45 2023 -0400
@@ -157,6 +157,12 @@
     init (row, tw);
   }
 
+  tm_row_const (const octave_value *beg, const octave_value *end)
+    : tm_info (beg == end), m_values ()
+  {
+    init (beg, end);
+  }
+
   tm_row_const (const tm_row_const&) = default;
 
   tm_row_const& operator = (const tm_row_const&) = delete;
@@ -182,6 +188,7 @@
   void init_element (const octave_value&, bool&);
 
   void init (const tree_argument_list&, tree_evaluator& tw);
+  void init (const octave_value *beg, const octave_value *end);
 };
 
 class tm_const : public tm_info
@@ -199,6 +206,20 @@
     init (tm);
   }
 
+  tm_const (const octave_value *beg, const octave_value *end,
+            octave_idx_type n_rows, tree_evaluator& tw)
+    : tm_info (beg == end), m_evaluator (tw), m_tm_rows ()
+  {
+     init (beg, end, n_rows);
+  }
+
+  tm_const (const octave_value *beg, const octave_value *end,
+            const std::vector<int>& row_lengths, tree_evaluator& tw)
+    : tm_info (beg == end), m_evaluator (tw), m_tm_rows ()
+  {
+     init (beg, end, row_lengths);
+  }
+
   OCTAVE_DISABLE_COPY_MOVE (tm_const)
 
   ~tm_const () = default;
@@ -217,6 +238,12 @@
 
   void init (const tree_matrix& tm);
 
+  void init (const octave_value *beg, const octave_value *end,
+             octave_idx_type row_length);
+
+  void init (const octave_value *beg, const octave_value *end,
+             const std::vector<int>& row_lengths);
+
   octave_value char_array_concat (char string_fill_char) const;
 
   octave_value class_concat () const;