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-diag.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2008-2015 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 
104  if (idx.length () == 2 && ! resize_ok)
105  {
106  idx_vector idx0 = idx(0).index_vector ();
107  idx_vector idx1 = idx(1).index_vector ();
108 
109  if (idx0.is_scalar () && idx1.is_scalar ())
110  {
111  retval = matrix.checkelem (idx0(0), idx1(0));
112  }
113  else
114  {
115  octave_idx_type m = idx0.length (matrix.rows ());
116  octave_idx_type n = idx1.length (matrix.columns ());
117  if (idx0.is_colon_equiv (m) && idx1.is_colon_equiv (n)
118  && m <= matrix.rows () && n <= matrix.rows ())
119  {
120  DMT rm (matrix);
121  rm.resize (m, n);
122  retval = rm;
123  }
124  else
125  retval = to_dense ().do_index_op (idx, resize_ok);
126  }
127  }
128  else
129  retval = to_dense ().do_index_op (idx, resize_ok);
130 
131  return retval;
132 }
133 
134 template <class DMT, class MT>
137  const std::list<octave_value_list>& idx,
138  const octave_value& rhs)
139 {
140  octave_value retval;
141 
142  switch (type[0])
143  {
144  case '(':
145  {
146  if (type.length () == 1)
147  {
148  octave_value_list jdx = idx.front ();
149  // Check for a simple element assignment. That means, if D is a
150  // diagonal matrix, 'D(i,i) = x' will not destroy its diagonality
151  // (provided i is a valid index).
152  if (jdx.length () == 2
153  && jdx(0).is_scalar_type () && jdx(1).is_scalar_type ())
154  {
155  typename DMT::element_type val;
156  idx_vector i0 = jdx(0).index_vector ();
157  idx_vector i1 = jdx(1).index_vector ();
158  if (! error_state && i0(0) == i1(0)
159  && i0(0) < matrix.rows () && i1(0) < matrix.cols ()
160  && chk_valid_scalar (rhs, val))
161  {
162  matrix.dgelem (i0(0)) = val;
163  retval = this;
164  this->count++;
165  // invalidate cache
166  dense_cache = octave_value ();
167  }
168  }
169 
170  if (! error_state && ! retval.is_defined ())
171  retval = numeric_assign (type, idx, rhs);
172  }
173  else
174  {
175  std::string nm = type_name ();
176  error ("in indexed assignment of %s, last lhs index must be ()",
177  nm.c_str ());
178  }
179  }
180  break;
181 
182  case '{':
183  case '.':
184  {
185  if (is_empty ())
186  {
187  octave_value tmp = octave_value::empty_conv (type, rhs);
188 
189  retval = tmp.subsasgn (type, idx, rhs);
190  }
191  else
192  {
193  std::string nm = type_name ();
194  error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
195  }
196  }
197  break;
198 
199  default:
200  panic_impossible ();
201  }
202 
203  return retval;
204 }
205 
206 template <class DMT, class MT>
208 octave_base_diag<DMT, MT>::resize (const dim_vector& dv, bool fill) const
209 {
210  octave_value retval;
211  if (dv.length () == 2)
212  {
213  DMT rm (matrix);
214  rm.resize (dv(0), dv(1));
215  retval = rm;
216  }
217  else
218  retval = to_dense ().resize (dv, fill);
219  return retval;
220 }
221 
222 template <class DMT, class MT>
223 bool
225 {
226  return to_dense ().is_true ();
227 }
228 
229 // FIXME: This should be achieveable using ::real
230 template <class T> inline T helper_getreal (T x) { return x; }
231 template <class T> inline T helper_getreal (std::complex<T> x)
232 { return x.real (); }
233 // FIXME: We really need some traits so that ad hoc hooks like this
234 // are not necessary.
235 template <class T> inline T helper_iscomplex (T) { return false; }
236 template <class T> inline T helper_iscomplex (std::complex<T>) { return true; }
237 
238 template <class DMT, class MT>
239 double
240 octave_base_diag<DMT, MT>::double_value (bool force_conversion) const
241 {
242  double retval = lo_ieee_nan_value ();
243  typedef typename DMT::element_type el_type;
244 
245  if (helper_iscomplex (el_type ()) && ! force_conversion)
246  gripe_implicit_conversion ("Octave:imag-to-real",
247  "complex matrix", "real scalar");
248 
249  if (numel () > 0)
250  {
251  gripe_implicit_conversion ("Octave:array-to-scalar",
252  type_name (), "real scalar");
253 
254  retval = helper_getreal (el_type (matrix (0, 0)));
255  }
256  else
257  gripe_invalid_conversion (type_name (), "real scalar");
258 
259  return retval;
260 }
261 
262 template <class DMT, class MT>
263 float
264 octave_base_diag<DMT, MT>::float_value (bool force_conversion) const
265 {
266  float retval = lo_ieee_float_nan_value ();
267  typedef typename DMT::element_type el_type;
268 
269  if (helper_iscomplex (el_type ()) && ! force_conversion)
270  gripe_implicit_conversion ("Octave:imag-to-real",
271  "complex matrix", "real scalar");
272 
273  if (numel () > 0)
274  {
275  gripe_implicit_conversion ("Octave:array-to-scalar",
276  type_name (), "real scalar");
277 
278  retval = helper_getreal (el_type (matrix (0, 0)));
279  }
280  else
281  gripe_invalid_conversion (type_name (), "real scalar");
282 
283  return retval;
284 }
285 
286 template <class DMT, class MT>
287 Complex
289 {
290  double tmp = lo_ieee_nan_value ();
291 
292  Complex retval (tmp, tmp);
293 
294  if (rows () > 0 && columns () > 0)
295  {
296  gripe_implicit_conversion ("Octave:array-to-scalar",
297  type_name (), "complex scalar");
298 
299  retval = matrix (0, 0);
300  }
301  else
302  gripe_invalid_conversion (type_name (), "complex scalar");
303 
304  return retval;
305 }
306 
307 template <class DMT, class MT>
310 {
311  float tmp = lo_ieee_float_nan_value ();
312 
313  FloatComplex retval (tmp, tmp);
314 
315  if (rows () > 0 && columns () > 0)
316  {
317  gripe_implicit_conversion ("Octave:array-to-scalar",
318  type_name (), "complex scalar");
319 
320  retval = matrix (0, 0);
321  }
322  else
323  gripe_invalid_conversion (type_name (), "complex scalar");
324 
325  return retval;
326 }
327 
328 template <class DMT, class MT>
329 Matrix
331 {
332  return Matrix (diag_matrix_value ());
333 }
334 
335 template <class DMT, class MT>
338 {
339  return FloatMatrix (float_diag_matrix_value ());
340 }
341 
342 template <class DMT, class MT>
345 {
346  return ComplexMatrix (complex_diag_matrix_value ());
347 }
348 
349 template <class DMT, class MT>
352 {
353  return FloatComplexMatrix (float_complex_diag_matrix_value ());
354 }
355 
356 template <class DMT, class MT>
357 NDArray
359 {
360  return NDArray (matrix_value ());
361 }
362 
363 template <class DMT, class MT>
366 {
367  return FloatNDArray (float_matrix_value ());
368 }
369 
370 template <class DMT, class MT>
373 {
374  return ComplexNDArray (complex_matrix_value ());
375 }
376 
377 template <class DMT, class MT>
380 {
381  return FloatComplexNDArray (float_complex_matrix_value ());
382 }
383 
384 template <class DMT, class MT>
387 {
388  return to_dense ().bool_array_value (warn);
389 }
390 
391 template <class DMT, class MT>
394 {
395  return to_dense ().char_array_value (warn);
396 }
397 
398 template <class DMT, class MT>
401 {
402  return SparseMatrix (diag_matrix_value ());
403 }
404 
405 template <class DMT, class MT>
408 {
409  return SparseComplexMatrix (complex_diag_matrix_value ());
410 }
411 
412 template <class DMT, class MT>
414 octave_base_diag<DMT, MT>::index_vector (bool require_integers) const
415 {
416  return to_dense ().index_vector (require_integers);
417 }
418 
419 template <class DMT, class MT>
422  char type) const
423 {
424  return to_dense ().convert_to_str_internal (pad, force, type);
425 }
426 
427 template <class DMT, class MT>
428 bool
430 {
431  os << "# rows: " << matrix.rows () << "\n"
432  << "# columns: " << matrix.columns () << "\n";
433 
434  os << matrix.extract_diag ();
435 
436  return true;
437 }
438 
439 template <class DMT, class MT>
440 bool
442 {
443  octave_idx_type r = 0;
444  octave_idx_type 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
508 octave_base_diag<DMT, MT>::print (std::ostream& os, bool pr_as_read_syntax)
509 {
510  print_raw (os, pr_as_read_syntax);
511  newline (os);
512 }
513 template <class DMT, class MT>
514 int
516  oct_data_conv::data_type output_type,
517  int skip,
518  oct_mach_info::float_format flt_fmt) const
519 {
520  return to_dense ().write (os, block_size, output_type, skip, flt_fmt);
521 }
522 
523 template <class DMT, class MT>
524 void
526  const std::string& prefix) const
527 {
528  matrix.print_info (os, prefix);
529 }
530 
531 template <class DMT, class MT>
534 {
535  if (n < matrix.numel ())
536  {
537  octave_idx_type nr = matrix.rows ();
538 
539  octave_idx_type r = n % nr;
540  octave_idx_type c = n / nr;
541 
542  return octave_value (matrix.elem (r, c));
543  }
544  else
545  return octave_value ();
546 }
547 
548 template <class DMT, class MT>
551 {
552  if (! dense_cache.is_defined ())
553  dense_cache = MT (matrix);
554 
555  return dense_cache;
556 }
557 
void gripe_implicit_conversion(const char *id, const char *from, const char *to)
Definition: gripes.cc:180
void print(std::ostream &os, bool pr_as_read_syntax=false)
octave_value to_dense(void) const
octave_idx_type length(octave_idx_type n=0) const
Definition: idx-vector.h:551
float float_value(bool=false) const
NDArray array_value(bool=false) const
T helper_iscomplex(T)
double double_value(bool=false) const
mxArray * as_mxArray(void) const
idx_vector index_vector(bool=false) const
bool load_ascii(std::istream &is)
octave_value resize(const dim_vector &dv, bool fill=false) const
octave_idx_type length(void) const
Definition: oct-obj.h:89
bool is_defined(void) const
Definition: ov.h:520
SparseComplexMatrix sparse_complex_matrix_value(bool=false) const
void error(const char *fmt,...)
Definition: error.cc:476
charNDArray char_array_value(bool=false) const
SparseMatrix sparse_matrix_value(bool=false) const
int write(octave_stream &os, int block_size, oct_data_conv::data_type output_type, int skip, oct_mach_info::float_format flt_fmt) const
octave_value resize(const dim_vector &dv, bool fill=false) const
Definition: ov.h:507
double lo_ieee_nan_value(void)
Definition: lo-ieee.cc:126
octave_value convert_to_str_internal(bool pad, bool force, char type) const
Definition: ov.h:1022
Definition: MArray.h:36
bool all_ones(void) const
Definition: dim-vector.h:349
FloatComplex float_complex_value(bool=false) const
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov-base-diag.cc:99
bool print_as_scalar(void) const
octave_value convert_to_str_internal(bool pad, bool force, char type) const
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov.cc:1414
std::string extract_keyword(std::istream &is, const char *keyword, const bool next_only)
Definition: ls-oct-ascii.cc:80
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
int error_state
Definition: error.cc:101
#define panic_impossible()
Definition: error.h:33
ComplexMatrix complex_matrix_value(bool=false) const
Definition: dMatrix.h:35
bool any_zero(void) const
Definition: dim-vector.h:331
Complex complex_value(bool=false) const
float lo_ieee_float_nan_value(void)
Definition: lo-ieee.cc:202
void print_info(std::ostream &os, const std::string &prefix) const
bool is_colon_equiv(octave_idx_type n) const
Definition: idx-vector.h:584
FloatComplexNDArray float_complex_array_value(bool=false) const
NDArray array_value(bool frc_str_conv=false) const
Definition: ov.h:779
FloatMatrix float_matrix_value(bool=false) const
NDArray diag(octave_idx_type k=0) const
Definition: dNDArray.cc:860
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov-base-diag.cc:45
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
void gripe_invalid_conversion(const std::string &from, const std::string &to)
Definition: gripes.cc:99
Matrix matrix_value(bool=false) const
ComplexNDArray complex_array_value(bool=false) const
FloatNDArray float_array_value(bool=false) const
void octave_print_internal(std::ostream &, char, bool)
Definition: pr-output.cc:1715
bool is_scalar(void) const
Definition: idx-vector.h:578
octave_value fast_elem_extract(octave_idx_type n) const
boolNDArray bool_array_value(bool warn=false) const
bool save_ascii(std::ostream &os)
std::complex< float > FloatComplex
Definition: oct-cmplx.h:30
FloatComplexMatrix float_complex_matrix_value(bool=false) const
std::complex< double > Complex
Definition: oct-cmplx.h:29
int length(void) const
Definition: dim-vector.h:281
octave_value next_subsref(const std::string &type, const std::list< octave_value_list > &idx, size_t skip=1)
Definition: ov.cc:1317
octave_value diag(octave_idx_type k=0) const
Definition: ov-base-diag.cc:74
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
bool is_true(void) const
F77_RET_T const double * x
T helper_getreal(T x)
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov.h:438