GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
ov-perm.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 2008-2025 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include "byte-swap.h"
31#include "dim-vector.h"
32
33#include "mxarray.h"
34#include "ov-perm.h"
35#include "ov-re-mat.h"
36#include "ov-scalar.h"
37#include "error.h"
38#include "errwarn.h"
39#include "ops.h"
40#include "pr-output.h"
41
42#include "ls-oct-text.h"
43
45octave_perm_matrix::subsref (const std::string& type,
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:
65 error ("unexpected: index not '(', '{', or '.' in octave_perm_matrix::subsref - please report this bug");
66 }
67
68 return retval.next_subsref (type, idx);
69}
70
73 bool resize_ok)
74{
75 octave_value retval;
76 octave_idx_type nidx = idx.length ();
77 octave::idx_vector idx0, idx1;
78 if (nidx == 2)
79 {
80 int k = 0; // index we're processing when index_vector throws
81 try
82 {
83 idx0 = idx(0).index_vector ();
84 k = 1;
85 idx1 = idx(1).index_vector ();
86 }
87 catch (octave::index_exception& ie)
88 {
89 // Rethrow to allow more info to be reported later.
90 ie.set_pos_if_unset (2, k+1);
91 throw;
92 }
93 }
94
95 // This hack is to allow constructing permutation matrices using
96 // eye(n)(p,:), eye(n)(:,q) && eye(n)(p,q) where p & q are permutation
97 // vectors.
98 // Note that, for better consistency, eye(n)(:,:) still converts to a full
99 // matrix.
100 if (nidx == 2)
101 {
102 bool left = idx0.is_permutation (m_matrix.rows ());
103 bool right = idx1.is_permutation (m_matrix.cols ());
104
105 if (left && right)
106 {
107 if (idx0.is_colon ()) left = false;
108 if (idx1.is_colon ()) right = false;
109 if (left || right)
110 {
112 if (left)
113 p = PermMatrix (idx0, false) * p;
114 if (right)
115 p = p * PermMatrix (idx1, true);
116 retval = p;
117 }
118 else
119 {
120 retval = this;
121 this->m_count++;
122 }
123 }
124 }
125
126 if (! retval.is_defined ())
127 {
128 if (nidx == 2 && ! resize_ok && idx0.is_scalar () && idx1.is_scalar ())
129 retval = m_matrix.checkelem (idx0(0), idx1(0));
130 else
131 retval = to_dense ().index_op (idx, resize_ok);
132 }
133
134 return retval;
135}
136
137// Return true if this matrix has all true elements (nonzero, not NaN/NA).
138// A permutation cannot have NaN/NA.
139bool
141{
142 if (dims ().numel () > 1)
143 {
145 return false; // > 1x1 permutation always has zeros, and no NaN.
146 }
147 else
148 return dims ().numel (); // 1x1 is [1] == true, 0x0 == false.
149}
150
151double
153{
154 if (isempty ())
155 err_invalid_conversion (type_name (), "real scalar");
156
157 warn_implicit_conversion ("Octave:array-to-scalar",
158 type_name (), "real scalar");
159
160 return m_matrix(0, 0);
161}
162
163float
165{
166 if (isempty ())
167 err_invalid_conversion (type_name (), "real scalar");
168
169 warn_implicit_conversion ("Octave:array-to-scalar",
170 type_name (), "real scalar");
171
172 return m_matrix(0, 0);
173}
174
177{
178 if (rows () == 0 || columns () == 0)
179 err_invalid_conversion (type_name (), "complex scalar");
180
181 warn_implicit_conversion ("Octave:array-to-scalar",
182 type_name (), "complex scalar");
183
184 return Complex (m_matrix(0, 0), 0);
185}
186
189{
190 float tmp = lo_ieee_float_nan_value ();
191
192 FloatComplex retval (tmp, tmp);
193
194 if (rows () == 0 || columns () == 0)
195 err_invalid_conversion (type_name (), "complex scalar");
196
197 warn_implicit_conversion ("Octave:array-to-scalar",
198 type_name (), "complex scalar");
199
200 retval = m_matrix(0, 0);
201
202 return retval;
203}
204
205#define FORWARD_MATRIX_VALUE(TYPE, PREFIX) \
206 TYPE \
207 octave_perm_matrix::PREFIX ## _value (bool frc_str_conv) const \
208 { \
209 return to_dense ().PREFIX ## _value (frc_str_conv); \
210 }
211
217
223
229
234
239
242
243octave::idx_vector
244octave_perm_matrix::index_vector (bool require_integers) const
245{
246 return to_dense ().index_vector (require_integers);
247}
248
251 char type) const
252{
253 return to_dense ().convert_to_str_internal (pad, force, type);
254}
255
258{
259 return m_matrix;
260}
261
264{
265 return float_array_value ();
266}
267
270{
271 return int8_array_value ();
272}
273
276{
277 return int16_array_value ();
278}
279
282{
283 return int32_array_value ();
284}
285
288{
289 return int64_array_value ();
290}
291
294{
295 return uint8_array_value ();
296}
297
300{
301 return uint16_array_value ();
302}
303
306{
307 return uint32_array_value ();
308}
309
312{
313 return uint64_array_value ();
314}
315
321
322std::string
325 octave_idx_type j) const
326{
327 std::ostringstream buf;
329 return buf.str ();
330}
331
332bool
334{
335 os << "# size: " << m_matrix.rows () << "\n";
336 os << "# orient: c\n";
337
339 octave_idx_type n = pvec.numel ();
340 ColumnVector tmp (n);
341 for (octave_idx_type i = 0; i < n; i++) tmp(i) = pvec(i) + 1;
342 os << tmp;
343
344 return true;
345}
346
347bool
349{
351 char orient;
352
353 if (! extract_keyword (is, "size", n, true)
354 || ! extract_keyword (is, "orient", orient, true))
355 error ("load: failed to extract size & orientation");
356
357 bool colp = orient == 'c';
358 ColumnVector tmp (n);
359 is >> tmp;
360 if (! is)
361 error ("load: failed to load permutation matrix constant");
362
364 for (octave_idx_type i = 0; i < n; i++) pvec(i) = tmp(i) - 1;
365 m_matrix = PermMatrix (pvec, colp);
366
367 // Invalidate cache. Probably not necessary, but safe.
369
370 return true;
371}
372
373bool
374octave_perm_matrix::save_binary (std::ostream& os, bool)
375{
376
377 int32_t sz = m_matrix.rows ();
378 bool colp = true;
379 os.write (reinterpret_cast<char *> (&sz), 4);
380 os.write (reinterpret_cast<char *> (&colp), 1);
381 const Array<octave_idx_type>& col_perm = m_matrix.col_perm_vec ();
382 os.write (reinterpret_cast<const char *> (col_perm.data ()),
383 col_perm.byte_size ());
384
385 return true;
386}
387
388bool
389octave_perm_matrix::load_binary (std::istream& is, bool swap,
390 octave::mach_info::float_format)
391{
392 int32_t sz;
393 bool colp;
394 if (! (is.read (reinterpret_cast<char *> (&sz), 4)
395 && is.read (reinterpret_cast<char *> (&colp), 1)))
396 return false;
397
399
400 if (! is.read (reinterpret_cast<char *> (m.rwdata ()), m.byte_size ()))
401 return false;
402
403 if (swap)
404 {
405 int nel = m.numel ();
406 for (int i = 0; i < nel; i++)
407 switch (sizeof (octave_idx_type))
408 {
409 case 8:
410 swap_bytes<8> (&m(i));
411 break;
412 case 4:
413 swap_bytes<4> (&m(i));
414 break;
415 case 2:
416 swap_bytes<2> (&m(i));
417 break;
418 case 1:
419 default:
420 break;
421 }
422 }
423
424 m_matrix = PermMatrix (m, colp);
425 return true;
426}
427
428void
430 bool pr_as_read_syntax) const
431{
432 return octave_print_internal (os, m_matrix, pr_as_read_syntax,
434}
435
436mxArray *
437octave_perm_matrix::as_mxArray (bool interleaved) const
438{
439 return to_dense ().as_mxArray (interleaved);
440}
441
442bool
444{
445 const dim_vector& dv = dims ();
446
447 return (dv.all_ones () || dv.any_zero ());
448}
449
450void
451octave_perm_matrix::print (std::ostream& os, bool pr_as_read_syntax)
452{
453 print_raw (os, pr_as_read_syntax);
454 newline (os);
455}
456
457int
458octave_perm_matrix::write (octave::stream& os, int block_size,
459 oct_data_conv::data_type output_type, int skip,
460 octave::mach_info::float_format flt_fmt) const
461{
462 return to_dense ().write (os, block_size, output_type, skip, flt_fmt);
463}
464
465void
467 const std::string& prefix) const
468{
469 m_matrix.print_info (os, prefix);
470}
471
474{
475 if (! m_dense_cache.is_defined ())
477
478 return m_dense_cache;
479}
480
482 "permutation matrix", "double");
483
484static octave_base_value *
485default_numeric_conversion_function (const octave_base_value& a)
486{
487 const octave_perm_matrix& v = dynamic_cast<const octave_perm_matrix&> (a);
488
489 return new octave_matrix (v.matrix_value ());
490}
491
494{
495 return octave_base_value::type_conv_info (default_numeric_conversion_function,
497}
498
499// FIXME: This is duplicated from octave_base_matrix<T>. Could
500// octave_perm_matrix be derived from octave_base_matrix<T>?
501
502void
503octave_perm_matrix::short_disp (std::ostream& os) const
504{
505 if (m_matrix.isempty ())
506 os << "[]";
507 else if (m_matrix.ndims () == 2)
508 {
509 // FIXME: should this be configurable?
510 octave_idx_type max_elts = 10;
511 octave_idx_type elts = 0;
512
515
516 os << '[';
517
518 for (octave_idx_type i = 0; i < nr; i++)
519 {
520 for (octave_idx_type j = 0; j < nc; j++)
521 {
522 std::ostringstream buf;
524 octave_print_internal (buf, tval);
525 std::string tmp = buf.str ();
526 std::size_t pos = tmp.find_first_not_of (' ');
527 if (pos != std::string::npos)
528 os << tmp.substr (pos);
529 else if (! tmp.empty ())
530 os << tmp[0];
531 elts++;
532
533 if (j < nc - 1)
534 {
535 os << ", ";
536
537 if (elts >= max_elts)
538 {
539 os << "...";
540 goto done;
541 }
542 }
543 }
544
545 if (i < nr - 1)
546 {
547 os << "; ";
548
549 if (elts >= max_elts)
550 {
551 os << "...";
552 goto done;
553 }
554 }
555 }
556
557 done:
558 os << ']';
559 }
560 else
562}
563
566{
567 octave_base_value *retval = nullptr;
568
569 if (m_matrix.numel () == 1)
570 retval = new octave_scalar (m_matrix (0, 0));
571
572 return retval;
573}
574
577{
578 if (n < m_matrix.numel ())
579 {
581
582 octave_idx_type r = n % nr;
583 octave_idx_type c = n / nr;
584
585 return octave_value (m_matrix.elem (r, c));
586 }
587 else
588 return octave_value ();
589}
void swap_bytes< 2 >(void *ptr)
Definition byte-swap.h:56
void swap_bytes< 8 >(void *ptr)
Definition byte-swap.h:71
void swap_bytes< 4 >(void *ptr)
Definition byte-swap.h:63
N Dimensional Array with copy-on-write semantics.
Definition Array.h:130
std::size_t byte_size() const
Size of the specified dimension.
Definition Array.h:503
const T * data() const
Size of the specified dimension.
Definition Array.h:665
T * rwdata()
Size of the specified dimension.
octave_idx_type numel() const
Number of elements in the array.
Definition Array.h:418
Template for N-dimensional array classes with like-type math operators.
Definition MArray.h:61
bool isempty() const
Definition PermMatrix.h:79
octave_idx_type elem(octave_idx_type i, octave_idx_type j) const
Definition PermMatrix.h:87
octave_idx_type numel() const
Definition PermMatrix.h:72
octave_idx_type rows() const
Definition PermMatrix.h:62
void print_info(std::ostream &os, const std::string &prefix) const
Definition PermMatrix.h:114
octave_idx_type checkelem(octave_idx_type i, octave_idx_type j) const
Definition PermMatrix.cc:91
octave_idx_type cols() const
Definition PermMatrix.h:63
octave_idx_type columns() const
Definition PermMatrix.h:64
const Array< octave_idx_type > & col_perm_vec() const
Definition PermMatrix.h:83
int ndims() const
Definition PermMatrix.h:81
Vector representing the dimensions (size) of an Array.
Definition dim-vector.h:90
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition dim-vector.h:331
bool any_zero() const
Definition dim-vector.h:312
bool all_ones() const
Definition dim-vector.h:320
octave_idx_type rows() const
Definition ov-base.h:384
octave_idx_type columns() const
Definition ov-base.h:391
virtual void short_disp(std::ostream &os) const
Definition ov-base.h:761
virtual octave_idx_type numel() const
Definition ov-base.h:401
int current_print_indent_level() const
Definition ov-base.h:945
void newline(std::ostream &os) const
Definition ov-base.cc:1377
octave::refcount< octave_idx_type > m_count
Definition ov-base.h:958
bool isempty() const
Definition ov-base.h:429
friend class octave_value
Definition ov-base.h:278
static int static_type_id()
Definition ov-re-mat.h:249
uint16NDArray uint16_array_value() const
Definition ov-perm.h:198
octave_value convert_to_str_internal(bool pad, bool force, char type) const
Definition ov-perm.cc:250
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition ov-perm.cc:429
octave_value as_int16() const
Definition ov-perm.cc:275
std::string edit_display(const float_display_format &fmt, octave_idx_type i, octave_idx_type j) const
Definition ov-perm.cc:323
type_conv_info numeric_conversion_function() const
Definition ov-perm.cc:493
uint64NDArray uint64_array_value() const
Definition ov-perm.h:204
std::string type_name() const
Definition ov-perm.h:266
SparseMatrix sparse_matrix_value(bool=false) const
Definition ov-perm.cc:213
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition ov-perm.cc:45
octave_base_value * try_narrowing_conversion()
Definition ov-perm.cc:565
PermMatrix m_matrix
Definition ov-perm.h:258
void print(std::ostream &os, bool pr_as_read_syntax=false)
Definition ov-perm.cc:451
octave_value as_int64() const
Definition ov-perm.cc:287
void print_info(std::ostream &os, const std::string &prefix) const
Definition ov-perm.cc:466
bool save_binary(std::ostream &os, bool save_as_floats)
Definition ov-perm.cc:374
double double_value(bool=false) const
Definition ov-perm.cc:152
float_display_format get_edit_display_format() const
Definition ov-perm.cc:317
int8NDArray int8_array_value() const
Definition ov-perm.h:183
octave_value as_int8() const
Definition ov-perm.cc:269
FloatNDArray float_array_value(bool=false) const
Definition ov-perm.cc:236
bool print_as_scalar() const
Definition ov-perm.cc:443
dim_vector dims() const
Definition ov-perm.h:75
int32NDArray int32_array_value() const
Definition ov-perm.h:189
int64NDArray int64_array_value() const
Definition ov-perm.h:192
SparseBoolMatrix sparse_bool_matrix_value(bool=false) const
Definition ov-perm.cc:219
uint8NDArray uint8_array_value() const
Definition ov-perm.h:195
virtual octave_value to_dense() const
Definition ov-perm.cc:473
bool load_ascii(std::istream &is)
Definition ov-perm.cc:348
bool is_true() const
Definition ov-perm.cc:140
octave_value as_double() const
Definition ov-perm.cc:257
octave_value as_uint8() const
Definition ov-perm.cc:293
float float_value(bool=false) const
Definition ov-perm.cc:164
FloatComplex float_complex_value(bool=false) const
Definition ov-perm.cc:188
Complex complex_value(bool=false) const
Definition ov-perm.cc:176
octave_value fast_elem_extract(octave_idx_type n) const
Definition ov-perm.cc:576
int16NDArray int16_array_value() const
Definition ov-perm.h:186
uint32NDArray uint32_array_value() const
Definition ov-perm.h:201
SparseComplexMatrix sparse_complex_matrix_value(bool=false) const
Definition ov-perm.cc:225
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
Definition ov-perm.cc:72
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:458
octave::idx_vector index_vector(bool require_integers=false) const
Definition ov-perm.cc:244
bool save_ascii(std::ostream &os)
Definition ov-perm.cc:333
octave_value as_uint32() const
Definition ov-perm.cc:305
Matrix matrix_value(bool=false) const
Definition ov-perm.cc:230
octave_value as_uint64() const
Definition ov-perm.cc:311
octave_value as_single() const
Definition ov-perm.cc:263
octave_value as_uint16() const
Definition ov-perm.cc:299
bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
Definition ov-perm.cc:389
octave_value m_dense_cache
Definition ov-perm.h:262
mxArray * as_mxArray(bool interleaved) const
Definition ov-perm.cc:437
void short_disp(std::ostream &os) const
Definition ov-perm.cc:503
octave_value as_int32() const
Definition ov-perm.cc:281
octave_idx_type length() const
Definition ovl.h:111
octave_value convert_to_str_internal(bool pad, bool force, char type) const
Definition ov.h:1327
octave_value index_op(const octave_value_list &idx, bool resize_ok=false)
Definition ov.h:504
octave_value next_subsref(const std::string &type, const std::list< octave_value_list > &idx, std::size_t skip=1)
bool is_defined() const
Definition ov.h:592
mxArray * as_mxArray(bool interleaved=false) const
Definition ov.h:1422
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
void error(const char *fmt,...)
Definition error.cc:1003
void warn_array_as_logical(const dim_vector &dv)
Definition errwarn.cc:286
void err_invalid_conversion(const std::string &from, const std::string &to)
Definition errwarn.cc:71
void warn_implicit_conversion(const char *id, const char *from, const char *to)
Definition errwarn.cc:344
float lo_ieee_float_nan_value()
Definition lo-ieee.cc:116
std::string extract_keyword(std::istream &is, const char *keyword, const bool next_only)
std::complex< double > Complex
Definition oct-cmplx.h:33
std::complex< float > FloatComplex
Definition oct-cmplx.h:34
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition ov-base.h:246
#define FORWARD_MATRIX_VALUE(TYPE, PREFIX)
Definition ov-perm.cc:205
void octave_print_internal(std::ostream &os, const float_display_format &fmt, bool d, bool pr_as_read_syntax)