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-perm.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 "byte-swap.h"
28 #include "dim-vector.h"
29 
30 #include "mxarray.h"
31 #include "ov-perm.h"
32 #include "ov-re-mat.h"
33 #include "ov-scalar.h"
34 #include "error.h"
35 #include "gripes.h"
36 #include "ops.h"
37 #include "pr-output.h"
38 
39 #include "ls-oct-ascii.h"
40 
42 octave_perm_matrix::subsref (const std::string& type,
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 
70  bool resize_ok)
71 {
72  octave_value retval;
73  octave_idx_type nidx = idx.length ();
74  idx_vector idx0, idx1;
75  if (nidx == 2)
76  {
77  idx0 = idx(0).index_vector ();
78  idx1 = idx(1).index_vector ();
79  }
80 
81  // This hack is to allow constructing permutation matrices using
82  // eye(n)(p,:), eye(n)(:,q) && eye(n)(p,q) where p & q are permutation
83  // vectors.
84  // Note that, for better consistency, eye(n)(:,:) still converts to a full
85  // matrix.
86  if (! error_state && nidx == 2)
87  {
88  bool left = idx0.is_permutation (matrix.rows ());
89  bool right = idx1.is_permutation (matrix.cols ());
90 
91  if (left && right)
92  {
93  if (idx0.is_colon ()) left = false;
94  if (idx1.is_colon ()) right = false;
95  if (left || right)
96  {
97  PermMatrix p = matrix;
98  if (left)
99  p = PermMatrix (idx0, false) * p;
100  if (right)
101  p = p * PermMatrix (idx1, true);
102  retval = p;
103  }
104  else
105  {
106  retval = this;
107  this->count++;
108  }
109  }
110  }
111 
112  // if error_state is set, we've already griped.
113  if (! error_state && ! retval.is_defined ())
114  {
115  if (nidx == 2 && ! resize_ok &&
116  idx0.is_scalar () && idx1.is_scalar ())
117  {
118  retval = matrix.checkelem (idx0(0), idx1(0));
119  }
120  else
121  retval = to_dense ().do_index_op (idx, resize_ok);
122  }
123 
124  return retval;
125 }
126 
127 bool
129 {
130  return to_dense ().is_true ();
131 }
132 
133 double
135 {
136  double retval = lo_ieee_nan_value ();
137 
138  if (numel () > 0)
139  {
140  gripe_implicit_conversion ("Octave:array-to-scalar",
141  type_name (), "real scalar");
142 
143  retval = matrix (0, 0);
144  }
145  else
146  gripe_invalid_conversion (type_name (), "real scalar");
147 
148  return retval;
149 }
150 
151 float
153 {
154  float retval = lo_ieee_float_nan_value ();
155 
156  if (numel () > 0)
157  {
158  gripe_implicit_conversion ("Octave:array-to-scalar",
159  type_name (), "real scalar");
160 
161  retval = matrix (0, 0);
162  }
163  else
164  gripe_invalid_conversion (type_name (), "real scalar");
165 
166  return retval;
167 }
168 
169 Complex
171 {
172  double tmp = lo_ieee_nan_value ();
173 
174  Complex retval (tmp, tmp);
175 
176  if (rows () > 0 && columns () > 0)
177  {
178  gripe_implicit_conversion ("Octave:array-to-scalar",
179  type_name (), "complex scalar");
180 
181  retval = matrix (0, 0);
182  }
183  else
184  gripe_invalid_conversion (type_name (), "complex scalar");
185 
186  return retval;
187 }
188 
191 {
192  float tmp = lo_ieee_float_nan_value ();
193 
194  FloatComplex retval (tmp, tmp);
195 
196  if (rows () > 0 && columns () > 0)
197  {
198  gripe_implicit_conversion ("Octave:array-to-scalar",
199  type_name (), "complex scalar");
200 
201  retval = matrix (0, 0);
202  }
203  else
204  gripe_invalid_conversion (type_name (), "complex scalar");
205 
206  return retval;
207 }
208 
209 #define FORWARD_MATRIX_VALUE(TYPE, PREFIX) \
210 TYPE \
211 octave_perm_matrix::PREFIX ## _value (bool frc_str_conv) const \
212 { \
213  return to_dense ().PREFIX ## _value (frc_str_conv); \
214 }
215 
218 {
219  return SparseMatrix (matrix);
220 }
221 
224 {
225  return SparseBoolMatrix (matrix);
226 }
227 
230 {
232 }
233 
238 
243 
246 
248 octave_perm_matrix::index_vector (void) const
249 {
250  return to_dense ().index_vector ();
251 }
252 
255  char type) const
256 {
257  return to_dense ().convert_to_str_internal (pad, force, type);
258 }
259 
260 bool
262 {
263  typedef octave_int<octave_idx_type> idx_int_type;
264 
265  os << "# size: " << matrix.rows () << "\n";
266  os << "# orient: " << (matrix.is_col_perm () ? 'c' : 'r') << '\n';
267 
269  octave_idx_type n = pvec.length ();
270  ColumnVector tmp (n);
271  for (octave_idx_type i = 0; i < n; i++) tmp(i) = pvec(i) + 1;
272  os << tmp;
273 
274  return true;
275 }
276 
277 bool
279 {
280  typedef octave_int<octave_idx_type> idx_int_type;
281  octave_idx_type n;
282  bool success = true;
283  char orient;
284 
285  if (extract_keyword (is, "size", n, true)
286  && extract_keyword (is, "orient", orient, true))
287  {
288  bool colp = orient == 'c';
289  ColumnVector tmp (n);
290  is >> tmp;
291  if (!is)
292  {
293  error ("load: failed to load permutation matrix constant");
294  success = false;
295  }
296  else
297  {
298  Array<octave_idx_type> pvec (dim_vector (n, 1));
299  for (octave_idx_type i = 0; i < n; i++) pvec(i) = tmp(i) - 1;
300  matrix = PermMatrix (pvec, colp);
301 
302  // Invalidate cache. Probably not necessary, but safe.
304  }
305  }
306  else
307  {
308  error ("load: failed to extract size & orientation");
309  success = false;
310  }
311 
312  return success;
313 }
314 
315 bool
316 octave_perm_matrix::save_binary (std::ostream& os, bool&)
317 {
318 
319  int32_t sz = matrix.rows ();
320  bool colp = matrix.is_col_perm ();
321  os.write (reinterpret_cast<char *> (&sz), 4);
322  os.write (reinterpret_cast<char *> (&colp), 1);
323  os.write (reinterpret_cast<const char *> (matrix.data ()),
324  matrix.byte_size ());
325 
326  return true;
327 }
328 
329 bool
330 octave_perm_matrix::load_binary (std::istream& is, bool swap,
332 {
333  int32_t sz;
334  bool colp;
335  if (! (is.read (reinterpret_cast<char *> (&sz), 4)
336  && is.read (reinterpret_cast<char *> (&colp), 1)))
337  return false;
338 
340 
341  if (! is.read (reinterpret_cast<char *> (m.fortran_vec ()), m.byte_size ()))
342  return false;
343 
344  if (swap)
345  {
346  int nel = m.numel ();
347  for (int i = 0; i < nel; i++)
348  switch (sizeof (octave_idx_type))
349  {
350  case 8:
351  swap_bytes<8> (&m(i));
352  break;
353  case 4:
354  swap_bytes<4> (&m(i));
355  break;
356  case 2:
357  swap_bytes<2> (&m(i));
358  break;
359  case 1:
360  default:
361  break;
362  }
363  }
364 
365  matrix = PermMatrix (m, colp);
366  return true;
367 }
368 
369 void
371  bool pr_as_read_syntax) const
372 {
373  return octave_print_internal (os, matrix, pr_as_read_syntax,
375 }
376 
377 mxArray *
379 {
380  return to_dense ().as_mxArray ();
381 }
382 
383 bool
385 {
386  dim_vector dv = dims ();
387 
388  return (dv.all_ones () || dv.any_zero ());
389 }
390 
391 void
392 octave_perm_matrix::print (std::ostream& os, bool pr_as_read_syntax) const
393 {
394  print_raw (os, pr_as_read_syntax);
395  newline (os);
396 }
397 
398 int
400  oct_data_conv::data_type output_type, int skip,
401  oct_mach_info::float_format flt_fmt) const
402 {
403  return to_dense ().write (os, block_size, output_type, skip, flt_fmt);
404 }
405 
406 void
408  const std::string& prefix) const
409 {
410  matrix.print_info (os, prefix);
411 }
412 
413 
416 {
417  if (! dense_cache.is_defined ())
419 
420  return dense_cache;
421 }
422 
424 
426  "permutation matrix", "double");
427 
428 static octave_base_value *
430 {
432 
433  return new octave_matrix (v.matrix_value ());
434 }
435 
438 {
441 }
442 
445 {
446  octave_base_value *retval = 0;
447 
448  if (matrix.nelem () == 1)
449  retval = new octave_scalar (matrix (0, 0));
450 
451  return retval;
452 }
453