1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2021 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 <istream>
31 #include <limits>
32 #include <ostream>
33 
34 #include "lo-ieee.h"
35 #include "lo-mappers.h"
36 
37 #include "defun.h"
38 #include "errwarn.h"
39 #include "interpreter-private.h"
40 #include "interpreter.h"
41 #include "mxarray.h"
42 #include "oct-hdf5.h"
43 #include "oct-lvalue.h"
44 #include "oct-map.h"
45 #include "oct-stream.h"
46 #include "ops.h"
47 #include "ov-base.h"
48 #include "ov-cell.h"
49 #include "ov-ch-mat.h"
50 #include "ov-classdef.h"
51 #include "ov-complex.h"
52 #include "ov-cx-mat.h"
53 #include "ov-fcn-handle.h"
54 #include "ov-range.h"
55 #include "ov-re-mat.h"
56 #include "ov-scalar.h"
57 #include "ov-str-mat.h"
58 #include "ovl.h"
59 #include "parse.h"
60 #include "pr-flt-fmt.h"
61 #include "pr-output.h"
62 #include "utils.h"
63 #include "variables.h"
64 
btyp_mixed_numeric(builtin_type_t x,builtin_type_t y)65 builtin_type_t btyp_mixed_numeric (builtin_type_t x, builtin_type_t y)
66 {
67   builtin_type_t retval = btyp_unknown;
68 
69   if (x == btyp_bool)
70     x = btyp_double;
71   if (y == btyp_bool)
72     y = btyp_double;
73 
74   if (x <= btyp_float_complex && y <= btyp_float_complex)
75     retval = static_cast<builtin_type_t> (x | y);
76   else if (x <= btyp_uint64 && y <= btyp_float)
77     retval = x;
78   else if (x <= btyp_float && y <= btyp_uint64)
79     retval = y;
80   else if ((x >= btyp_int8 && x <= btyp_int64
81             && y >= btyp_int8 && y <= btyp_int64)
82            || (x >= btyp_uint8 && x <= btyp_uint64
83                && y >= btyp_uint8 && y <= btyp_uint64))
84     retval = (x > y) ? x : y;
85 
86   return retval;
87 }
88 
89 std::string btyp_class_name[btyp_num_types] =
90 {
91   "double", "single", "double", "single",
92   "int8", "int16", "int32", "int64",
93   "uint8", "uint16", "uint32", "uint64",
94   "logical", "char",
95   "struct", "cell", "function_handle"
96 };
97 
98 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_base_value,
99                                      "<unknown type>", "unknown");
100 
101 // TRUE means to perform automatic sparse to real mutation if there
102 // is memory to be saved
103 bool Vsparse_auto_mutate = false;
104 
105 octave_base_value *
empty_clone(void) const106 octave_base_value::empty_clone (void) const
107 {
108   return resize (dim_vector ()).clone ();
109 }
110 
111 octave_value
squeeze(void) const112 octave_base_value::squeeze (void) const
113 {
114   std::string nm = type_name ();
115   error ("squeeze: invalid operation for %s type", nm.c_str ());
116 }
117 
118 octave_value
full_value(void) const119 octave_base_value::full_value (void) const
120 {
121   err_wrong_type_arg ("full: invalid operation for %s type", type_name ());
122 }
123 
124 octave_value
as_double(void) const125 octave_base_value::as_double (void) const
126 {
127   err_invalid_conversion (type_name (), "double");
128 }
129 
130 octave_value
as_single(void) const131 octave_base_value::as_single (void) const
132 {
133   err_invalid_conversion (type_name (), "single");
134 }
135 
136 octave_value
as_int8(void) const137 octave_base_value::as_int8 (void) const
138 {
139   err_invalid_conversion (type_name (), "int8");
140 }
141 
142 octave_value
as_int16(void) const143 octave_base_value::as_int16 (void) const
144 {
145   err_invalid_conversion (type_name (), "int16");
146 }
147 
148 octave_value
as_int32(void) const149 octave_base_value::as_int32 (void) const
150 {
151   err_invalid_conversion (type_name (), "int32");
152 }
153 
154 octave_value
as_int64(void) const155 octave_base_value::as_int64 (void) const
156 {
157   err_invalid_conversion (type_name (), "int64");
158 }
159 
160 octave_value
as_uint8(void) const161 octave_base_value::as_uint8 (void) const
162 {
163   err_invalid_conversion (type_name (), "uint8");
164 }
165 
166 octave_value
as_uint16(void) const167 octave_base_value::as_uint16 (void) const
168 {
169   err_invalid_conversion (type_name (), "uint16");
170 }
171 
172 octave_value
as_uint32(void) const173 octave_base_value::as_uint32 (void) const
174 {
175   err_invalid_conversion (type_name (), "uint32");
176 }
177 
178 octave_value
as_uint64(void) const179 octave_base_value::as_uint64 (void) const
180 {
181   err_invalid_conversion (type_name (), "uint64");
182 }
183 
184 Matrix
size(void)185 octave_base_value::size (void)
186 {
187   const dim_vector dv = dims ();
188   Matrix mdv (1, dv.ndims ());
189   for (octave_idx_type i = 0; i < dv.ndims (); i++)
190     mdv(i) = dv(i);
191   return mdv;
192 }
193 
194 octave_idx_type
xnumel(const octave_value_list & idx)195 octave_base_value::xnumel (const octave_value_list& idx)
196 {
197   return octave::dims_to_numel (dims (), idx);
198 }
199 
200 octave_value
subsref(const std::string &,const std::list<octave_value_list> &)201 octave_base_value::subsref (const std::string&,
202                             const std::list<octave_value_list>&)
203 {
204   std::string nm = type_name ();
205   error ("can't perform indexing operations for %s type", nm.c_str ());
206 }
207 
208 octave_value_list
subsref(const std::string &,const std::list<octave_value_list> &,int)209 octave_base_value::subsref (const std::string&,
210                             const std::list<octave_value_list>&, int)
211 {
212   std::string nm = type_name ();
213   error ("can't perform indexing operations for %s type", nm.c_str ());
214 }
215 
216 octave_value
subsref(const std::string & type,const std::list<octave_value_list> & idx,bool)217 octave_base_value::subsref (const std::string& type,
218                             const std::list<octave_value_list>& idx,
219                             bool /* auto_add */)
220 {
221   // This way we may get a more meaningful error message.
222   return subsref (type, idx);
223 }
224 
225 octave_value
do_index_op(const octave_value_list &,bool)226 octave_base_value::do_index_op (const octave_value_list&, bool)
227 {
228   std::string nm = type_name ();
229   error ("can't perform indexing operations for %s type", nm.c_str ());
230 }
231 
232 idx_vector
index_vector(bool) const233 octave_base_value::index_vector (bool /* require_integers */) const
234 {
235   std::string nm = '<' + type_name () + '>';
236   octave::err_invalid_index (nm.c_str ());
237 }
238 
239 octave_value
subsasgn(const std::string & type,const std::list<octave_value_list> & idx,const octave_value & rhs)240 octave_base_value::subsasgn (const std::string& type,
241                              const std::list<octave_value_list>& idx,
242                              const octave_value& rhs)
243 {
244   octave_value retval;
245 
246   if (is_defined ())
247     {
248       if (! isnumeric ())
249         {
250           std::string nm = type_name ();
251           error ("can't perform indexed assignment for %s type", nm.c_str ());
252         }
253 
254       switch (type[0])
255         {
256         case '(':
257           {
258             if (type.length () == 1)
259               retval = numeric_assign (type, idx, rhs);
260             else if (isempty ())
261               {
262                 // Allow conversion of empty matrix to some other
263                 // type in cases like
264                 //
265                 //  x = []; x(i).f = rhs
266 
267                 octave_value tmp = octave_value::empty_conv (type, rhs);
268 
269                 retval = tmp.subsasgn (type, idx, rhs);
270               }
271             else
272               {
273                 std::string nm = type_name ();
274                 error ("in indexed assignment of %s, last rhs index must be ()",
275                        nm.c_str ());
276               }
277           }
278           break;
279 
280         case '{':
281         case '.':
282           {
283             std::string nm = type_name ();
284             error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
285           }
286           break;
287 
288         default:
289           panic_impossible ();
290         }
291     }
292   else
293     {
294       // Create new object of appropriate type for given index and rhs
295       // types and then call undef_subsasgn for that object.
296 
297       octave_value tmp = octave_value::empty_conv (type, rhs);
298 
299       retval = tmp.undef_subsasgn (type, idx, rhs);
300     }
301 
302   return retval;
303 }
304 
305 octave_value
undef_subsasgn(const std::string & type,const std::list<octave_value_list> & idx,const octave_value & rhs)306 octave_base_value::undef_subsasgn (const std::string& type,
307                                    const std::list<octave_value_list>& idx,
308                                    const octave_value& rhs)
309 {
310   // In most cases, undef_subsasgn is handled the sams as subsasgn.  One
311   // exception is octave_class objects.
312 
313   return subsasgn (type, idx, rhs);
314 }
315 
316 octave_idx_type
nnz(void) const317 octave_base_value::nnz (void) const
318 {
319   err_wrong_type_arg ("octave_base_value::nnz ()", type_name ());
320 }
321 
322 octave_idx_type
nzmax(void) const323 octave_base_value::nzmax (void) const
324 {
325   return numel ();
326 }
327 
328 octave_idx_type
nfields(void) const329 octave_base_value::nfields (void) const
330 {
331   err_wrong_type_arg ("octave_base_value::nfields ()", type_name ());
332 }
333 
334 octave_value
reshape(const dim_vector &) const335 octave_base_value::reshape (const dim_vector&) const
336 {
337   err_wrong_type_arg ("octave_base_value::reshape ()", type_name ());
338 }
339 
340 octave_value
permute(const Array<int> &,bool) const341 octave_base_value::permute (const Array<int>&, bool) const
342 {
343   err_wrong_type_arg ("octave_base_value::permute ()", type_name ());
344 }
345 
346 octave_value
resize(const dim_vector &,bool) const347 octave_base_value::resize (const dim_vector&, bool) const
348 {
349   err_wrong_type_arg ("octave_base_value::resize ()", type_name ());
350 }
351 
352 MatrixType
matrix_type(void) const353 octave_base_value::matrix_type (void) const
354 {
355   err_wrong_type_arg ("octave_base_value::matrix_type ()", type_name ());
356 }
357 
358 MatrixType
matrix_type(const MatrixType &) const359 octave_base_value::matrix_type (const MatrixType&) const
360 {
361   err_wrong_type_arg ("octave_base_value::matrix_type ()", type_name ());
362 }
363 
364 octave_value
all(int) const365 octave_base_value::all (int) const
366 {
367   return 0.0;
368 }
369 
370 octave_value
any(int) const371 octave_base_value::any (int) const
372 {
373   return 0.0;
374 }
375 
376 octave_value
convert_to_str(bool pad,bool force,char type) const377 octave_base_value::convert_to_str (bool pad, bool force, char type) const
378 {
379   octave_value retval = convert_to_str_internal (pad, force, type);
380 
381   if (! force && isnumeric ())
382     warn_implicit_conversion ("Octave:num-to-str",
383                               type_name (), retval.type_name ());
384 
385   return retval;
386 }
387 
388 octave_value
convert_to_str_internal(bool,bool,char) const389 octave_base_value::convert_to_str_internal (bool, bool, char) const
390 {
391   err_wrong_type_arg ("octave_base_value::convert_to_str_internal ()",
392                       type_name ());
393 }
394 
395 void
convert_to_row_or_column_vector(void)396 octave_base_value::convert_to_row_or_column_vector (void)
397 {
398   err_wrong_type_arg
399     ("octave_base_value::convert_to_row_or_column_vector ()", type_name ());
400 }
401 
402 void
print(std::ostream &,bool)403 octave_base_value::print (std::ostream&, bool)
404 {
405   err_wrong_type_arg ("octave_base_value::print ()", type_name ());
406 }
407 
408 void
print_raw(std::ostream &,bool) const409 octave_base_value::print_raw (std::ostream&, bool) const
410 {
411   err_wrong_type_arg ("octave_base_value::print_raw ()", type_name ());
412 }
413 
414 bool
print_name_tag(std::ostream & os,const std::string & name) const415 octave_base_value::print_name_tag (std::ostream& os,
416                                    const std::string& name) const
417 {
418   indent (os);
419 
420   if (print_as_scalar ())
421     os << name << " = ";
422   else
423     {
424       os << name << " =";
425       newline (os);
426       if (! Vcompact_format)
427         newline (os);
428 
429       return true;
430     }
431 
432   return false;
433 }
434 
435 void
print_with_name(std::ostream & output_buf,const std::string & name,bool print_padding)436 octave_base_value::print_with_name (std::ostream& output_buf,
437                                     const std::string& name,
438                                     bool print_padding)
439 {
440   bool pad_after = print_name_tag (output_buf, name);
441 
442   print (output_buf);
443 
444   if (print_padding && pad_after && ! Vcompact_format)
445     newline (output_buf);
446 }
447 
448 float_display_format
get_edit_display_format(void) const449 octave_base_value::get_edit_display_format (void) const
450 {
451   return float_display_format ();
452 }
453 
454 void
print_info(std::ostream & os,const std::string &) const455 octave_base_value::print_info (std::ostream& os,
456                                const std::string& /* prefix */) const
457 {
458   os << "no info for type: " << type_name () << "\n";
459 }
460 
461 #define INT_CONV_METHOD(T, F)                                           \
462   T                                                                     \
463   octave_base_value::F ## _value (bool require_int, bool frc_str_conv) const \
464   {                                                                     \
465     T retval = 0;                                                       \
466                                                                         \
467     double d = 0.0;                                                     \
468                                                                         \
469     try                                                                 \
470       {                                                                 \
471         d = double_value (frc_str_conv);                                \
472       }                                                                 \
473     catch (octave::execution_exception& e)                               \
474       {                                                                 \
475         err_wrong_type_arg (e, "octave_base_value::" #F "_value ()", type_name ()); \
476       }                                                                 \
477                                                                         \
478     if (require_int && octave::math::x_nint (d) != d)                   \
479       error_with_cfn ("conversion of %g to " #T " value failed", d);    \
480     else if (d < std::numeric_limits<T>::min ())                        \
481       retval = std::numeric_limits<T>::min ();                          \
482     else if (d > std::numeric_limits<T>::max ())                        \
483       retval = std::numeric_limits<T>::max ();                          \
484     else                                                                \
485       retval = static_cast<T> (octave::math::fix (d));                  \
486                                                                         \
487     return retval;                                                      \
488   }
489 
INT_CONV_METHOD(short int,short)490 INT_CONV_METHOD (short int, short)
491 INT_CONV_METHOD (unsigned short int, ushort)
492 
493 INT_CONV_METHOD (int, int)
494 INT_CONV_METHOD (unsigned int, uint)
495 
496 INT_CONV_METHOD (long int, long)
497 INT_CONV_METHOD (unsigned long int, ulong)
498 
499 INT_CONV_METHOD (int64_t, int64)
500 INT_CONV_METHOD (uint64_t, uint64)
501 
502 int
503 octave_base_value::nint_value (bool frc_str_conv) const
504 {
505   double d = 0.0;
506 
507   try
508     {
509       d = double_value (frc_str_conv);
510     }
511   catch (octave::execution_exception& e)
512     {
513       err_wrong_type_arg (e, "octave_base_value::nint_value ()", type_name ());
514     }
515 
516   if (octave::math::isnan (d))
517     error ("conversion of NaN to integer value failed");
518 
519   return static_cast<int> (octave::math::fix (d));
520 }
521 
522 double
double_value(bool) const523 octave_base_value::double_value (bool) const
524 {
525   err_wrong_type_arg ("octave_base_value::double_value ()", type_name ());
526 }
527 
528 float
float_value(bool) const529 octave_base_value::float_value (bool) const
530 {
531   err_wrong_type_arg ("octave_base_value::float_value ()", type_name ());
532 }
533 
534 Cell
cell_value() const535 octave_base_value::cell_value () const
536 {
537   err_wrong_type_arg ("octave_base_value::cell_value()", type_name ());
538 }
539 
540 Matrix
matrix_value(bool) const541 octave_base_value::matrix_value (bool) const
542 {
543   err_wrong_type_arg ("octave_base_value::matrix_value()", type_name ());
544 }
545 
546 FloatMatrix
float_matrix_value(bool) const547 octave_base_value::float_matrix_value (bool) const
548 {
549   err_wrong_type_arg ("octave_base_value::float_matrix_value()", type_name ());
550 }
551 
552 NDArray
array_value(bool) const553 octave_base_value::array_value (bool) const
554 {
555   err_wrong_type_arg ("octave_base_value::array_value()", type_name ());
556 }
557 
558 FloatNDArray
float_array_value(bool) const559 octave_base_value::float_array_value (bool) const
560 {
561   err_wrong_type_arg ("octave_base_value::float_array_value()", type_name ());
562 }
563 
564 Complex
complex_value(bool) const565 octave_base_value::complex_value (bool) const
566 {
567   err_wrong_type_arg ("octave_base_value::complex_value()", type_name ());
568 }
569 
570 FloatComplex
float_complex_value(bool) const571 octave_base_value::float_complex_value (bool) const
572 {
573   err_wrong_type_arg ("octave_base_value::float_complex_value()", type_name ());
574 }
575 
576 ComplexMatrix
complex_matrix_value(bool) const577 octave_base_value::complex_matrix_value (bool) const
578 {
579   err_wrong_type_arg ("octave_base_value::complex_matrix_value()",
580                       type_name ());
581 }
582 
583 FloatComplexMatrix
float_complex_matrix_value(bool) const584 octave_base_value::float_complex_matrix_value (bool) const
585 {
586   err_wrong_type_arg ("octave_base_value::float_complex_matrix_value()",
587                       type_name ());
588 }
589 
590 ComplexNDArray
complex_array_value(bool) const591 octave_base_value::complex_array_value (bool) const
592 {
593   err_wrong_type_arg ("octave_base_value::complex_array_value()", type_name ());
594 }
595 
596 FloatComplexNDArray
float_complex_array_value(bool) const597 octave_base_value::float_complex_array_value (bool) const
598 {
599   err_wrong_type_arg ("octave_base_value::float_complex_array_value()",
600                       type_name ());
601 }
602 
603 bool
bool_value(bool) const604 octave_base_value::bool_value (bool) const
605 {
606   err_wrong_type_arg ("octave_base_value::bool_value()", type_name ());
607 }
608 
609 boolMatrix
bool_matrix_value(bool) const610 octave_base_value::bool_matrix_value (bool) const
611 {
612   err_wrong_type_arg ("octave_base_value::bool_matrix_value()", type_name ());
613 }
614 
615 boolNDArray
bool_array_value(bool) const616 octave_base_value::bool_array_value (bool) const
617 {
618   err_wrong_type_arg ("octave_base_value::bool_array_value()", type_name ());
619 }
620 
621 charMatrix
char_matrix_value(bool force) const622 octave_base_value::char_matrix_value (bool force) const
623 {
624   octave_value tmp = convert_to_str (false, force);
625 
626   return tmp.char_matrix_value ();
627 }
628 
629 charNDArray
char_array_value(bool) const630 octave_base_value::char_array_value (bool) const
631 {
632   err_wrong_type_arg ("octave_base_value::char_array_value()", type_name ());
633 }
634 
635 SparseMatrix
sparse_matrix_value(bool) const636 octave_base_value::sparse_matrix_value (bool) const
637 {
638   err_wrong_type_arg ("octave_base_value::sparse_matrix_value()", type_name ());
639 }
640 
641 SparseComplexMatrix
sparse_complex_matrix_value(bool) const642 octave_base_value::sparse_complex_matrix_value (bool) const
643 {
644   err_wrong_type_arg ("octave_base_value::sparse_complex_matrix_value()",
645                       type_name ());
646 }
647 
648 SparseBoolMatrix
sparse_bool_matrix_value(bool) const649 octave_base_value::sparse_bool_matrix_value (bool) const
650 {
651   err_wrong_type_arg ("octave_base_value::sparse_bool_matrix_value()",
652                       type_name ());
653 }
654 
655 DiagMatrix
diag_matrix_value(bool) const656 octave_base_value::diag_matrix_value (bool) const
657 {
658   err_wrong_type_arg ("octave_base_value::diag_matrix_value()", type_name ());
659 }
660 
661 FloatDiagMatrix
float_diag_matrix_value(bool) const662 octave_base_value::float_diag_matrix_value (bool) const
663 {
664   err_wrong_type_arg ("octave_base_value::float_diag_matrix_value()",
665                       type_name ());
666 }
667 
668 ComplexDiagMatrix
complex_diag_matrix_value(bool) const669 octave_base_value::complex_diag_matrix_value (bool) const
670 {
671   err_wrong_type_arg ("octave_base_value::complex_diag_matrix_value()",
672                       type_name ());
673 }
674 
675 FloatComplexDiagMatrix
float_complex_diag_matrix_value(bool) const676 octave_base_value::float_complex_diag_matrix_value (bool) const
677 {
678   err_wrong_type_arg ("octave_base_value::float_complex_diag_matrix_value()",
679                       type_name ());
680 }
681 
682 PermMatrix
perm_matrix_value(void) const683 octave_base_value::perm_matrix_value (void) const
684 {
685   err_wrong_type_arg ("octave_base_value::perm_matrix_value()", type_name ());
686 }
687 
688 octave_int8
int8_scalar_value(void) const689 octave_base_value::int8_scalar_value (void) const
690 {
691   err_wrong_type_arg ("octave_base_value::int8_scalar_value()", type_name ());
692 }
693 
694 octave_int16
int16_scalar_value(void) const695 octave_base_value::int16_scalar_value (void) const
696 {
697   err_wrong_type_arg ("octave_base_value::int16_scalar_value()", type_name ());
698 }
699 
700 octave_int32
int32_scalar_value(void) const701 octave_base_value::int32_scalar_value (void) const
702 {
703   err_wrong_type_arg ("octave_base_value::int32_scalar_value()", type_name ());
704 }
705 
706 octave_int64
int64_scalar_value(void) const707 octave_base_value::int64_scalar_value (void) const
708 {
709   err_wrong_type_arg ("octave_base_value::int64_scalar_value()", type_name ());
710 }
711 
712 octave_uint8
uint8_scalar_value(void) const713 octave_base_value::uint8_scalar_value (void) const
714 {
715   err_wrong_type_arg ("octave_base_value::uint8_scalar_value()", type_name ());
716 }
717 
718 octave_uint16
uint16_scalar_value(void) const719 octave_base_value::uint16_scalar_value (void) const
720 {
721   err_wrong_type_arg ("octave_base_value::uint16_scalar_value()", type_name ());
722 }
723 
724 octave_uint32
uint32_scalar_value(void) const725 octave_base_value::uint32_scalar_value (void) const
726 {
727   err_wrong_type_arg ("octave_base_value::uint32_scalar_value()", type_name ());
728 }
729 
730 octave_uint64
uint64_scalar_value(void) const731 octave_base_value::uint64_scalar_value (void) const
732 {
733   err_wrong_type_arg ("octave_base_value::uint64_scalar_value()", type_name ());
734 }
735 
736 int8NDArray
int8_array_value(void) const737 octave_base_value::int8_array_value (void) const
738 {
739   err_wrong_type_arg ("octave_base_value::int8_array_value()", type_name ());
740 }
741 
742 int16NDArray
int16_array_value(void) const743 octave_base_value::int16_array_value (void) const
744 {
745   err_wrong_type_arg ("octave_base_value::int16_array_value()", type_name ());
746 }
747 
748 int32NDArray
int32_array_value(void) const749 octave_base_value::int32_array_value (void) const
750 {
751   err_wrong_type_arg ("octave_base_value::int32_array_value()", type_name ());
752 }
753 
754 int64NDArray
int64_array_value(void) const755 octave_base_value::int64_array_value (void) const
756 {
757   err_wrong_type_arg ("octave_base_value::int64_array_value()", type_name ());
758 }
759 
760 uint8NDArray
uint8_array_value(void) const761 octave_base_value::uint8_array_value (void) const
762 {
763   err_wrong_type_arg ("octave_base_value::uint8_array_value()", type_name ());
764 }
765 
766 uint16NDArray
uint16_array_value(void) const767 octave_base_value::uint16_array_value (void) const
768 {
769   err_wrong_type_arg ("octave_base_value::uint16_array_value()", type_name ());
770 }
771 
772 uint32NDArray
uint32_array_value(void) const773 octave_base_value::uint32_array_value (void) const
774 {
775   err_wrong_type_arg ("octave_base_value::uint32_array_value()", type_name ());
776 }
777 
778 uint64NDArray
uint64_array_value(void) const779 octave_base_value::uint64_array_value (void) const
780 {
781   err_wrong_type_arg ("octave_base_value::uint64_array_value()", type_name ());
782 }
783 
784 string_vector
string_vector_value(bool pad) const785 octave_base_value::string_vector_value (bool pad) const
786 {
787   octave_value tmp = convert_to_str (pad, true);
788 
789   return tmp.string_vector_value ();
790 }
791 
792 std::string
string_value(bool force) const793 octave_base_value::string_value (bool force) const
794 {
795   octave_value tmp = convert_to_str (force);
796 
797   return tmp.string_value ();
798 }
799 
800 std::string
xstring_value(void) const801 octave_base_value::xstring_value (void) const
802 {
803   wrong_type_arg_error ();
804 
805   return std::string ();
806 }
807 
808 Array<std::string>
cellstr_value(void) const809 octave_base_value::cellstr_value (void) const
810 {
811   err_wrong_type_arg ("octave_base_value::cellstr_value()", type_name ());
812 }
813 
814 Range
range_value(void) const815 octave_base_value::range_value (void) const
816 {
817   err_wrong_type_arg ("octave_base_value::range_value()", type_name ());
818 }
819 
820 octave_map
map_value(void) const821 octave_base_value::map_value (void) const
822 {
823   err_wrong_type_arg ("octave_base_value::map_value()", type_name ());
824 }
825 
826 octave_scalar_map
scalar_map_value(void) const827 octave_base_value::scalar_map_value (void) const
828 {
829   octave_map tmp = map_value ();
830 
831   if (tmp.numel () != 1)
832     error ("invalid conversion of multi-dimensional struct to scalar struct");
833 
834   return octave_scalar_map (tmp.checkelem (0));
835 }
836 
837 string_vector
map_keys(void) const838 octave_base_value::map_keys (void) const
839 {
840   err_wrong_type_arg ("octave_base_value::map_keys()", type_name ());
841 }
842 
843 std::size_t
nparents(void) const844 octave_base_value::nparents (void) const
845 {
846   err_wrong_type_arg ("octave_base_value::nparents()", type_name ());
847 }
848 
849 std::list<std::string>
parent_class_name_list(void) const850 octave_base_value::parent_class_name_list (void) const
851 {
852   err_wrong_type_arg ("octave_base_value::parent_class_name_list()",
853                       type_name ());
854 }
855 
856 string_vector
parent_class_names(void) const857 octave_base_value::parent_class_names (void) const
858 {
859   err_wrong_type_arg ("octave_base_value::parent_class_names()", type_name ());
860 }
861 
862 octave_classdef *
classdef_object_value(bool silent)863 octave_base_value::classdef_object_value (bool silent)
864 {
865   if (! silent)
866     err_wrong_type_arg ("octave_base_value::classdef_object_value()",
867                         type_name ());
868 
869   return nullptr;
870 }
871 
872 octave_function *
function_value(bool silent)873 octave_base_value::function_value (bool silent)
874 {
875   if (! silent)
876     err_wrong_type_arg ("octave_base_value::function_value()", type_name ());
877 
878   return nullptr;
879 }
880 
881 octave_user_function *
user_function_value(bool silent)882 octave_base_value::user_function_value (bool silent)
883 {
884   if (! silent)
885     err_wrong_type_arg ("octave_base_value::user_function_value()",
886                         type_name ());
887   return nullptr;
888 }
889 
890 octave_user_script *
user_script_value(bool silent)891 octave_base_value::user_script_value (bool silent)
892 {
893   if (! silent)
894     err_wrong_type_arg ("octave_base_value::user_script_value()", type_name ());
895 
896   return nullptr;
897 }
898 
899 octave_user_code *
user_code_value(bool silent)900 octave_base_value::user_code_value (bool silent)
901 {
902   if (! silent)
903     err_wrong_type_arg ("octave_base_value::user_code_value()", type_name ());
904 
905   return nullptr;
906 }
907 
908 octave_fcn_handle *
fcn_handle_value(bool silent)909 octave_base_value::fcn_handle_value (bool silent)
910 {
911   if (! silent)
912     err_wrong_type_arg ("octave_base_value::fcn_handle_value()", type_name ());
913 
914   return nullptr;
915 }
916 
917 octave_value_list
list_value(void) const918 octave_base_value::list_value (void) const
919 {
920   err_wrong_type_arg ("octave_base_value::list_value()", type_name ());
921 }
922 
923 bool
save_ascii(std::ostream &)924 octave_base_value::save_ascii (std::ostream&)
925 {
926   err_wrong_type_arg ("octave_base_value::save_ascii()", type_name ());
927 }
928 
929 bool
load_ascii(std::istream &)930 octave_base_value::load_ascii (std::istream&)
931 {
932   err_wrong_type_arg ("octave_base_value::load_ascii()", type_name ());
933 }
934 
935 bool
save_binary(std::ostream &,bool)936 octave_base_value::save_binary (std::ostream&, bool)
937 {
938   err_wrong_type_arg ("octave_base_value::save_binary()", type_name ());
939 }
940 
941 bool
load_binary(std::istream &,bool,octave::mach_info::float_format)942 octave_base_value::load_binary (std::istream&, bool,
943                                 octave::mach_info::float_format)
944 {
945   err_wrong_type_arg ("octave_base_value::load_binary()", type_name ());
946 }
947 
948 bool
save_hdf5(octave_hdf5_id,const char *,bool)949 octave_base_value::save_hdf5 (octave_hdf5_id, const char *, bool)
950 {
951   err_wrong_type_arg ("octave_base_value::save_binary()", type_name ());
952 }
953 
954 bool
load_hdf5(octave_hdf5_id,const char *)955 octave_base_value::load_hdf5 (octave_hdf5_id, const char *)
956 {
957   err_wrong_type_arg ("octave_base_value::load_binary()", type_name ());
958 }
959 
960 int
write(octave::stream &,int,oct_data_conv::data_type,int,octave::mach_info::float_format) const961 octave_base_value::write (octave::stream&, int, oct_data_conv::data_type,
962                           int, octave::mach_info::float_format) const
963 {
964   err_wrong_type_arg ("octave_base_value::write()", type_name ());
965 }
966 
967 mxArray *
as_mxArray(void) const968 octave_base_value::as_mxArray (void) const
969 {
970   return nullptr;
971 }
972 
973 octave_value
diag(octave_idx_type) const974 octave_base_value::diag (octave_idx_type) const
975 {
976   err_wrong_type_arg ("octave_base_value::diag ()", type_name ());
977 }
978 
979 octave_value
diag(octave_idx_type,octave_idx_type) const980 octave_base_value::diag (octave_idx_type, octave_idx_type) const
981 {
982   err_wrong_type_arg ("octave_base_value::diag ()", type_name ());
983 }
984 
985 octave_value
sort(octave_idx_type,sortmode) const986 octave_base_value::sort (octave_idx_type, sortmode) const
987 {
988   err_wrong_type_arg ("octave_base_value::sort ()", type_name ());
989 }
990 
991 octave_value
sort(Array<octave_idx_type> &,octave_idx_type,sortmode) const992 octave_base_value::sort (Array<octave_idx_type> &,
993                          octave_idx_type, sortmode) const
994 {
995   err_wrong_type_arg ("octave_base_value::sort ()", type_name ());
996 }
997 
998 sortmode
issorted(sortmode) const999 octave_base_value::issorted (sortmode) const
1000 {
1001   err_wrong_type_arg ("octave_base_value::issorted ()", type_name ());
1002 }
1003 
1004 Array<octave_idx_type>
sort_rows_idx(sortmode) const1005 octave_base_value::sort_rows_idx (sortmode) const
1006 {
1007   err_wrong_type_arg ("octave_base_value::sort_rows_idx ()", type_name ());
1008 }
1009 
1010 sortmode
is_sorted_rows(sortmode) const1011 octave_base_value::is_sorted_rows (sortmode) const
1012 {
1013   err_wrong_type_arg ("octave_base_value::is_sorted_rows ()", type_name ());
1014 }
1015 
1016 const char *
get_umap_name(unary_mapper_t umap)1017 octave_base_value::get_umap_name (unary_mapper_t umap)
1018 {
1019   static const char *names[num_unary_mappers] =
1020   {
1021     "abs",
1022     "acos",
1023     "acosh",
1024     "angle",
1025     "arg",
1026     "asin",
1027     "asinh",
1028     "atan",
1029     "atanh",
1030     "cbrt",
1031     "ceil",
1032     "conj",
1033     "cos",
1034     "cosh",
1035     "erf",
1036     "erfinv",
1037     "erfcinv",
1038     "erfc",
1039     "erfcx",
1040     "erfi",
1041     "dawson",
1042     "exp",
1043     "expm1",
1044     "isfinite",
1045     "fix",
1046     "floor",
1047     "gamma",
1048     "imag",
1049     "isinf",
1050     "isna",
1051     "isnan",
1052     "lgamma",
1053     "log",
1054     "log2",
1055     "log10",
1056     "log1p",
1057     "real",
1058     "round",
1059     "roundb",
1060     "signum",
1061     "sin",
1062     "sinh",
1063     "sqrt",
1064     "tan",
1065     "tanh",
1066     "isalnum",
1067     "isalpha",
1068     "isascii",
1069     "iscntrl",
1070     "isdigit",
1071     "isgraph",
1072     "islower",
1073     "isprint",
1074     "ispunct",
1075     "isspace",
1076     "isupper",
1077     "isxdigit",
1078     "signbit",
1079     "tolower",
1080     "toupper"
1081   };
1082 
1083   if (umap < 0 || umap >= num_unary_mappers)
1084     return "unknown";
1085   else
1086     return names[umap];
1087 }
1088 
1089 void
warn_load(const char * type) const1090 octave_base_value::warn_load (const char *type) const
1091 {
1092   warning_with_id
1093     ("Octave:load-save-unavailable",
1094      "%s: loading %s files not available in this version of Octave",
1095      t_name.c_str (), type);
1096 }
1097 
1098 void
warn_save(const char * type) const1099 octave_base_value::warn_save (const char *type) const
1100 {
1101   warning_with_id
1102     ("Octave:load-save-unavailable",
1103      "%s: saving %s files not available in this version of Octave",
1104      t_name.c_str (), type);
1105 }
1106 
1107 void
wrong_type_arg_error(void) const1108 octave_base_value::wrong_type_arg_error (void) const
1109 {
1110   err_wrong_type_arg (type_name ());
1111 }
1112 
1113 octave_value
map(unary_mapper_t umap) const1114 octave_base_value::map (unary_mapper_t umap) const
1115 {
1116   error ("%s: not defined for %s", get_umap_name (umap), type_name ().c_str ());
1117 }
1118 
1119 void
lock(void)1120 octave_base_value::lock (void)
1121 {
1122   err_wrong_type_arg ("octave_base_value::lock ()", type_name ());
1123 }
1124 
1125 void
unlock(void)1126 octave_base_value::unlock (void)
1127 {
1128   err_wrong_type_arg ("octave_base_value::unlock ()", type_name ());
1129 }
1130 
1131 octave_value
dump(void) const1132 octave_base_value::dump (void) const
1133 {
1134   std::map<std::string, octave_value> m
1135     = {{ "class", this->class_name () },
1136        { "type", this->type_name () },
1137        { "dims", this->dims().as_array () }};
1138 
1139   return octave_value (m);
1140 }
1141 
1142 OCTAVE_NORETURN static
1143 void
err_indexed_assignment(const std::string & tn1,const std::string & tn2)1144 err_indexed_assignment (const std::string& tn1, const std::string& tn2)
1145 {
1146   error ("assignment of '%s' to indexed '%s' not implemented",
1147          tn2.c_str (), tn1.c_str ());
1148 }
1149 
1150 OCTAVE_NORETURN static
1151 void
err_assign_conversion_failed(const std::string & tn1,const std::string & tn2)1152 err_assign_conversion_failed (const std::string& tn1, const std::string& tn2)
1153 {
1154   error ("type conversion for assignment of '%s' to indexed '%s' failed",
1155          tn2.c_str (), tn1.c_str ());
1156 }
1157 
1158 OCTAVE_NORETURN static
1159 void
err_no_conversion(const std::string & on,const std::string & tn1,const std::string & tn2)1160 err_no_conversion (const std::string& on, const std::string& tn1,
1161                    const std::string& tn2)
1162 {
1163   error ("operator %s: no conversion for assignment of '%s' to indexed '%s'",
1164          on.c_str (), tn2.c_str (), tn1.c_str ());
1165 }
1166 
1167 octave_value
numeric_assign(const std::string & type,const std::list<octave_value_list> & idx,const octave_value & rhs)1168 octave_base_value::numeric_assign (const std::string& type,
1169                                    const std::list<octave_value_list>& idx,
1170                                    const octave_value& rhs)
1171 {
1172   octave_value retval;
1173 
1174   if (idx.front ().empty ())
1175     error ("missing index in indexed assignment");
1176 
1177   int t_lhs = type_id ();
1178   int t_rhs = rhs.type_id ();
1179 
1180   octave::type_info& ti
1181     = octave::__get_type_info__ ("octave_base_value::numeric_assign");
1182 
1183   octave::type_info::assign_op_fcn f
1184     = ti.lookup_assign_op (octave_value::op_asn_eq, t_lhs, t_rhs);
1185 
1186   bool done = false;
1187 
1188   if (f)
1189     {
1190       f (*this, idx.front (), rhs.get_rep ());
1191 
1192       done = true;
1193     }
1194 
1195   if (done)
1196     {
1197       count++;
1198       retval = octave_value (this);
1199     }
1200   else
1201     {
1202       int t_result = ti.lookup_pref_assign_conv (t_lhs, t_rhs);
1203 
1204       if (t_result >= 0)
1205         {
1206           octave_base_value::type_conv_fcn cf
1207             = ti.lookup_widening_op (t_lhs, t_result);
1208 
1209           if (! cf)
1210             err_indexed_assignment (type_name (), rhs.type_name ());
1211 
1212           octave_base_value *tmp = cf (*this);
1213 
1214           if (! tmp)
1215             err_assign_conversion_failed (type_name (), rhs.type_name ());
1216 
1217           octave_value val (tmp);
1218 
1219           retval = val.subsasgn (type, idx, rhs);
1220 
1221           done = true;
1222         }
1223 
1224       if (! done)
1225         {
1226           octave_value tmp_rhs;
1227 
1228           octave_base_value::type_conv_info cf_rhs
1229             = rhs.numeric_conversion_function ();
1230 
1231           octave_base_value::type_conv_info cf_this
1232             = numeric_conversion_function ();
1233 
1234           // Try biased (one-sided) conversions first.
1235           if (cf_rhs.type_id () >= 0
1236               && (ti.lookup_assign_op (octave_value::op_asn_eq,
1237                                        t_lhs, cf_rhs.type_id ())
1238                   || ti.lookup_pref_assign_conv (t_lhs,
1239                                                  cf_rhs.type_id ()) >= 0))
1240             cf_this = nullptr;
1241           else if (cf_this.type_id () >= 0
1242                    && (ti.lookup_assign_op (octave_value::op_asn_eq,
1243                                             cf_this.type_id (), t_rhs)
1244                        || ti.lookup_pref_assign_conv (cf_this.type_id (),
1245                                                       t_rhs) >= 0))
1246             cf_rhs = nullptr;
1247 
1248           if (cf_rhs)
1249             {
1250               octave_base_value *tmp = cf_rhs (rhs.get_rep ());
1251 
1252               if (! tmp)
1253                 err_assign_conversion_failed (type_name (), rhs.type_name ());
1254 
1255               tmp_rhs = octave_value (tmp);
1256             }
1257           else
1258             tmp_rhs = rhs;
1259 
1260           count++;
1261           octave_value tmp_lhs = octave_value (this);
1262 
1263           if (cf_this)
1264             {
1265               octave_base_value *tmp = cf_this (*this);
1266 
1267               if (! tmp)
1268                 err_assign_conversion_failed (type_name (), rhs.type_name ());
1269 
1270               tmp_lhs = octave_value (tmp);
1271             }
1272 
1273           if (! cf_this && ! cf_rhs)
1274             err_no_conversion (octave_value::assign_op_as_string
1275                                (octave_value::op_asn_eq),
1276                                type_name (), rhs.type_name ());
1277 
1278           retval = tmp_lhs.subsasgn (type, idx, tmp_rhs);
1279 
1280           done = true;
1281         }
1282     }
1283 
1284   // The assignment may have converted to a type that is wider than necessary.
1285 
1286   retval.maybe_mutate ();
1287 
1288   return retval;
1289 }
1290 
1291 // Current indentation.
1292 int octave_base_value::curr_print_indent_level = 0;
1293 
1294 // TRUE means we are at the beginning of a line.
1295 bool octave_base_value::beginning_of_line = true;
1296 
1297 // Each print() function should call this before printing anything.
1298 //
1299 // This doesn't need to be fast, but isn't there a better way?
1300 
1301 void
indent(std::ostream & os) const1302 octave_base_value::indent (std::ostream& os) const
1303 {
1304   assert (curr_print_indent_level >= 0);
1305 
1306   if (beginning_of_line)
1307     {
1308       // FIXME: do we need this?
1309       // os << prefix;
1310 
1311       for (int i = 0; i < curr_print_indent_level; i++)
1312         os << ' ';
1313 
1314       beginning_of_line = false;
1315     }
1316 }
1317 
1318 // All print() functions should use this to print new lines.
1319 
1320 void
newline(std::ostream & os) const1321 octave_base_value::newline (std::ostream& os) const
1322 {
1323   os << "\n";
1324 
1325   beginning_of_line = true;
1326 }
1327 
1328 // For resetting print state.
1329 
1330 void
reset(void) const1331 octave_base_value::reset (void) const
1332 {
1333   beginning_of_line = true;
1334   curr_print_indent_level = 0;
1335 }
1336 
1337 octave_value
fast_elem_extract(octave_idx_type) const1338 octave_base_value::fast_elem_extract (octave_idx_type) const
1339 {
1340   return octave_value ();
1341 }
1342 
1343 bool
fast_elem_insert(octave_idx_type,const octave_value &)1344 octave_base_value::fast_elem_insert (octave_idx_type, const octave_value&)
1345 {
1346   return false;
1347 }
1348 
1349 bool
fast_elem_insert_self(void *,builtin_type_t) const1350 octave_base_value::fast_elem_insert_self (void *, builtin_type_t) const
1351 {
1352   return false;
1353 }
1354 
1355 static octave_base_value *
oct_conv_matrix_conv(const octave_base_value &)1356 oct_conv_matrix_conv (const octave_base_value&)
1357 {
1358   return new octave_matrix ();
1359 }
1360 
1361 static octave_base_value *
oct_conv_complex_matrix_conv(const octave_base_value &)1362 oct_conv_complex_matrix_conv (const octave_base_value&)
1363 {
1364   return new octave_complex_matrix ();
1365 }
1366 
1367 static octave_base_value *
oct_conv_string_conv(const octave_base_value &)1368 oct_conv_string_conv (const octave_base_value&)
1369 {
1370   return new octave_char_matrix_str ();
1371 }
1372 
1373 static octave_base_value *
oct_conv_cell_conv(const octave_base_value &)1374 oct_conv_cell_conv (const octave_base_value&)
1375 {
1376   return new octave_cell ();
1377 }
1378 
1379 static inline octave_value_list
sanitize(const octave_value_list & ovl)1380 sanitize (const octave_value_list& ovl)
1381 {
1382   octave_value_list retval = ovl;
1383 
1384   for (octave_idx_type i = 0; i < ovl.length (); i++)
1385     {
1386       if (retval(i).is_magic_colon ())
1387         retval(i) = ":";
1388     }
1389 
1390   return retval;
1391 }
1392 
1393 octave_value
make_idx_args(const std::string & type,const std::list<octave_value_list> & idx,const std::string & who)1394 make_idx_args (const std::string& type,
1395                const std::list<octave_value_list>& idx,
1396                const std::string& who)
1397 {
1398   std::size_t len = type.length ();
1399 
1400   if (len != idx.size ())
1401     error ("invalid index for %s", who.c_str ());
1402 
1403   Cell type_field (1, len);
1404   Cell subs_field (1, len);
1405 
1406   auto p = idx.begin ();
1407 
1408   for (std::size_t i = 0; i < len; i++)
1409     {
1410       char t = type[i];
1411 
1412       switch (t)
1413         {
1414         case '(':
1415           type_field(i) = "()";
1416           subs_field(i) = Cell (sanitize (*p++));
1417           break;
1418 
1419         case '{':
1420           type_field(i) = "{}";
1421           subs_field(i) = Cell (sanitize (*p++));
1422           break;
1423 
1424         case '.':
1425           {
1426             type_field(i) = ".";
1427 
1428             octave_value_list vlist = *p++;
1429 
1430             if (vlist.length () != 1)
1431               error ("only single argument permitted for '.' index");
1432 
1433             octave_value val = vlist(0);
1434 
1435             if (! val.is_string ())
1436               error ("string argument required for '.' index");
1437 
1438             subs_field(i) = val;
1439           }
1440           break;
1441 
1442         default:
1443           panic_impossible ();
1444           break;
1445         }
1446     }
1447 
1448   octave_map m;
1449 
1450   m.assign ("type", type_field);
1451   m.assign ("subs", subs_field);
1452 
1453   return m;
1454 }
1455 
1456 bool
called_from_builtin(void)1457 called_from_builtin (void)
1458 {
1459   octave::tree_evaluator& tw
1460     = octave::__get_evaluator__ ("called_from_builtin");
1461 
1462   octave_function *fcn = tw.caller_function ();
1463 
1464   // FIXME: we probably need a better check here, or some other
1465   // mechanism to avoid overloaded functions when builtin is used.
1466   // For example, what if someone overloads the builtin function?
1467   // Also, are there other places where using builtin is not properly
1468   // avoiding dispatch?
1469 
1470   return (fcn && fcn->name () == "builtin");
1471 }
1472 
1473 void
install_base_type_conversions(octave::type_info & ti)1474 install_base_type_conversions (octave::type_info& ti)
1475 {
1476   INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_scalar, octave_matrix);
1477   INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_matrix, octave_matrix);
1478   INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_complex,
1479                          octave_complex_matrix);
1480   INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_complex_matrix,
1481                          octave_complex_matrix);
1482   INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_range, octave_matrix);
1483   INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_char_matrix_str,
1484                          octave_char_matrix_str);
1485   INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_cell, octave_cell);
1486 
1487   INSTALL_WIDENOP_TI (ti, octave_base_value, octave_matrix, matrix_conv);
1488   INSTALL_WIDENOP_TI (ti, octave_base_value, octave_complex_matrix,
1489                       complex_matrix_conv);
1490   INSTALL_WIDENOP_TI (ti, octave_base_value, octave_char_matrix_str, string_conv);
1491   INSTALL_WIDENOP_TI (ti, octave_base_value, octave_cell, cell_conv);
1492 }
1493 
1494 DEFUN (sparse_auto_mutate, args, nargout,
1495        doc: /* -*- texinfo -*-
1496 @deftypefn  {} {@var{val} =} sparse_auto_mutate ()
1497 @deftypefnx {} {@var{old_val} =} sparse_auto_mutate (@var{new_val})
1498 @deftypefnx {} {} sparse_auto_mutate (@var{new_val}, "local")
1499 Query or set the internal variable that controls whether Octave will
1500 automatically mutate sparse matrices to full matrices to save memory.
1501 
1502 For example:
1503 
1504 @example
1505 @group
1506 s = speye (3);
1507 sparse_auto_mutate (false);
1508 s(:, 1) = 1;
1509 typeinfo (s)
1510 @result{} sparse matrix
1511 sparse_auto_mutate (true);
1512 s(1, :) = 1;
1513 typeinfo (s)
1514 @result{} matrix
1515 @end group
1516 @end example
1517 
1518 When called from inside a function with the @qcode{"local"} option, the
1519 variable is changed locally for the function and any subroutines it calls.
1520 The original variable value is restored when exiting the function.
1521 @end deftypefn */)
1522 {
1523   return SET_INTERNAL_VARIABLE (sparse_auto_mutate);
1524 }
1525 
1526 /*
1527 %!test
1528 %! s = speye (3);
1529 %! sparse_auto_mutate (false);
1530 %! s(:, 1) = 1;
1531 %! assert (typeinfo (s), "sparse matrix");
1532 %! sparse_auto_mutate (true);
1533 %! s(1, :) = 1;
1534 %! assert (typeinfo (s), "matrix");
1535 %! sparse_auto_mutate (false);
1536 */
1537