GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
ov-perm.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2008-2018 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
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License 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 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (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 "errwarn.h"
36 #include "ops.h"
37 #include "pr-output.h"
38 
39 #include "ls-oct-text.h"
40 
43  const std::list<octave_value_list>& idx)
44 {
46 
47  switch (type[0])
48  {
49  case '(':
50  retval = do_index_op (idx.front ());
51  break;
52 
53  case '{':
54  case '.':
55  {
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 {
73  octave_idx_type nidx = idx.length ();
74  idx_vector idx0, idx1;
75  if (nidx == 2)
76  {
77  int k = 0; // index we're processing when index_vector throws
78  try
79  {
80  idx0 = idx(0).index_vector ();
81  k = 1;
82  idx1 = idx(1).index_vector ();
83  }
84  catch (octave::index_exception& e)
85  {
86  // Rethrow to allow more info to be reported later.
87  e.set_pos_if_unset (2, k+1);
88  throw;
89  }
90  }
91 
92  // This hack is to allow constructing permutation matrices using
93  // eye(n)(p,:), eye(n)(:,q) && eye(n)(p,q) where p & q are permutation
94  // vectors.
95  // Note that, for better consistency, eye(n)(:,:) still converts to a full
96  // matrix.
97  if (nidx == 2)
98  {
99  bool left = idx0.is_permutation (matrix.rows ());
100  bool right = idx1.is_permutation (matrix.cols ());
101 
102  if (left && right)
103  {
104  if (idx0.is_colon ()) left = false;
105  if (idx1.is_colon ()) right = false;
106  if (left || right)
107  {
108  PermMatrix p = matrix;
109  if (left)
110  p = PermMatrix (idx0, false) * p;
111  if (right)
112  p = p * PermMatrix (idx1, true);
113  retval = p;
114  }
115  else
116  {
117  retval = this;
118  this->count++;
119  }
120  }
121  }
122 
123  if (! retval.is_defined ())
124  {
125  if (nidx == 2 && ! resize_ok && idx0.is_scalar () && idx1.is_scalar ())
126  retval = matrix.checkelem (idx0(0), idx1(0));
127  else
128  retval = to_dense ().do_index_op (idx, resize_ok);
129  }
130 
131  return retval;
132 }
133 
134 // Return true if this matrix has all true elements (non-zero, not NaN/NA).
135 // A permutation cannot have NaN/NA.
136 bool
138 {
139  if (dims ().numel () > 1)
140  {
142  return false; // > 1x1 permutation always has zeros, and no NaN.
143  }
144  else
145  return dims ().numel (); // 1x1 is [1] == true, 0x0 == false.
146 }
147 
148 double
150 {
151  if (isempty ())
152  err_invalid_conversion (type_name (), "real scalar");
153 
154  warn_implicit_conversion ("Octave:array-to-scalar",
155  type_name (), "real scalar");
156 
157  return matrix(0, 0);
158 }
159 
160 float
162 {
163  if (isempty ())
164  err_invalid_conversion (type_name (), "real scalar");
165 
166  warn_implicit_conversion ("Octave:array-to-scalar",
167  type_name (), "real scalar");
168 
169  return matrix(0, 0);
170 }
171 
172 Complex
174 {
175  if (rows () == 0 || columns () == 0)
176  err_invalid_conversion (type_name (), "complex scalar");
177 
178  warn_implicit_conversion ("Octave:array-to-scalar",
179  type_name (), "complex scalar");
180 
181  return Complex (matrix(0, 0), 0);
182 }
183 
186 {
187  float tmp = lo_ieee_float_nan_value ();
188 
190 
191  if (rows () == 0 || columns () == 0)
192  err_invalid_conversion (type_name (), "complex scalar");
193 
194  warn_implicit_conversion ("Octave:array-to-scalar",
195  type_name (), "complex scalar");
196 
197  retval = matrix(0, 0);
198 
199  return retval;
200 }
201 
202 #define FORWARD_MATRIX_VALUE(TYPE, PREFIX) \
203  TYPE \
204  octave_perm_matrix::PREFIX ## _value (bool frc_str_conv) const \
205  { \
206  return to_dense ().PREFIX ## _value (frc_str_conv); \
207  }
208 
211 {
212  return SparseMatrix (matrix);
213 }
214 
217 {
218  return SparseBoolMatrix (matrix);
219 }
220 
223 {
225 }
226 
231 
236 
239 
241 octave_perm_matrix::index_vector (bool require_integers) const
242 {
243  return to_dense ().index_vector (require_integers);
244 }
245 
248  char type) const
249 {
250  return to_dense ().convert_to_str_internal (pad, force, type);
251 }
252 
255 {
256  return matrix;
257 }
258 
261 {
262  return float_array_value ();
263 }
264 
267 {
268  return int8_array_value ();
269 }
270 
273 {
274  return int16_array_value ();
275 }
276 
279 {
280  return int32_array_value ();
281 }
282 
285 {
286  return int64_array_value ();
287 }
288 
291 {
292  return uint8_array_value ();
293 }
294 
297 {
298  return uint16_array_value ();
299 }
300 
303 {
304  return uint32_array_value ();
305 }
306 
309 {
310  return uint64_array_value ();
311 }
312 
315 {
316  return float_display_format (float_format (1, 0, 0));
317 }
318 
322  octave_idx_type j) const
323 {
324  std::ostringstream buf;
326  return buf.str ();
327 }
328 
329 bool
331 {
332  os << "# size: " << matrix.rows () << "\n";
333  os << "# orient: c\n";
334 
336  octave_idx_type n = pvec.numel ();
337  ColumnVector tmp (n);
338  for (octave_idx_type i = 0; i < n; i++) tmp(i) = pvec(i) + 1;
339  os << tmp;
340 
341  return true;
342 }
343 
344 bool
346 {
347  octave_idx_type n;
348  char orient;
349 
350  if (! extract_keyword (is, "size", n, true)
351  || ! extract_keyword (is, "orient", orient, true))
352  error ("load: failed to extract size & orientation");
353 
354  bool colp = orient == 'c';
355  ColumnVector tmp (n);
356  is >> tmp;
357  if (! is)
358  error ("load: failed to load permutation matrix constant");
359 
360  Array<octave_idx_type> pvec (dim_vector (n, 1));
361  for (octave_idx_type i = 0; i < n; i++) pvec(i) = tmp(i) - 1;
362  matrix = PermMatrix (pvec, colp);
363 
364  // Invalidate cache. Probably not necessary, but safe.
366 
367  return true;
368 }
369 
370 bool
371 octave_perm_matrix::save_binary (std::ostream& os, bool&)
372 {
373 
374  int32_t sz = matrix.rows ();
375  bool colp = true;
376  os.write (reinterpret_cast<char *> (&sz), 4);
377  os.write (reinterpret_cast<char *> (&colp), 1);
378  const Array<octave_idx_type>& col_perm = matrix.col_perm_vec ();
379  os.write (reinterpret_cast<const char *> (col_perm.data ()),
380  col_perm.byte_size ());
381 
382  return true;
383 }
384 
385 bool
388 {
389  int32_t sz;
390  bool colp;
391  if (! (is.read (reinterpret_cast<char *> (&sz), 4)
392  && is.read (reinterpret_cast<char *> (&colp), 1)))
393  return false;
394 
396 
397  if (! is.read (reinterpret_cast<char *> (m.fortran_vec ()), m.byte_size ()))
398  return false;
399 
400  if (swap)
401  {
402  int nel = m.numel ();
403  for (int i = 0; i < nel; i++)
404  switch (sizeof (octave_idx_type))
405  {
406  case 8:
407  swap_bytes<8> (&m(i));
408  break;
409  case 4:
410  swap_bytes<4> (&m(i));
411  break;
412  case 2:
413  swap_bytes<2> (&m(i));
414  break;
415  case 1:
416  default:
417  break;
418  }
419  }
420 
421  matrix = PermMatrix (m, colp);
422  return true;
423 }
424 
425 void
427  bool pr_as_read_syntax) const
428 {
429  return octave_print_internal (os, matrix, pr_as_read_syntax,
431 }
432 
433 mxArray *
435 {
436  return to_dense ().as_mxArray ();
437 }
438 
439 bool
441 {
442  dim_vector dv = dims ();
443 
444  return (dv.all_ones () || dv.any_zero ());
445 }
446 
447 void
448 octave_perm_matrix::print (std::ostream& os, bool pr_as_read_syntax)
449 {
450  print_raw (os, pr_as_read_syntax);
451  newline (os);
452 }
453 
454 int
456  oct_data_conv::data_type output_type, int skip,
458 {
459  return to_dense ().write (os, block_size, output_type, skip, flt_fmt);
460 }
461 
462 void
464  const std::string& prefix) const
465 {
466  matrix.print_info (os, prefix);
467 }
468 
471 {
472  if (! dense_cache.is_defined ())
474 
475  return dense_cache;
476 }
477 
479  "permutation matrix", "double");
480 
481 static octave_base_value *
483 {
484  const octave_perm_matrix& v = dynamic_cast<const octave_perm_matrix&> (a);
485 
486  return new octave_matrix (v.matrix_value ());
487 }
488 
491 {
494 }
495 
496 // FIXME: This is duplicated from octave_base_matrix<T>. Could
497 // octave_perm_matrix be derived from octave_base_matrix<T>?
498 
499 void
500 octave_perm_matrix::short_disp (std::ostream& os) const
501 {
502  if (matrix.isempty ())
503  os << "[]";
504  else if (matrix.ndims () == 2)
505  {
506  // FIXME: should this be configurable?
507  octave_idx_type max_elts = 10;
508  octave_idx_type elts = 0;
509 
510  octave_idx_type nel = matrix.numel ();
511 
512  octave_idx_type nr = matrix.rows ();
514 
515  os << '[';
516 
517  for (octave_idx_type i = 0; i < nr; i++)
518  {
519  for (octave_idx_type j = 0; j < nc; j++)
520  {
521  std::ostringstream buf;
523  octave_print_internal (buf, tval);
524  std::string tmp = buf.str ();
525  size_t pos = tmp.find_first_not_of (' ');
526  if (pos != std::string::npos)
527  os << tmp.substr (pos);
528  else if (! tmp.empty ())
529  os << tmp[0];
530 
531  if (++elts >= max_elts)
532  goto done;
533 
534  if (j < nc - 1)
535  os << ", ";
536  }
537 
538  if (i < nr - 1 && elts < max_elts)
539  os << "; ";
540  }
541 
542  done:
543 
544  if (nel <= max_elts)
545  os << ']';
546  }
547  else
548  os << "...";
549 }
550 
553 {
554  octave_base_value *retval = nullptr;
555 
556  if (matrix.numel () == 1)
557  retval = new octave_scalar (matrix (0, 0));
558 
559  return retval;
560 }
561 
564 {
565  if (n < matrix.numel ())
566  {
567  octave_idx_type nr = matrix.rows ();
568 
569  octave_idx_type r = n % nr;
570  octave_idx_type c = n / nr;
571 
572  return octave_value (matrix.elem (r, c));
573  }
574  else
575  return octave_value ();
576 }
octave_idx_type write(const octave_value &data, octave_idx_type block_size, oct_data_conv::data_type output_type, octave_idx_type skip, mach_info::float_format flt_fmt)
Definition: oct-stream.cc:6704
octave_value as_uint32(void) const
Definition: ov-perm.cc:302
SparseMatrix sparse_matrix_value(bool=false) const
Definition: ov-perm.cc:210
octave_value as_uint64(void) const
Definition: ov-perm.cc:308
octave_value as_int64(void) const
Definition: ov-perm.cc:284
octave_value as_int32(void) const
Definition: ov-perm.cc:278
static int left
Definition: randmtzig.cc:184
uint8NDArray uint8_array_value(void) const
Definition: ov-perm.h:184
octave_idx_type numel(void) const
Definition: PermMatrix.h:66
characters Given a string matrix
Definition: hex2num.cc:155
octave_idx_type rows(void) const
Definition: PermMatrix.h:53
const T * data(void) const
Definition: Array.h:582
uint32NDArray uint32_array_value(void) const
Definition: ov-perm.h:190
int64NDArray int64_array_value(void) const
Definition: ov-perm.h:181
mxArray * as_mxArray(void) const
Definition: ov-perm.cc:434
int current_print_indent_level(void) const
Definition: ov-base.h:849
octave_value as_single(void) const
Definition: ov-perm.cc:260
uint64NDArray uint64_array_value(void) const
Definition: ov-perm.h:193
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition: ov-perm.cc:426
void print_info(std::ostream &os, const std::string &prefix) const
Definition: ov-perm.cc:463
void newline(std::ostream &os) const
Definition: ov-base.cc:1328
Complex complex_value(bool=false) const
Definition: ov-perm.cc:173
for large enough k
Definition: lu.cc:617
const T * fortran_vec(void) const
Definition: Array.h:584
void swap_bytes< 8 >(void *ptr)
Definition: byte-swap.h:68
void error(const char *fmt,...)
Definition: error.cc:578
void swap_bytes< 2 >(void *ptr)
Definition: byte-swap.h:53
void print_info(std::ostream &os, const std::string &prefix) const
Definition: PermMatrix.h:108
int write(octave::stream &os, int block_size, oct_data_conv::data_type output_type, int skip, octave::mach_info::float_format flt_fmt) const
bool print_as_scalar(void) const
Definition: ov-perm.cc:440
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition: ov-base.h:180
octave::mach_info::float_format flt_fmt
Definition: load-save.cc:736
bool is_defined(void) const
Definition: ov.h:523
bool is_true(void) const
Definition: ov-perm.cc:137
virtual octave_value to_dense(void) const
Definition: ov-perm.cc:470
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit and then converted to the native representation Opening a file that is already open simply opens it again and returns a separate file id It is not an error to open a file several though writing to the same file through several different file ids may produce unexpected results The possible values of text mode reading and writing automatically converts linefeeds to the appropriate line end character for the you may append a you must also open the file in binary mode The parameter conversions are currently only supported for and permissions will be set to and then everything is written in a single operation This is very efficient and improves performance c
Definition: file-io.cc:587
in this the arguments are accumulated from left to right
Definition: data.cc:390
octave_base_value * try_narrowing_conversion(void)
Definition: ov-perm.cc:552
i e
Definition: data.cc:2591
bool save_binary(std::ostream &os, bool &save_as_floats)
Definition: ov-perm.cc:371
octave_value as_uint8(void) const
Definition: ov-perm.cc:290
int32NDArray int32_array_value(void) const
Definition: ov-perm.h:178
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov-perm.cc:69
bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
Definition: ov-perm.cc:386
bool any_zero(void) const
Definition: dim-vector.h:343
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:400
bool swap
Definition: load-save.cc:738
bool is_permutation(octave_idx_type n) const
Definition: idx-vector.cc:1139
idx_vector index_vector(bool require_integers=false) const
Definition: ov-perm.cc:241
then the function must return scalars which will be concatenated into the return array(s). If code
Definition: cellfun.cc:400
Matrix matrix_value(bool=false) const
Definition: ov-perm.cc:227
done
Definition: syscalls.cc:251
void octave_print_internal(std::ostream &os, const float_display_format &fmt, bool d, bool pr_as_read_syntax)
Definition: pr-output.cc:1780
std::string edit_display(const float_display_format &fmt, octave_idx_type i, octave_idx_type j) const
Definition: ov-perm.cc:320
OCTAVE_EXPORT octave_value_list isdir nd deftypefn *std::string nm
Definition: utils.cc:975
void swap_bytes< 4 >(void *ptr)
Definition: byte-swap.h:60
static octave_base_value * default_numeric_conversion_function(const octave_base_value &a)
Definition: ov-perm.cc:482
std::string extract_keyword(std::istream &is, const char *keyword, const bool next_only)
Definition: ls-oct-text.cc:82
bool is_colon(void) const
Definition: idx-vector.h:575
octave_idx_type rows(void) const
Definition: ov-base.h:316
dim_vector dims(void) const
Definition: ov-perm.h:69
octave_value convert_to_str_internal(bool pad, bool force, char type) const
Definition: ov.h:1256
static int static_type_id(void)
Definition: ov-re-mat.h:248
float_display_format get_edit_display_format(void) const
Definition: ov-perm.cc:314
int write(octave::stream &os, int block_size, oct_data_conv::data_type output_type, int skip, octave::mach_info::float_format flt_fmt) const
Definition: ov-perm.cc:455
octave_value as_double(void) const
Definition: ov-perm.cc:254
type_conv_info numeric_conversion_function(void) const
Definition: ov-perm.cc:490
void short_disp(std::ostream &os) const
Definition: ov-perm.cc:500
double tmp
Definition: data.cc:6252
octave_value retval
Definition: data.cc:6246
#define panic_impossible()
Definition: error.h:40
virtual octave_idx_type numel(void) const
Definition: ov-base.h:333
idx type
Definition: ov.cc:3114
double double_value(bool=false) const
Definition: ov-perm.cc:149
SparseBoolMatrix sparse_bool_matrix_value(bool=false) const
Definition: ov-perm.cc:216
Definition: dMatrix.h:36
sz
Definition: data.cc:5264
void print(std::ostream &os, bool pr_as_read_syntax=false)
Definition: ov-perm.cc:448
PermMatrix matrix
Definition: ov-perm.h:247
float lo_ieee_float_nan_value(void)
Definition: lo-ieee.cc:123
int8NDArray int8_array_value(void) const
Definition: ov-perm.h:172
const Array< octave_idx_type > & col_perm_vec(void) const
Definition: PermMatrix.h:77
FloatNDArray float_array_value(bool=false) const
Definition: ov-perm.cc:233
friend class octave_value
Definition: ov-base.h:228
bool load_ascii(std::istream &is)
Definition: ov-perm.cc:345
octave_idx_type elem(octave_idx_type i, octave_idx_type j) const
Definition: PermMatrix.h:81
octave_idx_type columns(void) const
Definition: PermMatrix.h:55
octave_idx_type checkelem(octave_idx_type i, octave_idx_type j) const
Definition: PermMatrix.cc:88
octave_value dense_cache
Definition: ov-perm.h:251
bool isempty(void) const
Definition: PermMatrix.h:73
bool all_ones(void) const
Definition: dim-vector.h:351
void err_invalid_conversion(const std::string &from, const std::string &to)
Definition: errwarn.cc:68
bool save_ascii(std::ostream &os)
Definition: ov-perm.cc:330
int16NDArray int16_array_value(void) const
Definition: ov-perm.h:175
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:362
std::string type_name(void) const
Definition: ov-perm.h:255
p
Definition: lu.cc:138
void warn_implicit_conversion(const char *id, const char *from, const char *to)
Definition: errwarn.cc:338
float float_value(bool=false) const
Definition: ov-perm.cc:161
octave_idx_type length(void) const
Definition: ovl.h:96
octave_value fast_elem_extract(octave_idx_type n) const
Definition: ov-perm.cc:563
octave_value as_uint16(void) const
Definition: ov-perm.cc:296
octave::refcount< octave_idx_type > count
Definition: ov-base.h:862
for i
Definition: data.cc:5264
void warn_array_as_logical(const dim_vector &dv)
Definition: errwarn.cc:282
octave_idx_type columns(void) const
Definition: ov-base.h:323
bool isempty(void) const
Definition: ov-base.h:359
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:32
mxArray * as_mxArray(void) const
Definition: ov.h:1366
std::complex< double > Complex
Definition: oct-cmplx.h:31
octave_idx_type cols(void) const
Definition: PermMatrix.h:54
int ndims(void) const
Definition: PermMatrix.h:75
octave_value as_int16(void) const
Definition: ov-perm.cc:272
SparseComplexMatrix sparse_complex_matrix_value(bool=false) const
Definition: ov-perm.cc:222
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:366
write the output to stdout if nargout is
Definition: load-save.cc:1612
#define FORWARD_MATRIX_VALUE(TYPE, PREFIX)
Definition: ov-perm.cc:202
octave_value convert_to_str_internal(bool pad, bool force, char type) const
Definition: ov-perm.cc:247
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
bool is_scalar(void) const
Definition: idx-vector.h:578
octave_value as_int8(void) const
Definition: ov-perm.cc:266
size_t byte_size(void) const
Definition: Array.h:438
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
dim_vector dv
Definition: sub2ind.cc:263
octave_value next_subsref(const std::string &type, const std::list< octave_value_list > &idx, size_t skip=1)
FloatComplex float_complex_value(bool=false) const
Definition: ov-perm.cc:185
octave::stream os
Definition: file-io.cc:627
uint16NDArray uint16_array_value(void) const
Definition: ov-perm.h:187
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov.h:444