GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ov-base-mat.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2017 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 the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 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 <http://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 (is_empty ())
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 (! is_empty ())
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
459 octave_base_matrix<MT>::short_disp (std::ostream& os) const
460 {
461  if (matrix.is_empty ())
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  if (n < matrix.numel ())
514  return matrix(n);
515  else
516  return octave_value ();
517 }
518 
519 template <typename MT>
520 bool
522  const octave_value& x)
523 {
524  if (n < matrix.numel ())
525  {
526  // Don't use builtin_type () here to avoid an extra VM call.
527  typedef typename MT::element_type ET;
529  if (btyp == btyp_unknown) // Dead branch?
530  return false;
531 
532  // Set up the pointer to the proper place.
533  void *here = reinterpret_cast<void *> (&matrix(n));
534  // Ask x to store there if it can.
535  return x.get_rep ().fast_elem_insert_self (here, btyp);
536  }
537  else
538  return false;
539 }
boolNDArray all(int dim=-1) const
Definition: boolNDArray.cc:60
void short_disp(std::ostream &os) const
Definition: ov-base-mat.cc:459
bool fast_elem_insert(octave_idx_type n, const octave_value &x)
Definition: ov-base-mat.cc:521
const octave_base_value const Array< octave_idx_type > & ra_idx
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov-base-mat.cc:71
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 set_pos_if_unset(octave_idx_type nd_arg, octave_idx_type dim_arg)
octave_idx_type length(void) const
Definition: ovl.h:96
void delete_elements(const octave_value_list &idx)
Definition: ov-base-mat.cc:378
for large enough k
Definition: lu.cc:606
the sparsity preserving column transformation such that that defines the pivoting threshold can be given in which case it defines the then the first element defines the pivoting tolerance for the unsymmetric the values defined such that for full matrix
Definition: lu.cc:138
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:570
std::string idx(void) const
bool all_ones(void) const
Definition: dim-vector.h:377
virtual bool fast_elem_insert_self(void *where, builtin_type_t btyp) const
Definition: ov-base.cc:1410
builtin_type_t
Definition: ov-base.h:61
void err_nan_to_logical_conversion(void)
i e
Definition: data.cc:2724
MatrixType matrix_type(void) const
Definition: ov-base-mat.h:129
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:389
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov.cc:1540
done
Definition: syscalls.cc:248
OCTAVE_EXPORT octave_value_list isdir nd deftypefn *std::string nm
Definition: utils.cc:941
void print(std::ostream &os, bool pr_as_read_syntax=false)
Definition: ov-base-mat.cc:443
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov-base-mat.cc:130
octave_value resize(const dim_vector &dv, bool fill=false) const
Definition: ov-base-mat.cc:395
double tmp
Definition: data.cc:6300
octave_value retval
Definition: data.cc:6294
#define panic_impossible()
Definition: error.h:40
idx type
Definition: ov.cc:3129
Array< octave_idx_type > conv_to_int_array(const Array< idx_vector > &a)
Definition: Array-util.cc:238
bool any_zero(void) const
Definition: dim-vector.h:359
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
N Dimensional Array with copy-on-write semantics.
Definition: Array.h:126
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
const octave_base_value & get_rep(void) const
Definition: ov.h:1270
void octave_print_internal(std::ostream &, char, bool)
Definition: pr-output.cc:1722
bool is_scalar(void) const
Definition: idx-vector.h:568
bool is_true(void) const
Definition: ov-base-mat.cc:408
bool print_as_scalar(void) const
Definition: ov-base-mat.cc:434
octave_value fast_elem_extract(octave_idx_type n) const
Definition: ov-base-mat.cc:511
void warn_array_as_logical(const dim_vector &dv)
Definition: errwarn.cc:276
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:854
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)
Definition: ov.cc:1462
F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &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 F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T F77_REAL F77_REAL &F77_RET_T F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE * x
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))
static octave_value empty_conv(const std::string &type, const octave_value &rhs=octave_value())
Definition: ov.cc:2882
void print_info(std::ostream &os, const std::string &prefix) const
Definition: ov-base-mat.cc:451