GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
pt-tm-const.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2018 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <iostream>
28 
29 #include "oct-locbuf.h"
30 #include "quit.h"
31 
32 #include "data.h"
33 #include "defun.h"
34 #include "error.h"
35 #include "errwarn.h"
36 #include "oct-map.h"
37 #include "ovl.h"
38 #include "pt-arg-list.h"
39 #include "pt-bp.h"
40 #include "pt-eval.h"
41 #include "pt-exp.h"
42 #include "pt-mat.h"
43 #include "pt-tm-const.h"
44 #include "utils.h"
45 #include "ov.h"
46 #include "variables.h"
47 
48 #include "ov-cx-mat.h"
49 #include "ov-flt-cx-mat.h"
50 #include "ov-re-sparse.h"
51 #include "ov-cx-sparse.h"
52 
53 OCTAVE_NORETURN static
54 void
55 eval_error (const char *msg, const dim_vector& x, const dim_vector& y)
56 {
57  error ("%s (%s vs %s)", msg, x.str ().c_str (), y.str ().c_str ());
58 }
59 
60 namespace octave
61 {
62  void
64  bool& first_elem)
65  {
66  std::string this_elt_class_nm = val.isobject () ? "class"
67  : val.class_name ();
68 
69  m_class_nm = get_concat_class (m_class_nm, this_elt_class_nm);
70 
71  dim_vector this_elt_dv = val.dims ();
72 
73  if (! this_elt_dv.zero_by_zero ())
74  {
75  m_all_mt = false;
76 
77  if (first_elem)
78  {
79  if (val.isstruct ())
81 
82  first_elem = false;
83  }
84  }
85  else if (val.iscell ())
86  first_elem = false;
87 
88  append (val);
89 
90  if (m_all_str && ! val.is_string ())
91  m_all_str = false;
92 
93  if (m_all_sq_str && ! val.is_sq_string ())
94  m_all_sq_str = false;
95 
96  if (m_all_dq_str && ! val.is_dq_string ())
97  m_all_dq_str = false;
98 
99  if (! m_some_str && val.is_string ())
100  m_some_str = true;
101 
102  if (m_all_real && ! val.isreal ())
103  m_all_real = false;
104 
105  if (m_all_cmplx && ! (val.iscomplex () || val.isreal ()))
106  m_all_cmplx = false;
107 
108  if (! m_any_cell && val.iscell ())
109  m_any_cell = true;
110 
111  if (! m_any_sparse && val.issparse ())
112  m_any_sparse = true;
113 
114  if (! m_any_class && val.isobject ())
115  m_any_class = true;
116 
117  // Special treatment of sparse matrices to avoid out-of-memory error
118  m_all_1x1 = m_all_1x1 && ! val.issparse () && val.numel () == 1;
119  }
120 
121  void
123  tree_evaluator *tw)
124  {
125  m_all_str = true;
126  m_all_sq_str = true;
127  m_all_dq_str = true;
128  m_all_real = true;
129  m_all_cmplx = true;
130  m_any_cell = false;
131  m_any_sparse = false;
132  m_any_class = false;
133 
134  bool first_elem = true;
135 
136  for (tree_expression* elt : row)
137  {
138  octave_quit ();
139 
140  octave_value tmp = tw->evaluate (elt);
141 
142  if (tmp.is_undefined ())
143  {
144  m_ok = true;
145  return;
146  }
147  else
148  {
149  if (tmp.is_cs_list ())
150  {
151  octave_value_list tlst = tmp.list_value ();
152 
153  for (octave_idx_type i = 0; i < tlst.length (); i++)
154  {
155  octave_quit ();
156 
157  do_init_element (tlst(i), first_elem);
158  }
159  }
160  else
161  do_init_element (tmp, first_elem);
162  }
163  }
164 
165  if (m_any_cell && ! m_any_class && ! m_first_elem_is_struct)
166  cellify ();
167 
168  first_elem = true;
169 
170  for (const octave_value& val : *this)
171  {
172  octave_quit ();
173 
174  dim_vector this_elt_dv = val.dims ();
175 
176  if (! this_elt_dv.zero_by_zero ())
177  {
178  m_all_mt = false;
179 
180  if (first_elem)
181  {
182  first_elem = false;
183  m_dv = this_elt_dv;
184  }
185  else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 1)))
186  eval_error ("horizontal dimensions mismatch", m_dv, this_elt_dv);
187  }
188  }
189 
190  m_ok = true;
191  }
192 
193  void
195  {
196  bool elt_changed = false;
197 
198  for (auto& elt : *this)
199  {
200  octave_quit ();
201 
202  if (! elt.iscell ())
203  {
204  elt_changed = true;
205 
206  if (elt.isempty ())
207  elt = Cell ();
208  else
209  elt = Cell (elt);
210  }
211  }
212 
213  if (elt_changed)
214  {
215  bool first_elem = true;
216 
217  for (const octave_value& val : *this)
218  {
219  octave_quit ();
220 
221  dim_vector this_elt_dv = val.dims ();
222 
223  if (! this_elt_dv.zero_by_zero ())
224  {
225  if (first_elem)
226  {
227  first_elem = false;
228  m_dv = this_elt_dv;
229  }
230  else if (! m_dv.hvcat (this_elt_dv, 1))
231  eval_error ("horizontal dimensions mismatch", m_dv, this_elt_dv);
232  }
233  }
234  }
235  }
236 
237  void
239  {
240  m_all_str = true;
241  m_all_sq_str = true;
242  m_all_dq_str = true;
243  m_all_real = true;
244  m_all_cmplx = true;
245  m_any_cell = false;
246  m_any_sparse = false;
247  m_any_class = false;
248  m_all_1x1 = ! tm.empty ();
249 
250  bool first_elem = true;
251  bool first_elem_is_struct = false;
252 
253  // Just eval and figure out if what we have is complex or all strings.
254  // We can't check columns until we know that this is a numeric matrix --
255  // collections of strings can have elements of different lengths.
256  for (const tree_argument_list* elt : tm)
257  {
258  octave_quit ();
259 
260  tm_row_const tmp (*elt, tw);
261 
262  if (first_elem)
263  {
264  first_elem_is_struct = tmp.first_elem_struct_p ();
265 
266  first_elem = false;
267  }
268 
269  if (tmp && ! tmp.empty ())
270  {
271  if (m_all_str && ! tmp.all_strings_p ())
272  m_all_str = false;
273 
274  if (m_all_sq_str && ! tmp.all_sq_strings_p ())
275  m_all_sq_str = false;
276 
277  if (m_all_dq_str && ! tmp.all_dq_strings_p ())
278  m_all_dq_str = false;
279 
280  if (! m_some_str && tmp.some_strings_p ())
281  m_some_str = true;
282 
283  if (m_all_real && ! tmp.all_real_p ())
284  m_all_real = false;
285 
286  if (m_all_cmplx && ! tmp.all_complex_p ())
287  m_all_cmplx = false;
288 
289  if (m_all_mt && ! tmp.all_empty_p ())
290  m_all_mt = false;
291 
292  if (! m_any_cell && tmp.any_cell_p ())
293  m_any_cell = true;
294 
295  if (! m_any_sparse && tmp.any_sparse_p ())
296  m_any_sparse = true;
297 
298  if (! m_any_class && tmp.any_class_p ())
299  m_any_class = true;
300 
301  m_all_1x1 = m_all_1x1 && tmp.all_1x1_p ();
302 
303  append (tmp);
304  }
305  else
306  break;
307  }
308 
309  if (m_any_cell && ! m_any_class && ! first_elem_is_struct)
310  {
311  for (auto& elt : *this)
312  {
313  octave_quit ();
314 
315  elt.cellify ();
316  }
317  }
318 
319  first_elem = true;
320 
321  for (tm_row_const& elt : *this)
322  {
323  octave_quit ();
324 
325  octave_idx_type this_elt_nr = elt.rows ();
326  octave_idx_type this_elt_nc = elt.cols ();
327 
328  std::string this_elt_class_nm = elt.class_name ();
329  m_class_nm = get_concat_class (m_class_nm, this_elt_class_nm);
330 
331  dim_vector this_elt_dv = elt.dims ();
332 
333  m_all_mt = false;
334 
335  if (first_elem)
336  {
337  first_elem = false;
338 
339  m_dv = this_elt_dv;
340  }
341  else if (m_all_str && m_dv.ndims () == 2
342  && this_elt_dv.ndims () == 2)
343  {
344  // This is Octave's specialty.
345  // Character matrices support rows of unequal length.
346  if (m_dv.any_zero ())
347  {
348  // Empty existing element (bug #52542).
349  // Replace empty element with non-empty one.
350  m_dv = this_elt_dv;
351  }
352  else
353  {
354  if (this_elt_nc > cols ())
355  m_dv(1) = this_elt_nc;
356  m_dv(0) += this_elt_nr;
357  }
358  }
359  else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 0)))
360  eval_error ("vertical dimensions mismatch", m_dv, this_elt_dv);
361  }
362 
363  m_ok = true;
364  }
365 
366  template <>
369  tm_const& tmp)
370  {
372 
373  if (tmp.all_1x1_p ())
374  single_type_concat<octave_scalar_map> (result, dv, tmp);
375  else
376  single_type_concat<octave_map> (result, dv, tmp);
377 
378  return result;
379  }
380 
382  {
384 
386 
387  octave_idx_type j = 0;
388  for (tm_row_const& tmrc : tmc)
389  {
390  octave_quit ();
391 
392  if (tmrc.length () == 1)
393  rows(j++) = *(tmrc.begin ());
394  else
395  {
396  octave_value_list row (tmrc.length (), octave_value ());
397 
398  octave_idx_type i = 0;
399  for (auto& elt : tmrc)
400  row(i++) = elt;
401 
402  rows(j++) = do_class_concat (row, "horzcat", 1);
403  }
404  }
405 
406  if (rows.length () == 1)
407  retval = rows(0);
408  else
409  retval = do_class_concat (rows, "vertcat", 0);
410 
411  return retval;
412  }
413 }
octave_idx_type rows(void)
Definition: pt-tm-const.h:156
Definition: Cell.h:37
static OCTAVE_NORETURN void eval_error(const char *msg, const dim_vector &x, const dim_vector &y)
Definition: pt-tm-const.cc:55
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:4986
bool zero_by_zero(void) const
Definition: dim-vector.h:338
dim_vector dims(void)
Definition: pt-tm-const.h:163
void init(const tree_matrix &tm, tree_evaluator *tw)
Definition: pt-tm-const.cc:238
size_t length(void) const
Definition: base-list.h:50
void error(const char *fmt,...)
Definition: error.cc:578
octave_idx_type cols(void)
Definition: pt-tm-const.h:157
double tmp
Definition: data.cc:6252
octave_value retval
Definition: data.cc:6246
bool append
Definition: load-save.cc:1618
octave_value do_single_type_concat< octave_map >(const dim_vector &dv, tm_const &tmp)
Definition: pt-tm-const.cc:368
With real return the complex result
Definition: data.cc:3260
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
bool empty(void) const
Definition: base-list.h:47
octave_value do_class_concat(tm_const &tmc)
Definition: pt-tm-const.cc:381
void do_init_element(const octave_value &, bool &)
Definition: pt-tm-const.cc:63
void init(const tree_argument_list &, tree_evaluator *tw)
Definition: pt-tm-const.cc:122
octave_idx_type length(void) const
Definition: ovl.h:96
the element is set to zero In other the statement xample y
Definition: data.cc:5264
octave_value evaluate(tree_expression *expr, int nargout=1)
Definition: pt-eval.h:294
for i
Definition: data.cc:5264
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:295
void append(const octave_value &s)
Definition: base-list.h:110
std::string get_concat_class(const std::string &c1, const std::string &c2)
Definition: pt-mat.cc:44
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
std::string class_name(void) const
Definition: pt-tm-const.h:178
dim_vector dv
Definition: sub2ind.cc:263
where the brackets indicate optional arguments and and character or cell array For character arrays the conversion is repeated for every row
Definition: str2double.cc:342
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE * x