GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
ov-base-mat.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2018 John W. Eaton
4 Copyright (C) 2009-2010 VZLU Prague
5 
6 This file is part of Octave.
7 
8 Octave is free software: you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <https://www.gnu.org/licenses/>.
21 
22 */
23 
24 // This file should not include config.h. It is only included in other
25 // C++ source files that should have included config.h before including
26 // this file.
27 
28 #include <iostream>
29 
30 #include "Array-util.h"
31 
32 #include "Cell.h"
33 #include "errwarn.h"
34 #include "ovl.h"
35 #include "oct-map.h"
36 #include "ov-base.h"
37 #include "ov-base-mat.h"
38 #include "ov-base-scalar.h"
39 #include "pr-output.h"
40 
41 template <typename MT>
44  const std::list<octave_value_list>& idx)
45 {
47 
48  switch (type[0])
49  {
50  case '(':
51  retval = do_index_op (idx.front ());
52  break;
53 
54  case '{':
55  case '.':
56  {
57  std::string nm = type_name ();
58  error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
59  }
60  break;
61 
62  default:
64  }
65 
66  return retval.next_subsref (type, idx);
67 }
68 
69 template <typename MT>
72  const std::list<octave_value_list>& idx,
73  const octave_value& rhs)
74 {
76 
77  switch (type[0])
78  {
79  case '(':
80  {
81  if (type.length () == 1)
82  retval = numeric_assign (type, idx, rhs);
83  else if (isempty ())
84  {
85  // Allow conversion of empty matrix to some other type in
86  // cases like
87  //
88  // x = []; x(i).f = rhs
89 
90  if (type[1] != '.')
91  error ("invalid assignment expression");
92 
94 
95  retval = tmp.subsasgn (type, idx, rhs);
96  }
97  else
98  {
99  std::string nm = type_name ();
100  error ("in indexed assignment of %s, last lhs index must be ()",
101  nm.c_str ());
102  }
103  }
104  break;
105 
106  case '{':
107  case '.':
108  {
109  if (! isempty ())
110  {
111  std::string nm = type_name ();
112  error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
113  }
114 
116 
117  retval = tmp.subsasgn (type, idx, rhs);
118  }
119  break;
120 
121  default:
122  panic_impossible ();
123  }
124 
125  return retval;
126 }
127 
128 template <typename MT>
131  bool resize_ok)
132 {
134 
135  octave_idx_type n_idx = idx.length ();
136 
137  int nd = matrix.ndims ();
138  const MT& cmatrix = matrix;
139 
140  // If we catch an indexing error in index_vector, we flag an error in
141  // index k. Ensure it is the right value befor each idx_vector call.
142  // Same variable as used in the for loop in the default case.
143 
144  octave_idx_type k = 0;
145 
146  try
147  {
148  switch (n_idx)
149  {
150  case 0:
151  retval = matrix;
152  break;
153 
154  case 1:
155  {
156  idx_vector i = idx (0).index_vector ();
157 
158  // optimize single scalar index.
159  if (! resize_ok && i.is_scalar ())
160  retval = cmatrix.checkelem (i(0));
161  else
162  retval = MT (matrix.index (i, resize_ok));
163  }
164  break;
165 
166  case 2:
167  {
168  idx_vector i = idx (0).index_vector ();
169 
170  k=1;
171  idx_vector j = idx (1).index_vector ();
172 
173  // optimize two scalar indices.
174  if (! resize_ok && i.is_scalar () && j.is_scalar ())
175  retval = cmatrix.checkelem (i(0), j(0));
176  else
177  retval = MT (matrix.index (i, j, resize_ok));
178  }
179  break;
180 
181  default:
182  {
183  Array<idx_vector> idx_vec (dim_vector (n_idx, 1));
184  bool scalar_opt = n_idx == nd && ! resize_ok;
185  const dim_vector dv = matrix.dims ();
186 
187  for (k = 0; k < n_idx; k++)
188  {
189  idx_vec(k) = idx(k).index_vector ();
190 
191  scalar_opt = (scalar_opt && idx_vec(k).is_scalar ());
192  }
193 
194  if (scalar_opt)
195  retval = cmatrix.checkelem (conv_to_int_array (idx_vec));
196  else
197  retval = MT (matrix.index (idx_vec, resize_ok));
198  }
199  break;
200  }
201  }
202  catch (octave::index_exception& e)
203  {
204  // Rethrow to allow more info to be reported later.
205  e.set_pos_if_unset (n_idx, k+1);
206  throw;
207  }
208 
209  return retval;
210 }
211 
212 template <typename MT>
213 void
215 {
216  octave_idx_type n_idx = idx.length ();
217 
218  // If we catch an indexing error in index_vector, we flag an error in
219  // index k. Ensure it is the right value befor each idx_vector call.
220  // Same variable as used in the for loop in the default case.
221 
222  octave_idx_type k = 0;
223 
224  try
225  {
226  switch (n_idx)
227  {
228  case 0:
229  panic_impossible ();
230  break;
231 
232  case 1:
233  {
234  idx_vector i = idx (0).index_vector ();
235 
236  matrix.assign (i, rhs);
237  }
238  break;
239 
240  case 2:
241  {
242  idx_vector i = idx (0).index_vector ();
243 
244  k = 1;
245  idx_vector j = idx (1).index_vector ();
246 
247  matrix.assign (i, j, rhs);
248  }
249  break;
250 
251  default:
252  {
253  Array<idx_vector> idx_vec (dim_vector (n_idx, 1));
254 
255  for (k = 0; k < n_idx; k++)
256  idx_vec(k) = idx(k).index_vector ();
257 
258  matrix.assign (idx_vec, rhs);
259  }
260  break;
261  }
262  }
263  catch (const octave::index_exception& e)
264  {
265  octave::err_invalid_index (e.idx (), n_idx, k+1);
266  }
267 
268  // Clear cache.
269  clear_cached_info ();
270 }
271 
272 template <typename MT>
275 {
276  delete typ;
277  typ = new MatrixType (_typ);
278  return *typ;
279 }
280 
281 template <typename MT>
282 void
284  typename MT::element_type rhs)
285 {
286  octave_idx_type n_idx = idx.length ();
287 
288  int nd = matrix.ndims ();
289 
290  MT mrhs (dim_vector (1, 1), rhs);
291 
292  // If we catch an indexing error in index_vector, we flag an error in
293  // index k. Ensure it is the right value befor each idx_vector call.
294  // Same variable as used in the for loop in the default case.
295 
296  octave_idx_type k = 0;
297 
298  try
299  {
300  switch (n_idx)
301  {
302  case 0:
303  panic_impossible ();
304  break;
305 
306  case 1:
307  {
308  idx_vector i = idx (0).index_vector ();
309 
310  // optimize single scalar index.
311  if (i.is_scalar () && i(0) < matrix.numel ())
312  matrix(i(0)) = rhs;
313  else
314  matrix.assign (i, mrhs);
315  }
316  break;
317 
318  case 2:
319  {
320  idx_vector i = idx (0).index_vector ();
321 
322  k = 1;
323  idx_vector j = idx (1).index_vector ();
324 
325  // optimize two scalar indices.
326  if (i.is_scalar () && j.is_scalar () && nd == 2
327  && i(0) < matrix.rows () && j(0) < matrix.columns ())
328  matrix(i(0), j(0)) = rhs;
329  else
330  matrix.assign (i, j, mrhs);
331  }
332  break;
333 
334  default:
335  {
336  Array<idx_vector> idx_vec (dim_vector (n_idx, 1));
337  bool scalar_opt = n_idx == nd;
338  const dim_vector dv = matrix.dims ().redim (n_idx);
339 
340  for (k = 0; k < n_idx; k++)
341  {
342  idx_vec(k) = idx(k).index_vector ();
343 
344  scalar_opt = (scalar_opt && idx_vec(k).is_scalar ()
345  && idx_vec(k)(0) < dv(k));
346  }
347 
348  if (scalar_opt)
349  {
350  // optimize all scalar indices. Don't construct
351  // an index array, but rather calc a scalar index directly.
352  octave_idx_type n = 1;
353  octave_idx_type j = 0;
354  for (octave_idx_type i = 0; i < n_idx; i++)
355  {
356  j += idx_vec(i)(0) * n;
357  n *= dv (i);
358  }
359  matrix(j) = rhs;
360  }
361  else
362  matrix.assign (idx_vec, mrhs);
363  }
364  break;
365  }
366  }
367  catch (const octave::index_exception& e)
368  {
369  octave::err_invalid_index (e.idx (), n_idx, k+1);
370  }
371 
372  // Clear cache.
373  clear_cached_info ();
374 }
375 
376 template <typename MT>
377 void
379 {
380  octave_idx_type len = idx.length ();
381 
383 
384  for (octave_idx_type i = 0; i < len; i++)
385  ra_idx(i) = idx(i).index_vector ();
386 
387  matrix.delete_elements (ra_idx);
388 
389  // Clear cache.
390  clear_cached_info ();
391 }
392 
393 template <typename MT>
396 {
397  MT retval (matrix);
398  if (fill)
399  retval.resize (dv, 0);
400  else
401  retval.resize (dv);
402  return retval;
403 }
404 
405 // Return true if this matrix has all true elements (non-zero, not NA/NaN).
406 template <typename MT>
407 bool
409 {
410  bool retval = false;
411  dim_vector dv = matrix.dims ();
412  int nel = dv.numel ();
413 
414  if (nel > 0)
415  {
416  MT t1 (matrix.reshape (dim_vector (nel, 1)));
417 
418  if (t1.any_element_is_nan ())
420 
421  if (nel > 1)
423 
424  boolNDArray t2 = t1.all ();
425 
426  retval = t2(0);
427  }
428 
429  return retval;
430 }
431 
432 template <typename MT>
433 bool
435 {
436  dim_vector dv = dims ();
437 
438  return (dv.all_ones () || dv.any_zero ());
439 }
440 
441 template <typename MT>
442 void
443 octave_base_matrix<MT>::print (std::ostream& os, bool pr_as_read_syntax)
444 {
445  print_raw (os, pr_as_read_syntax);
446  newline (os);
447 }
448 
449 template <typename MT>
450 void
452  const std::string& prefix) const
453 {
454  matrix.print_info (os, prefix);
455 }
456 
457 template <typename MT>
458 void
460 {
461  if (matrix.isempty ())
462  os << "[]";
463  else if (matrix.ndims () == 2)
464  {
465  // FIXME: should this be configurable?
466  octave_idx_type max_elts = 10;
467  octave_idx_type elts = 0;
468 
469  octave_idx_type nel = matrix.numel ();
470 
471  octave_idx_type nr = matrix.rows ();
472  octave_idx_type nc = matrix.columns ();
473 
474  os << '[';
475 
476  for (octave_idx_type i = 0; i < nr; i++)
477  {
478  for (octave_idx_type j = 0; j < nc; j++)
479  {
480  std::ostringstream buf;
481  octave_print_internal (buf, matrix(j*nr+i));
482  std::string tmp = buf.str ();
483  size_t pos = tmp.find_first_not_of (' ');
484  if (pos != std::string::npos)
485  os << tmp.substr (pos);
486  else if (! tmp.empty ())
487  os << tmp[0];
488 
489  if (++elts >= max_elts)
490  goto done;
491 
492  if (j < nc - 1)
493  os << ", ";
494  }
495 
496  if (i < nr - 1 && elts < max_elts)
497  os << "; ";
498  }
499 
500  done:
501 
502  if (nel <= max_elts)
503  os << ']';
504  }
505  else
506  os << "...";
507 }
508 
509 template <typename MT>
512 {
513  return make_format (matrix);
514 }
515 
516 template <typename MT>
520  octave_idx_type j) const
521 {
522  std::ostringstream buf;
523  octave_print_internal (buf, fmt, matrix(i,j));
524  return buf.str ();
525 }
526 
527 template <typename MT>
530 {
531  if (n < matrix.numel ())
532  return matrix(n);
533  else
534  return octave_value ();
535 }
536 
537 template <typename MT>
538 bool
540  const octave_value& x)
541 {
542  if (n < matrix.numel ())
543  {
544  // Don't use builtin_type () here to avoid an extra VM call.
545  typedef typename MT::element_type ET;
547  if (btyp == btyp_unknown) // Dead branch?
548  return false;
549 
550  // Set up the pointer to the proper place.
551  void *here = reinterpret_cast<void *> (&matrix(n));
552  // Ask x to store there if it can.
553  return x.get_rep ().fast_elem_insert_self (here, btyp);
554  }
555  else
556  return false;
557 }
bool fast_elem_insert(octave_idx_type n, const octave_value &x)
Definition: ov-base-mat.cc:539
const octave_base_value const Array< octave_idx_type > & ra_idx
characters Given a string matrix
Definition: hex2num.cc:155
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov-base-mat.cc:71
bool print_as_scalar(void) const
Definition: ov-base-mat.cc:434
void assign(const octave_value_list &idx, const MT &rhs)
Definition: ov-base-mat.cc:214
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov-base-mat.cc:43
void delete_elements(const octave_value_list &idx)
Definition: ov-base-mat.cc:378
for large enough k
Definition: lu.cc:617
void err_invalid_index(const std::string &idx, octave_idx_type nd, octave_idx_type dim, const std::string &)
void error(const char *fmt,...)
Definition: error.cc:578
boolNDArray all(int dim=-1) const
Definition: boolNDArray.cc:59
octave_value fast_elem_extract(octave_idx_type n) const
Definition: ov-base-mat.cc:529
builtin_type_t
Definition: ov-base.h:71
void err_nan_to_logical_conversion(void)
i e
Definition: data.cc:2591
bool any_zero(void) const
Definition: dim-vector.h:343
octave_value resize(const dim_vector &dv, bool fill=false) const
Definition: ov.h:511
float_display_format get_edit_display_format(void) const
Definition: ov-base-mat.cc:511
done
Definition: syscalls.cc:251
void octave_print_internal(std::ostream &os, const float_display_format &fmt, bool d, bool pr_as_read_syntax)
Definition: pr-output.cc:1780
OCTAVE_EXPORT octave_value_list isdir nd deftypefn *std::string nm
Definition: utils.cc:975
void print(std::ostream &os, bool pr_as_read_syntax=false)
Definition: ov-base-mat.cc:443
std::string edit_display(const float_display_format &fmt, octave_idx_type i, octave_idx_type j) const
Definition: ov-base-mat.cc:518
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov-base-mat.cc:130
double tmp
Definition: data.cc:6252
octave_value retval
Definition: data.cc:6246
#define panic_impossible()
Definition: error.h:40
idx type
Definition: ov.cc:3114
Array< octave_idx_type > conv_to_int_array(const Array< idx_vector > &a)
Definition: Array-util.cc:237
the exceeded dimensions are set to if fewer subscripts than dimensions are the exceeding dimensions are merged into the final requested dimension For consider the following dims
Definition: sub2ind.cc:255
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
octave_value resize(const dim_vector &dv, bool fill=false) const
Definition: ov-base-mat.cc:395
N Dimensional Array with copy-on-write semantics.
Definition: Array.h:125
bool all_ones(void) const
Definition: dim-vector.h:351
bool is_true(void) const
Definition: ov-base-mat.cc:408
float_display_format make_format(const double &d)
Definition: pr-output.cc:591
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:362
MatrixType matrix_type(void) const
Definition: ov-base-mat.h:124
octave_idx_type length(void) const
Definition: ovl.h:96
for i
Definition: data.cc:5264
void warn_array_as_logical(const dim_vector &dv)
Definition: errwarn.cc:282
void short_disp(std::ostream &os) const
Definition: ov-base-mat.cc:459
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
bool is_scalar(void) const
Definition: idx-vector.h:578
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
dim_vector dv
Definition: sub2ind.cc:263
octave_value next_subsref(const std::string &type, const std::list< octave_value_list > &idx, size_t skip=1)
octave::stream os
Definition: file-io.cc:627
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
static octave_value empty_conv(const std::string &type, const octave_value &rhs=octave_value())
Definition: ov.cc:2867
void print_info(std::ostream &os, const std::string &prefix) const
Definition: ov-base-mat.cc:451