GNU Octave  4.0.0
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-2015 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 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <iostream>
29 
30 #include "Array-util.h"
31 
32 #include "Cell.h"
33 #include "oct-obj.h"
34 #include "oct-map.h"
35 #include "ov-base.h"
36 #include "ov-base-mat.h"
37 #include "ov-base-scalar.h"
38 #include "pr-output.h"
39 
40 template <class MT>
43  const std::list<octave_value_list>& idx)
44 {
45  octave_value retval;
46 
47  switch (type[0])
48  {
49  case '(':
50  retval = do_index_op (idx.front ());
51  break;
52 
53  case '{':
54  case '.':
55  {
56  std::string nm = type_name ();
57  error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
58  }
59  break;
60 
61  default:
63  }
64 
65  return retval.next_subsref (type, idx);
66 }
67 
68 template <class MT>
71  const std::list<octave_value_list>& idx,
72  const octave_value& rhs)
73 {
74  octave_value retval;
75 
76  switch (type[0])
77  {
78  case '(':
79  {
80  if (type.length () == 1)
81  retval = numeric_assign (type, idx, rhs);
82  else if (is_empty ())
83  {
84  // Allow conversion of empty matrix to some other type in
85  // cases like
86  //
87  // x = []; x(i).f = rhs
88 
89  if (type[1] == '.')
90  {
91  octave_value tmp = octave_value::empty_conv (type, rhs);
92 
93  retval = tmp.subsasgn (type, idx, rhs);
94  }
95  else
96  error ("invalid assignment expression");
97  }
98  else
99  {
100  std::string nm = type_name ();
101  error ("in indexed assignment of %s, last lhs index must be ()",
102  nm.c_str ());
103  }
104  }
105  break;
106 
107  case '{':
108  case '.':
109  {
110  if (is_empty ())
111  {
112  octave_value tmp = octave_value::empty_conv (type, rhs);
113 
114  retval = tmp.subsasgn (type, idx, rhs);
115  }
116  else
117  {
118  std::string nm = type_name ();
119  error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
120  }
121  }
122  break;
123 
124  default:
125  panic_impossible ();
126  }
127 
128  return retval;
129 }
130 
131 template <class MT>
134  bool resize_ok)
135 {
136  octave_value retval;
137 
138  octave_idx_type n_idx = idx.length ();
139 
140  int nd = matrix.ndims ();
141  const MT& cmatrix = matrix;
142 
143  switch (n_idx)
144  {
145  case 0:
146  retval = matrix;
147  break;
148 
149  case 1:
150  {
151  idx_vector i = idx (0).index_vector ();
152 
153  if (! error_state)
154  {
155  // optimize single scalar index.
156  if (! resize_ok && i.is_scalar ())
157  retval = cmatrix.checkelem (i(0));
158  else
159  retval = MT (matrix.index (i, resize_ok));
160  }
161  }
162  break;
163 
164  case 2:
165  {
166  idx_vector i = idx (0).index_vector ();
167 
168  if (! error_state)
169  {
170  idx_vector j = idx (1).index_vector ();
171 
172  if (! error_state)
173  {
174  // optimize two scalar indices.
175  if (! resize_ok && i.is_scalar () && j.is_scalar ())
176  retval = cmatrix.checkelem (i(0), j(0));
177  else
178  retval = MT (matrix.index (i, j, resize_ok));
179  }
180  }
181  }
182  break;
183 
184  default:
185  {
186  Array<idx_vector> idx_vec (dim_vector (n_idx, 1));
187  bool scalar_opt = n_idx == nd && ! resize_ok;
188  const dim_vector dv = matrix.dims ();
189 
190  for (octave_idx_type i = 0; i < n_idx; i++)
191  {
192  idx_vec(i) = idx(i).index_vector ();
193 
194  if (error_state)
195  break;
196 
197  scalar_opt = (scalar_opt && idx_vec(i).is_scalar ());
198  }
199 
200  if (! error_state)
201  {
202  if (scalar_opt)
203  retval = cmatrix.checkelem (conv_to_int_array (idx_vec));
204  else
205  retval = MT (matrix.index (idx_vec, resize_ok));
206  }
207  }
208  break;
209  }
210 
211  return retval;
212 }
213 
214 template <class MT>
215 void
217 {
218  octave_idx_type n_idx = idx.length ();
219 
220  switch (n_idx)
221  {
222  case 0:
223  panic_impossible ();
224  break;
225 
226  case 1:
227  {
228  idx_vector i = idx (0).index_vector ();
229 
230  if (! error_state)
231  matrix.assign (i, rhs);
232  }
233  break;
234 
235  case 2:
236  {
237  idx_vector i = idx (0).index_vector ();
238 
239  if (! error_state)
240  {
241  idx_vector j = idx (1).index_vector ();
242 
243  if (! error_state)
244  matrix.assign (i, j, rhs);
245  }
246  }
247  break;
248 
249  default:
250  {
251  Array<idx_vector> idx_vec (dim_vector (n_idx, 1));
252 
253  for (octave_idx_type i = 0; i < n_idx; i++)
254  {
255  idx_vec(i) = idx(i).index_vector ();
256 
257  if (error_state)
258  break;
259  }
260 
261  if (! error_state)
262  matrix.assign (idx_vec, rhs);
263  }
264  break;
265  }
266 
267  // Clear cache.
268  clear_cached_info ();
269 }
270 
271 template <class MT>
274 {
275  delete typ;
276  typ = new MatrixType (_typ);
277  return *typ;
278 }
279 
280 template <class MT>
281 void
283  typename MT::element_type rhs)
284 {
285  octave_idx_type n_idx = idx.length ();
286 
287  int nd = matrix.ndims ();
288 
289  MT mrhs (dim_vector (1, 1), rhs);
290 
291  switch (n_idx)
292  {
293  case 0:
294  panic_impossible ();
295  break;
296 
297  case 1:
298  {
299  idx_vector i = idx (0).index_vector ();
300 
301  if (! error_state)
302  {
303  // optimize single scalar index.
304  if (i.is_scalar () && i(0) < matrix.numel ())
305  matrix(i(0)) = rhs;
306  else
307  matrix.assign (i, mrhs);
308  }
309  }
310  break;
311 
312  case 2:
313  {
314  idx_vector i = idx (0).index_vector ();
315 
316  if (! error_state)
317  {
318  idx_vector j = idx (1).index_vector ();
319 
320  if (! error_state)
321  {
322  // optimize two scalar indices.
323  if (i.is_scalar () && j.is_scalar () && nd == 2
324  && i(0) < matrix.rows () && j(0) < matrix.columns ())
325  matrix(i(0), j(0)) = rhs;
326  else
327  matrix.assign (i, j, mrhs);
328  }
329  }
330  }
331  break;
332 
333  default:
334  {
335  Array<idx_vector> idx_vec (dim_vector (n_idx, 1));
336  bool scalar_opt = n_idx == nd;
337  const dim_vector dv = matrix.dims ().redim (n_idx);
338 
339  for (octave_idx_type i = 0; i < n_idx; i++)
340  {
341  idx_vec(i) = idx(i).index_vector ();
342 
343  if (error_state)
344  break;
345 
346  scalar_opt = (scalar_opt && idx_vec(i).is_scalar ()
347  && idx_vec(i)(0) < dv(i));
348  }
349 
350  if (! error_state)
351  {
352  if (scalar_opt)
353  {
354  // optimize all scalar indices. Don't construct an index array,
355  // but rather calc a scalar index directly.
356  octave_idx_type k = 1;
357  octave_idx_type j = 0;
358  for (octave_idx_type i = 0; i < n_idx; i++)
359  {
360  j += idx_vec(i)(0) * k;
361  k *= dv (i);
362  }
363  matrix(j) = rhs;
364  }
365  else
366  matrix.assign (idx_vec, mrhs);
367  }
368  }
369  break;
370  }
371 
372  // Clear cache.
373  clear_cached_info ();
374 }
375 
376 template <class 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 <class MT>
395 octave_base_matrix<MT>::resize (const dim_vector& dv, bool fill) const
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 template <class MT>
406 bool
408 {
409  bool retval = false;
410  dim_vector dv = matrix.dims ();
411  int nel = dv.numel ();
412 
413  if (nel > 0)
414  {
415  MT t1 (matrix.reshape (dim_vector (nel, 1)));
416 
417  if (t1.any_element_is_nan ())
419  else
420  {
421  boolNDArray t2 = t1.all ();
422 
423  retval = t2(0);
424  }
425  }
426 
427  return retval;
428 }
429 
430 template <class MT>
431 bool
433 {
434  dim_vector dv = dims ();
435 
436  return (dv.all_ones () || dv.any_zero ());
437 }
438 
439 template <class MT>
440 void
441 octave_base_matrix<MT>::print (std::ostream& os, bool pr_as_read_syntax)
442 {
443  print_raw (os, pr_as_read_syntax);
444  newline (os);
445 }
446 
447 template <class MT>
448 void
450  const std::string& prefix) const
451 {
452  matrix.print_info (os, prefix);
453 }
454 
455 template <class MT>
456 void
457 octave_base_matrix<MT>::short_disp (std::ostream& os) const
458 {
459  if (matrix.is_empty ())
460  os << "[]";
461  else if (matrix.ndims () == 2)
462  {
463  // FIXME: should this be configurable?
464  octave_idx_type max_elts = 10;
465  octave_idx_type elts = 0;
466 
467  octave_idx_type nel = matrix.numel ();
468 
469  octave_idx_type nr = matrix.rows ();
470  octave_idx_type nc = matrix.columns ();
471 
472  os << "[";
473 
474  for (octave_idx_type i = 0; i < nr; i++)
475  {
476  for (octave_idx_type j = 0; j < nc; j++)
477  {
478  std::ostringstream buf;
479  octave_print_internal (buf, matrix(j*nr+i));
480  std::string tmp = buf.str ();
481  size_t pos = tmp.find_first_not_of (" ");
482  if (pos != std::string::npos)
483  os << tmp.substr (pos);
484  else if (! tmp.empty ())
485  os << tmp[0];
486 
487  if (++elts >= max_elts)
488  goto done;
489 
490  if (j < nc - 1)
491  os << ", ";
492  }
493 
494  if (i < nr - 1 && elts < max_elts)
495  os << "; ";
496  }
497 
498  done:
499 
500  if (nel <= max_elts)
501  os << "]";
502  }
503  else
504  os << "...";
505 }
506 
507 template <class MT>
510 {
511  if (n < matrix.numel ())
512  return matrix(n);
513  else
514  return octave_value ();
515 }
516 
517 template <class MT>
518 bool
520  const octave_value& x)
521 {
522  if (n < matrix.numel ())
523  {
524  // Don't use builtin_type () here to avoid an extra VM call.
525  typedef typename MT::element_type ET;
527  if (btyp == btyp_unknown) // Dead branch?
528  return false;
529 
530  // Set up the pointer to the proper place.
531  void *here = reinterpret_cast<void *> (&matrix(n));
532  // Ask x to store there if it can.
533  return x.get_rep ().fast_elem_insert_self (here, btyp);
534  }
535  else
536  return false;
537 }
boolNDArray all(int dim=-1) const
Definition: boolNDArray.cc:61
void short_disp(std::ostream &os) const
Definition: ov-base-mat.cc:457
bool fast_elem_insert(octave_idx_type n, const octave_value &x)
Definition: ov-base-mat.cc:519
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:70
void assign(const octave_value_list &idx, const MT &rhs)
Definition: ov-base-mat.cc:216
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov-base-mat.cc:42
octave_idx_type length(void) const
Definition: oct-obj.h:89
void delete_elements(const octave_value_list &idx)
Definition: ov-base-mat.cc:378
void error(const char *fmt,...)
Definition: error.cc:476
bool all_ones(void) const
Definition: dim-vector.h:349
virtual bool fast_elem_insert_self(void *where, builtin_type_t btyp) const
Definition: ov-base.cc:1530
builtin_type_t
Definition: ov-base.h:59
MatrixType matrix_type(void) const
Definition: ov-base-mat.h:120
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:361
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov.cc:1414
void print(std::ostream &os, bool pr_as_read_syntax=false)
Definition: ov-base-mat.cc:441
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov-base-mat.cc:133
void gripe_nan_to_logical_conversion(void)
int error_state
Definition: error.cc:101
octave_value resize(const dim_vector &dv, bool fill=false) const
Definition: ov-base-mat.cc:395
#define panic_impossible()
Definition: error.h:33
dim_vector redim(int n) const
Definition: dim-vector.cc:266
Array< octave_idx_type > conv_to_int_array(const Array< idx_vector > &a)
Definition: Array-util.cc:234
bool any_zero(void) const
Definition: dim-vector.h:331
Handles the reference counting for all the derived classes.
Definition: Array.h:45
const octave_base_value & get_rep(void) const
Definition: ov.h:1085
void octave_print_internal(std::ostream &, char, bool)
Definition: pr-output.cc:1715
bool is_scalar(void) const
Definition: idx-vector.h:578
bool is_true(void) const
Definition: ov-base-mat.cc:407
bool print_as_scalar(void) const
Definition: ov-base-mat.cc:432
octave_value fast_elem_extract(octave_idx_type n) const
Definition: ov-base-mat.cc:509
octave_value next_subsref(const std::string &type, const std::list< octave_value_list > &idx, size_t skip=1)
Definition: ov.cc:1317
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:2829
F77_RET_T const double * x
void print_info(std::ostream &os, const std::string &prefix) const
Definition: ov-base-mat.cc:449