1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING.  If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if ! defined (octave_pt_tm_const_h)
27 #define octave_pt_tm_const_h 1
28 
29 #include "octave-config.h"
30 
31 #include <list>
32 #include <memory>
33 #include <string>
34 
35 #include "Array.h"
36 #include "Sparse.h"
37 
38 #include "data.h"
39 #include "dim-vector.h"
40 #include "oct-map.h"
41 #include "ov.h"
42 #include "ovl.h"
43 #include "pt-arg-list.h"
44 #include "pt-mat.h"
45 
46 namespace octave
47 {
48   class tree_evaluator;
49 
50   // Evaluate tree_matrix objects and convert them to octave_value
51   // arrays (full and sparse numeric, char, cell, struct, class and
52   // anything else that works like an array).  Use a separate class
53   // (tm_const) and pass the evaluator object to it instead of doing
54   // all this work in tree_evaluator::visit_matrix because the job is
55   // fairly large and requires extra data (stored in the tm_info
56   // class) for each row and for the overall array.
57 
58   // Evaluate all elements of the array, recording info about each
59   // row, then create summary info for the full array.  Compute the
60   // result type and dimension first before copying values.
61 
62   // FIXME: Handle overloading of horzcat and vertcat for for built-in
63   // types.
64 
65   // Summary info about the current row or matrix.
66 
67   class tm_info
68   {
69   public:
70 
tm_info(bool obj_is_empty)71     tm_info (bool obj_is_empty)
72       : m_dv (0, 0), m_all_strings (true), m_all_sq_strings (true),
73         m_all_dq_strings (true), m_some_strings (false),
74         m_all_real (true), m_all_complex (true), m_all_empty (true),
75         m_any_cell (false), m_any_sparse (false),
76         m_any_class (false), m_all_1x1 (! obj_is_empty),
77         m_first_elem_is_struct (false), m_class_name ()
78     { }
79 
dims(void)80     dim_vector dims (void) const { return m_dv; }
81 
rows(void)82     octave_idx_type rows (void) const { return m_dv(0); }
cols(void)83     octave_idx_type cols (void) const { return m_dv(1); }
84 
all_strings_p(void)85     bool all_strings_p (void) const { return m_all_strings; }
all_sq_strings_p(void)86     bool all_sq_strings_p (void) const { return m_all_sq_strings; }
all_dq_strings_p(void)87     bool all_dq_strings_p (void) const { return m_all_dq_strings; }
some_strings_p(void)88     bool some_strings_p (void) const { return m_some_strings; }
all_real_p(void)89     bool all_real_p (void) const { return m_all_real; }
all_complex_p(void)90     bool all_complex_p (void) const { return m_all_complex; }
all_empty_p(void)91     bool all_empty_p (void) const { return m_all_empty; }
any_cell_p(void)92     bool any_cell_p (void) const { return m_any_cell; }
any_sparse_p(void)93     bool any_sparse_p (void) const { return m_any_sparse; }
any_class_p(void)94     bool any_class_p (void) const { return m_any_class; }
all_1x1_p(void)95     bool all_1x1_p (void) const { return m_all_1x1; }
first_elem_struct_p(void)96     bool first_elem_struct_p (void) const { return m_first_elem_is_struct; }
97 
class_name(void)98     std::string class_name (void) const { return m_class_name; }
99 
100   protected:
101 
102     // Size of this row or matrix after evaluation.
103     dim_vector m_dv;
104 
105     // Are all elements character strings?
106     bool m_all_strings;
107 
108     // Are all elements double-quoted character strings?
109     bool m_all_sq_strings;
110 
111     // Are all elements single-quoted character strings?
112     bool m_all_dq_strings;
113 
114     // Are any elements character strings?
115     bool m_some_strings;
116 
117     // Are all elements real valued?
118     bool m_all_real;
119 
120     // Are all elements complex valued?
121     bool m_all_complex;
122 
123     // Are all elements empty?
124     bool m_all_empty;
125 
126     // Are any elements cells?
127     bool m_any_cell;
128 
129     // Are any elements sparse arrays?
130     bool m_any_sparse;
131 
132     // Are any elements sparse class objects?
133     bool m_any_class;
134 
135     // Do all elements have dimensions 1x1?
136     bool m_all_1x1;
137 
138     // Is the first element a struct?
139     bool m_first_elem_is_struct;
140 
141     // Class name of result.
142     std::string m_class_name;
143   };
144 
145   class tm_row_const : public tm_info
146   {
147   public:
148 
149     typedef std::list<octave_value>::iterator iterator;
150     typedef std::list<octave_value>::const_iterator const_iterator;
151 
152     tm_row_const (void) = delete;
153 
tm_row_const(const tree_argument_list & row,tree_evaluator & tw)154     tm_row_const (const tree_argument_list& row, tree_evaluator& tw)
155       : tm_info (row.empty ()), m_values ()
156     {
157       init (row, tw);
158     }
159 
160     tm_row_const (const tm_row_const&) = default;
161 
162     tm_row_const& operator = (const tm_row_const&) = delete;
163 
164     ~tm_row_const (void) = default;
165 
begin(void)166     iterator begin (void) { return m_values.begin (); }
begin(void)167     const_iterator begin (void) const { return m_values.begin (); }
168 
end(void)169     iterator end (void) { return m_values.end (); }
end(void)170     const_iterator end (void) const { return m_values.end (); }
171 
empty(void)172     bool empty (void) const { return m_values.empty (); }
173 
length(void)174     std::size_t length (void) const { return m_values.size (); }
175 
176     void cellify (void);
177 
178   private:
179 
180     std::list<octave_value> m_values;
181 
182     void init_element (const octave_value&, bool&);
183 
184     void init (const tree_argument_list&, tree_evaluator& tw);
185   };
186 
187   class tm_const : public tm_info
188   {
189   public:
190 
191     typedef std::list<tm_row_const>::iterator iterator;
192     typedef std::list<tm_row_const>::const_iterator const_iterator;
193 
194     tm_const (void) = delete;
195 
tm_const(const tree_matrix & tm,tree_evaluator & tw)196     tm_const (const tree_matrix& tm, tree_evaluator& tw)
197       : tm_info (tm.empty ()), m_evaluator (tw), m_tm_rows ()
198     {
199       init (tm);
200     }
201 
202     // No copying!
203 
204     tm_const (const tm_const&) = delete;
205 
206     tm_const& operator = (const tm_const&) = delete;
207 
208     ~tm_const (void) = default;
209 
210     octave_value concat (char string_fill_char) const;
211 
212   private:
213 
214     tree_evaluator& m_evaluator;
215 
216     // The list of lists of octave_value objects that contain the
217     // values of elements in each row of the tree_matrix object we are
218     // evaluating.
219 
220     std::list<tm_row_const> m_tm_rows;
221 
222     void init (const tree_matrix& tm);
223 
224     octave_value char_array_concat (char string_fill_char) const;
225 
226     octave_value class_concat (void) const;
227 
228     octave_value generic_concat (void) const;
229 
230     template <typename TYPE>
231     void array_concat_internal (TYPE& result) const;
232 
233     template <typename TYPE>
234     TYPE array_concat (void) const;
235 
236     template <typename TYPE>
237     TYPE sparse_array_concat (void) const;
238 
239     template <typename MAP>
240     octave_map map_concat (void) const;
241   };
242 }
243 
244 #endif
245