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