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-perm.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 "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 && idx0.is_scalar () && idx1.is_scalar ())
116  retval = matrix.checkelem (idx0(0), idx1(0));
117  else
118  retval = to_dense ().do_index_op (idx, resize_ok);
119  }
120 
121  return retval;
122 }
123 
124 bool
126 {
127  return to_dense ().is_true ();
128 }
129 
130 double
132 {
133  double retval = lo_ieee_nan_value ();
134 
135  if (numel () > 0)
136  {
137  gripe_implicit_conversion ("Octave:array-to-scalar",
138  type_name (), "real scalar");
139 
140  retval = matrix (0, 0);
141  }
142  else
143  gripe_invalid_conversion (type_name (), "real scalar");
144 
145  return retval;
146 }
147 
148 float
150 {
151  float retval = lo_ieee_float_nan_value ();
152 
153  if (numel () > 0)
154  {
155  gripe_implicit_conversion ("Octave:array-to-scalar",
156  type_name (), "real scalar");
157 
158  retval = matrix (0, 0);
159  }
160  else
161  gripe_invalid_conversion (type_name (), "real scalar");
162 
163  return retval;
164 }
165 
166 Complex
168 {
169  double tmp = lo_ieee_nan_value ();
170 
171  Complex retval (tmp, tmp);
172 
173  if (rows () > 0 && columns () > 0)
174  {
175  gripe_implicit_conversion ("Octave:array-to-scalar",
176  type_name (), "complex scalar");
177 
178  retval = matrix (0, 0);
179  }
180  else
181  gripe_invalid_conversion (type_name (), "complex scalar");
182 
183  return retval;
184 }
185 
188 {
189  float tmp = lo_ieee_float_nan_value ();
190 
191  FloatComplex retval (tmp, tmp);
192 
193  if (rows () > 0 && columns () > 0)
194  {
195  gripe_implicit_conversion ("Octave:array-to-scalar",
196  type_name (), "complex scalar");
197 
198  retval = matrix (0, 0);
199  }
200  else
201  gripe_invalid_conversion (type_name (), "complex scalar");
202 
203  return retval;
204 }
205 
206 #define FORWARD_MATRIX_VALUE(TYPE, PREFIX) \
207 TYPE \
208 octave_perm_matrix::PREFIX ## _value (bool frc_str_conv) const \
209 { \
210  return to_dense ().PREFIX ## _value (frc_str_conv); \
211 }
212 
215 {
216  return SparseMatrix (matrix);
217 }
218 
221 {
222  return SparseBoolMatrix (matrix);
223 }
224 
227 {
229 }
230 
235 
240 
243 
245 octave_perm_matrix::index_vector (bool require_integers) const
246 {
247  return to_dense ().index_vector (require_integers);
248 }
249 
252  char type) const
253 {
254  return to_dense ().convert_to_str_internal (pad, force, type);
255 }
256 
257 bool
259 {
260  os << "# size: " << matrix.rows () << "\n";
261  os << "# orient: c\n";
262 
264  octave_idx_type n = pvec.length ();
265  ColumnVector tmp (n);
266  for (octave_idx_type i = 0; i < n; i++) tmp(i) = pvec(i) + 1;
267  os << tmp;
268 
269  return true;
270 }
271 
272 bool
274 {
275  octave_idx_type n;
276  bool success = true;
277  char orient;
278 
279  if (extract_keyword (is, "size", n, true)
280  && extract_keyword (is, "orient", orient, true))
281  {
282  bool colp = orient == 'c';
283  ColumnVector tmp (n);
284  is >> tmp;
285  if (!is)
286  {
287  error ("load: failed to load permutation matrix constant");
288  success = false;
289  }
290  else
291  {
292  Array<octave_idx_type> pvec (dim_vector (n, 1));
293  for (octave_idx_type i = 0; i < n; i++) pvec(i) = tmp(i) - 1;
294  matrix = PermMatrix (pvec, colp);
295 
296  // Invalidate cache. Probably not necessary, but safe.
298  }
299  }
300  else
301  {
302  error ("load: failed to extract size & orientation");
303  success = false;
304  }
305 
306  return success;
307 }
308 
309 bool
310 octave_perm_matrix::save_binary (std::ostream& os, bool&)
311 {
312 
313  int32_t sz = matrix.rows ();
314  bool colp = true;
315  os.write (reinterpret_cast<char *> (&sz), 4);
316  os.write (reinterpret_cast<char *> (&colp), 1);
317  const Array<octave_idx_type>& col_perm = matrix.col_perm_vec ();
318  os.write (reinterpret_cast<const char *> (col_perm.data ()),
319  col_perm.byte_size ());
320 
321  return true;
322 }
323 
324 bool
325 octave_perm_matrix::load_binary (std::istream& is, bool swap,
327 {
328  int32_t sz;
329  bool colp;
330  if (! (is.read (reinterpret_cast<char *> (&sz), 4)
331  && is.read (reinterpret_cast<char *> (&colp), 1)))
332  return false;
333 
335 
336  if (! is.read (reinterpret_cast<char *> (m.fortran_vec ()), m.byte_size ()))
337  return false;
338 
339  if (swap)
340  {
341  int nel = m.numel ();
342  for (int i = 0; i < nel; i++)
343  switch (sizeof (octave_idx_type))
344  {
345  case 8:
346  swap_bytes<8> (&m(i));
347  break;
348  case 4:
349  swap_bytes<4> (&m(i));
350  break;
351  case 2:
352  swap_bytes<2> (&m(i));
353  break;
354  case 1:
355  default:
356  break;
357  }
358  }
359 
360  matrix = PermMatrix (m, colp);
361  return true;
362 }
363 
364 void
366  bool pr_as_read_syntax) const
367 {
368  return octave_print_internal (os, matrix, pr_as_read_syntax,
370 }
371 
372 mxArray *
374 {
375  return to_dense ().as_mxArray ();
376 }
377 
378 bool
380 {
381  dim_vector dv = dims ();
382 
383  return (dv.all_ones () || dv.any_zero ());
384 }
385 
386 void
387 octave_perm_matrix::print (std::ostream& os, bool pr_as_read_syntax)
388 {
389  print_raw (os, pr_as_read_syntax);
390  newline (os);
391 }
392 
393 int
395  oct_data_conv::data_type output_type, int skip,
396  oct_mach_info::float_format flt_fmt) const
397 {
398  return to_dense ().write (os, block_size, output_type, skip, flt_fmt);
399 }
400 
401 void
403  const std::string& prefix) const
404 {
405  matrix.print_info (os, prefix);
406 }
407 
408 
411 {
412  if (! dense_cache.is_defined ())
414 
415  return dense_cache;
416 }
417 
418 
420  "permutation matrix", "double");
421 
422 static octave_base_value *
424 {
426 
427  return new octave_matrix (v.matrix_value ());
428 }
429 
432 {
435 }
436 
439 {
440  octave_base_value *retval = 0;
441 
442  if (matrix.nelem () == 1)
443  retval = new octave_scalar (matrix (0, 0));
444 
445  return retval;
446 }
447 
450 {
451  if (n < matrix.numel ())
452  {
453  octave_idx_type nr = matrix.rows ();
454 
455  octave_idx_type r = n % nr;
456  octave_idx_type c = n / nr;
457 
458  return octave_value (matrix.elem (r, c));
459  }
460  else
461  return octave_value ();
462 }
void gripe_implicit_conversion(const char *id, const char *from, const char *to)
Definition: gripes.cc:180
octave_refcount< octave_idx_type > count
Definition: ov-base.h:818
octave_idx_type rows(void) const
Definition: PermMatrix.h:55
octave_idx_type columns(void) const
Definition: ov-base.h:301
mxArray * as_mxArray(void) const
Definition: ov.h:1124
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:275
octave_idx_type length(void) const
Definition: oct-obj.h:89
octave_idx_type cols(void) const
Definition: PermMatrix.h:56
bool is_defined(void) const
Definition: ov.h:520
void swap_bytes< 8 >(void *ptr)
Definition: byte-swap.h:67
void error(const char *fmt,...)
Definition: error.cc:476
void swap_bytes< 2 >(void *ptr)
Definition: byte-swap.h:52
void print_info(std::ostream &os, const std::string &prefix) const
Definition: ov-perm.cc:402
virtual octave_value to_dense(void) const
Definition: ov-perm.cc:410
OCTAVE_EMPTY_CPP_ARG std::string type_name(void) const
Definition: ov-perm.h:234
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition: ov-base.h:164
double lo_ieee_nan_value(void)
Definition: lo-ieee.cc:126
static int left
Definition: randmtzig.c:189
octave_value convert_to_str_internal(bool pad, bool force, char type) const
Definition: ov.h:1022
bool is_true(void) const
Definition: ov-perm.cc:125
octave_idx_type checkelem(octave_idx_type i, octave_idx_type j) const
Definition: PermMatrix.cc:105
bool all_ones(void) const
Definition: dim-vector.h:349
void print_info(std::ostream &os, const std::string &prefix) const
Definition: PermMatrix.h:107
octave_idx_type nelem(void) const
Definition: PermMatrix.h:64
octave_base_value * try_narrowing_conversion(void)
Definition: ov-perm.cc:438
void newline(std::ostream &os) const
Definition: ov-base.cc:1500
SparseBoolMatrix sparse_bool_matrix_value(bool=false) const
Definition: ov-perm.cc:220
bool save_binary(std::ostream &os, bool &save_as_floats)
Definition: ov-perm.cc:310
virtual octave_idx_type numel(void) const
Definition: ov-base.h:311
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov-perm.cc:69
double double_value(bool=false) const
Definition: ov-perm.cc:131
size_t byte_size(void) const
Definition: Array.h:333
bool print_as_scalar(void) const
Definition: ov-perm.cc:379
std::string extract_keyword(std::istream &is, const char *keyword, const bool next_only)
Definition: ls-oct-ascii.cc:80
void swap_bytes< 4 >(void *ptr)
Definition: byte-swap.h:59
#define CAST_CONV_ARG(t)
Definition: ops.h:83
static octave_base_value * default_numeric_conversion_function(const octave_base_value &a)
Definition: ov-perm.cc:423
const Array< octave_idx_type > & col_perm_vec(void) const
Definition: PermMatrix.h:72
static int static_type_id(void)
Definition: ov-re-mat.h:235
const T * data(void) const
Definition: Array.h:479
int error_state
Definition: error.cc:101
octave_value convert_to_str_internal(bool pad, bool force, char type) const
Definition: ov-perm.cc:251
#define panic_impossible()
Definition: error.h:33
FloatComplex float_complex_value(bool=false) const
Definition: ov-perm.cc:187
octave_idx_type elem(octave_idx_type i, octave_idx_type j) const
Definition: PermMatrix.h:76
Definition: dMatrix.h:35
void print(std::ostream &os, bool pr_as_read_syntax=false)
Definition: ov-perm.cc:387
bool any_zero(void) const
Definition: dim-vector.h:331
bool is_permutation(octave_idx_type n) const
Definition: idx-vector.cc:1145
PermMatrix matrix
Definition: ov-perm.h:225
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
Definition: ov.cc:1956
float lo_ieee_float_nan_value(void)
Definition: lo-ieee.cc:202
friend class octave_value
Definition: ov-base.h:206
bool load_ascii(std::istream &is)
Definition: ov-perm.cc:273
octave_value dense_cache
Definition: ov-perm.h:229
bool is_true(void) const
Definition: ov.h:671
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
Definition: ov-perm.cc:394
octave_idx_type length(void) const
Number of elements in the array.
Definition: Array.h:267
bool save_ascii(std::ostream &os)
Definition: ov-perm.cc:258
void gripe_invalid_conversion(const std::string &from, const std::string &to)
Definition: gripes.cc:99
int current_print_indent_level(void) const
Definition: ov-base.h:805
void octave_print_internal(std::ostream &, char, bool)
Definition: pr-output.cc:1715
bool is_scalar(void) const
Definition: idx-vector.h:578
type_conv_info numeric_conversion_function(void) const
Definition: ov-perm.cc:431
SparseComplexMatrix sparse_complex_matrix_value(bool=false) const
Definition: ov-perm.cc:226
octave_value fast_elem_extract(octave_idx_type n) const
Definition: ov-perm.cc:449
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov-perm.cc:42
std::complex< float > FloatComplex
Definition: oct-cmplx.h:30
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition: ov-perm.cc:365
Complex complex_value(bool=false) const
Definition: ov-perm.cc:167
std::complex< double > Complex
Definition: oct-cmplx.h:29
const T * fortran_vec(void) const
Definition: Array.h:481
#define FORWARD_MATRIX_VALUE(TYPE, PREFIX)
Definition: ov-perm.cc:206
idx_vector index_vector(bool require_integers=false) const
Definition: ov-perm.cc:245
float float_value(bool=false) const
Definition: ov-perm.cc:149
octave_idx_type numel(void) const
Definition: PermMatrix.h:65
octave_value next_subsref(const std::string &type, const std::list< octave_value_list > &idx, size_t skip=1)
Definition: ov.cc:1317
octave_idx_type rows(void) const
Definition: ov-base.h:294
bool is_colon(void) const
Definition: idx-vector.h:575
bool load_binary(std::istream &is, bool swap, oct_mach_info::float_format fmt)
Definition: ov-perm.cc:325
SparseMatrix sparse_matrix_value(bool=false) const
Definition: ov-perm.cc:214
dim_vector dims(void) const
Definition: ov-perm.h:67
mxArray * as_mxArray(void) const
Definition: ov-perm.cc:373
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov.h:438