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-diag.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2008-2013 Jaroslav Hajek
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 the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 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 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <iostream>
28 
29 #include "mach-info.h"
30 #include "lo-ieee.h"
31 
32 #include "mxarray.h"
33 #include "ov-base.h"
34 #include "ov-base-mat.h"
35 #include "pr-output.h"
36 #include "error.h"
37 #include "gripes.h"
38 #include "oct-stream.h"
39 #include "ops.h"
40 
41 #include "ls-oct-ascii.h"
42 
43 template <class DMT, class MT>
46  const std::list<octave_value_list>& idx)
47 {
48  octave_value retval;
49 
50  switch (type[0])
51  {
52  case '(':
53  retval = do_index_op (idx.front ());
54  break;
55 
56  case '{':
57  case '.':
58  {
59  std::string nm = type_name ();
60  error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
61  }
62  break;
63 
64  default:
66  }
67 
68  return retval.next_subsref (type, idx);
69 }
70 
71 
72 template <class DMT, class MT>
75 {
76  octave_value retval;
77  if (matrix.rows () == 1 || matrix.cols () == 1)
78  {
79  // Rather odd special case. This is a row or column vector
80  // represented as a diagonal matrix with a single nonzero entry, but
81  // Fdiag semantics are to product a diagonal matrix for vector
82  // inputs.
83  if (k == 0)
84  // Returns Diag2Array<T> with nnz <= 1.
85  retval = matrix.build_diag_matrix ();
86  else
87  // Returns Array<T> matrix
88  retval = matrix.array_value ().diag (k);
89  }
90  else
91  // Returns Array<T> vector
92  retval = matrix.extract_diag (k);
93  return retval;
94 }
95 
96 
97 template <class DMT, class MT>
100  bool resize_ok)
101 {
102  octave_value retval;
103  typedef typename DMT::element_type el_type;
104 
105  if (idx.length () == 2 && ! resize_ok)
106  {
107  idx_vector idx0 = idx(0).index_vector ();
108  idx_vector idx1 = idx(1).index_vector ();
109 
110  if (idx0.is_scalar () && idx1.is_scalar ())
111  {
112  retval = matrix.checkelem (idx0(0), idx1(0));
113  }
114  else
115  {
116  octave_idx_type m = idx0.length (matrix.rows ());
117  octave_idx_type n = idx1.length (matrix.columns ());
118  if (idx0.is_colon_equiv (m) && idx1.is_colon_equiv (n)
119  && m <= matrix.rows () && n <= matrix.rows ())
120  {
121  DMT rm (matrix);
122  rm.resize (m, n);
123  retval = rm;
124  }
125  else
126  retval = to_dense ().do_index_op (idx, resize_ok);
127  }
128  }
129  else
130  retval = to_dense ().do_index_op (idx, resize_ok);
131 
132  return retval;
133 }
134 
135 template <class DMT, class MT>
138  const std::list<octave_value_list>& idx,
139  const octave_value& rhs)
140 {
141  octave_value retval;
142 
143  switch (type[0])
144  {
145  case '(':
146  {
147  if (type.length () == 1)
148  {
149  octave_value_list jdx = idx.front ();
150  // Check for a simple element assignment. That means, if D is a
151  // diagonal matrix, 'D(i,i) = x' will not destroy its diagonality
152  // (provided i is a valid index).
153  if (jdx.length () == 2
154  && jdx(0).is_scalar_type () && jdx(1).is_scalar_type ())
155  {
156  typename DMT::element_type val;
157  idx_vector i0 = jdx(0).index_vector ();
158  idx_vector i1 = jdx(1).index_vector ();
159  if (! error_state && i0(0) == i1(0)
160  && i0(0) < matrix.rows () && i1(0) < matrix.cols ()
161  && chk_valid_scalar (rhs, val))
162  {
163  matrix.dgelem (i0(0)) = val;
164  retval = this;
165  this->count++;
166  // invalidate cache
167  dense_cache = octave_value ();
168  }
169  }
170 
171  if (! error_state && ! retval.is_defined ())
172  retval = numeric_assign (type, idx, rhs);
173  }
174  else
175  {
176  std::string nm = type_name ();
177  error ("in indexed assignment of %s, last lhs index must be ()",
178  nm.c_str ());
179  }
180  }
181  break;
182 
183  case '{':
184  case '.':
185  {
186  if (is_empty ())
187  {
188  octave_value tmp = octave_value::empty_conv (type, rhs);
189 
190  retval = tmp.subsasgn (type, idx, rhs);
191  }
192  else
193  {
194  std::string nm = type_name ();
195  error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
196  }
197  }
198  break;
199 
200  default:
201  panic_impossible ();
202  }
203 
204  return retval;
205 }
206 
207 template <class DMT, class MT>
209 octave_base_diag<DMT, MT>::resize (const dim_vector& dv, bool fill) const
210 {
211  octave_value retval;
212  if (dv.length () == 2)
213  {
214  DMT rm (matrix);
215  rm.resize (dv(0), dv(1));
216  retval = rm;
217  }
218  else
219  retval = to_dense ().resize (dv, fill);
220  return retval;
221 }
222 
223 template <class DMT, class MT>
224 bool
226 {
227  return to_dense ().is_true ();
228 }
229 
230 // FIXME: This should be achieveable using ::real
231 template <class T> inline T helper_getreal (T x) { return x; }
232 template <class T> inline T helper_getreal (std::complex<T> x)
233 { return x.real (); }
234 // FIXME: We really need some traits so that ad hoc hooks like this
235 // are not necessary.
236 template <class T> inline T helper_iscomplex (T) { return false; }
237 template <class T> inline T helper_iscomplex (std::complex<T>) { return true; }
238 
239 template <class DMT, class MT>
240 double
241 octave_base_diag<DMT, MT>::double_value (bool force_conversion) const
242 {
243  double retval = lo_ieee_nan_value ();
244  typedef typename DMT::element_type el_type;
245 
246  if (helper_iscomplex (el_type ()) && ! force_conversion)
247  gripe_implicit_conversion ("Octave:imag-to-real",
248  "complex matrix", "real scalar");
249 
250  if (numel () > 0)
251  {
252  gripe_implicit_conversion ("Octave:array-to-scalar",
253  type_name (), "real scalar");
254 
255  retval = helper_getreal (el_type (matrix (0, 0)));
256  }
257  else
258  gripe_invalid_conversion (type_name (), "real scalar");
259 
260  return retval;
261 }
262 
263 template <class DMT, class MT>
264 float
265 octave_base_diag<DMT, MT>::float_value (bool force_conversion) const
266 {
267  float retval = lo_ieee_float_nan_value ();
268  typedef typename DMT::element_type el_type;
269 
270  if (helper_iscomplex (el_type ()) && ! force_conversion)
271  gripe_implicit_conversion ("Octave:imag-to-real",
272  "complex matrix", "real scalar");
273 
274  if (numel () > 0)
275  {
276  gripe_implicit_conversion ("Octave:array-to-scalar",
277  type_name (), "real scalar");
278 
279  retval = helper_getreal (el_type (matrix (0, 0)));
280  }
281  else
282  gripe_invalid_conversion (type_name (), "real scalar");
283 
284  return retval;
285 }
286 
287 template <class DMT, class MT>
288 Complex
290 {
291  double tmp = lo_ieee_nan_value ();
292 
293  Complex retval (tmp, tmp);
294 
295  if (rows () > 0 && columns () > 0)
296  {
297  gripe_implicit_conversion ("Octave:array-to-scalar",
298  type_name (), "complex scalar");
299 
300  retval = matrix (0, 0);
301  }
302  else
303  gripe_invalid_conversion (type_name (), "complex scalar");
304 
305  return retval;
306 }
307 
308 template <class DMT, class MT>
311 {
312  float tmp = lo_ieee_float_nan_value ();
313 
314  FloatComplex retval (tmp, tmp);
315 
316  if (rows () > 0 && columns () > 0)
317  {
318  gripe_implicit_conversion ("Octave:array-to-scalar",
319  type_name (), "complex scalar");
320 
321  retval = matrix (0, 0);
322  }
323  else
324  gripe_invalid_conversion (type_name (), "complex scalar");
325 
326  return retval;
327 }
328 
329 template <class DMT, class MT>
330 Matrix
332 {
333  return Matrix (diag_matrix_value ());
334 }
335 
336 template <class DMT, class MT>
339 {
340  return FloatMatrix (float_diag_matrix_value ());
341 }
342 
343 template <class DMT, class MT>
346 {
347  return ComplexMatrix (complex_diag_matrix_value ());
348 }
349 
350 template <class DMT, class MT>
353 {
354  return FloatComplexMatrix (float_complex_diag_matrix_value ());
355 }
356 
357 template <class DMT, class MT>
358 NDArray
360 {
361  return NDArray (matrix_value ());
362 }
363 
364 template <class DMT, class MT>
367 {
368  return FloatNDArray (float_matrix_value ());
369 }
370 
371 template <class DMT, class MT>
374 {
375  return ComplexNDArray (complex_matrix_value ());
376 }
377 
378 template <class DMT, class MT>
381 {
382  return FloatComplexNDArray (float_complex_matrix_value ());
383 }
384 
385 template <class DMT, class MT>
388 {
389  return to_dense ().bool_array_value (warn);
390 }
391 
392 template <class DMT, class MT>
395 {
396  return to_dense ().char_array_value (warn);
397 }
398 
399 template <class DMT, class MT>
402 {
403  return SparseMatrix (diag_matrix_value ());
404 }
405 
406 template <class DMT, class MT>
409 {
410  return SparseComplexMatrix (complex_diag_matrix_value ());
411 }
412 
413 template <class DMT, class MT>
416 {
417  return to_dense ().index_vector ();
418 }
419 
420 template <class DMT, class MT>
423  char type) const
424 {
425  return to_dense ().convert_to_str_internal (pad, force, type);
426 }
427 
428 template <class DMT, class MT>
429 bool
431 {
432  os << "# rows: " << matrix.rows () << "\n"
433  << "# columns: " << matrix.columns () << "\n";
434 
435  os << matrix.extract_diag ();
436 
437  return true;
438 }
439 
440 template <class DMT, class MT>
441 bool
443 {
444  octave_idx_type r = 0, c = 0;
445  bool success = true;
446 
447  if (extract_keyword (is, "rows", r, true)
448  && extract_keyword (is, "columns", c, true))
449  {
450  octave_idx_type l = r < c ? r : c;
451  MT tmp (l, 1);
452  is >> tmp;
453 
454  if (!is)
455  {
456  error ("load: failed to load diagonal matrix constant");
457  success = false;
458  }
459  else
460  {
461  // This is a little tricky, as we have the Matrix type, but
462  // not ColumnVector type. We need to help the compiler get
463  // through the inheritance tree.
464  typedef typename DMT::element_type el_type;
465  matrix = DMT (MDiagArray2<el_type> (MArray<el_type> (tmp)));
466  matrix.resize (r, c);
467 
468  // Invalidate cache. Probably not necessary, but safe.
469  dense_cache = octave_value ();
470  }
471  }
472  else
473  {
474  error ("load: failed to extract number of rows and columns");
475  success = false;
476  }
477 
478  return success;
479 }
480 
481 template <class DMT, class MT>
482 void
484  bool pr_as_read_syntax) const
485 {
486  return octave_print_internal (os, matrix, pr_as_read_syntax,
487  current_print_indent_level ());
488 }
489 
490 template <class DMT, class MT>
491 mxArray *
493 {
494  return to_dense ().as_mxArray ();
495 }
496 
497 template <class DMT, class MT>
498 bool
500 {
501  dim_vector dv = dims ();
502 
503  return (dv.all_ones () || dv.any_zero ());
504 }
505 
506 template <class DMT, class MT>
507 void
509  bool pr_as_read_syntax) const
510 {
511  print_raw (os, pr_as_read_syntax);
512  newline (os);
513 }
514 template <class DMT, class MT>
515 int
517  oct_data_conv::data_type output_type,
518  int skip,
519  oct_mach_info::float_format flt_fmt) const
520 {
521  return to_dense ().write (os, block_size, output_type, skip, flt_fmt);
522 }
523 
524 template <class DMT, class MT>
525 void
527  const std::string& prefix) const
528 {
529  matrix.print_info (os, prefix);
530 }
531 
532 template <class DMT, class MT>
535 {
536  if (! dense_cache.is_defined ())
537  dense_cache = MT (matrix);
538 
539  return dense_cache;
540 }
541