Mercurial > octave
view libinterp/octave-value/ov-base.cc @ 28126:4c21f99b4ad5
handle interleaved complex data and new typed data access functions for mex
* mexproto.h, mex.cc, mxarray.h (mxMakeArrayReal, mxMakeArrayComplex,
mxGetDoubles, mxGetSingles, mxGetInt8s, mxGetInt16s, mxGetInt32s,
mxGetInt64s, mxGetUint8s, mxGetUint16s, mxGetUint32s, mxGetUint64s,
mxGetComplexDoubles, mxGetComplexSingles, mxSetDoubles, mxSetSingles,
mxSetInt8s, mxSetInt16s, mxSetInt32s, mxSetInt64s, mxSetUint8s,
mxSetUint16s, mxSetUint32s, mxSetUint64s, mxSetComplexDoubles,
mxSetComplexSingles): New functions. Provide corresponding member
functions in mxArray class hierarchy to handle the actual operations.
(mxGetComplexInt8s, mxGetComplexInt16s, mxGetComplexInt32s,
mxGetComplexInt64s, mxGetComplexUint8s, mxGetComplexUint16s,
mxGetComplexUint32s, mxGetComplexUint64s, mxSetComplexInt8s,
mxSetComplexInt16s, mxSetComplexInt32s, mxSetComplexInt64s,
mxSetComplexUint8s, mxSetComplexUint16s, mxSetComplexUint32s,
mxSetComplexUint64s): Add prototypes and functions, but leave
commented out since we don't have complex integer data.
(class mxArray_number, class mxArray_sparse):
Handle interleaved complex data. In mxArray_octave_value and
mxArray_matlab constructors, handle interleaved flag in constructor to
determine data layout to use when creating mxArray_number or
mxArray_sparse objects.
(mex::make_value): Check flag in mex function to determine whether to
create arrays with interleaved complex.
* ov.h, ov.cc, ov-base.h, ov-base.cc, ov-base-diag.h, ov-base-diag.cc,
ov-bool-mat.h, ov-bool-mat.cc, ov-bool-sparse.h, ov-bool-sparse.cc,
ov-bool.h, ov-bool.cc, ov-cell.h, ov-cell.cc, ov-ch-mat.h,
ov-ch-mat.cc, ov-class.h, ov-class.cc, ov-complex.h, ov-complex.cc,
ov-cx-mat.h, ov-cx-mat.cc, ov-cx-sparse.h, ov-cx-sparse.cc,
ov-float.h, ov-float.cc, ov-flt-complex.h, ov-flt-complex.cc,
ov-flt-cx-mat.h, ov-flt-cx-mat.cc, ov-flt-re-mat.h, ov-flt-re-mat.cc,
ov-intx.h, ov-lazy-idx.h, ov-perm.h, ov-perm.cc, ov-range.h,
ov-range.cc, ov-re-mat.h, ov-re-mat.cc, ov-re-sparse.h,
ov-re-sparse.cc, ov-scalar.h, ov-scalar.cc, ov-struct.h, ov-struct.cc:
In all as_mxArray methods, handle new interleaved input to optionally
create objects that will use interleaved complex data.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 18 Feb 2020 13:16:41 -0500 |
parents | bd51beb6205e |
children | b743a63e2dab |
line wrap: on
line source
//////////////////////////////////////////////////////////////////////// // // Copyright (C) 1996-2020 The Octave Project Developers // // See the file COPYRIGHT.md in the top-level directory of this // distribution or <https://octave.org/copyright/>. // // This file is part of Octave. // // Octave is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Octave is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Octave; see the file COPYING. If not, see // <https://www.gnu.org/licenses/>. // //////////////////////////////////////////////////////////////////////// #if defined (HAVE_CONFIG_H) # include "config.h" #endif #include <istream> #include <limits> #include <ostream> #include "lo-ieee.h" #include "lo-mappers.h" #include "defun.h" #include "errwarn.h" #include "interpreter-private.h" #include "interpreter.h" #include "mxarray.h" #include "oct-hdf5.h" #include "oct-lvalue.h" #include "oct-map.h" #include "oct-stream.h" #include "ops.h" #include "ov-base.h" #include "ov-cell.h" #include "ov-ch-mat.h" #include "ov-classdef.h" #include "ov-complex.h" #include "ov-cx-mat.h" #include "ov-fcn-handle.h" #include "ov-range.h" #include "ov-re-mat.h" #include "ov-scalar.h" #include "ov-str-mat.h" #include "ovl.h" #include "parse.h" #include "pr-flt-fmt.h" #include "pr-output.h" #include "utils.h" #include "variables.h" builtin_type_t btyp_mixed_numeric (builtin_type_t x, builtin_type_t y) { builtin_type_t retval = btyp_unknown; if (x == btyp_bool) x = btyp_double; if (y == btyp_bool) y = btyp_double; if (x <= btyp_float_complex && y <= btyp_float_complex) retval = static_cast<builtin_type_t> (x | y); else if (x <= btyp_uint64 && y <= btyp_float) retval = x; else if (x <= btyp_float && y <= btyp_uint64) retval = y; else if ((x >= btyp_int8 && x <= btyp_int64 && y >= btyp_int8 && y <= btyp_int64) || (x >= btyp_uint8 && x <= btyp_uint64 && y >= btyp_uint8 && y <= btyp_uint64)) retval = (x > y) ? x : y; return retval; } std::string btyp_class_name[btyp_num_types] = { "double", "single", "double", "single", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "logical", "char", "struct", "cell", "function_handle" }; DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_base_value, "<unknown type>", "unknown"); // TRUE means to perform automatic sparse to real mutation if there // is memory to be saved bool Vsparse_auto_mutate = false; octave_base_value * octave_base_value::empty_clone (void) const { return resize (dim_vector ()).clone (); } octave_value octave_base_value::squeeze (void) const { std::string nm = type_name (); error ("squeeze: invalid operation for %s type", nm.c_str ()); } octave_value octave_base_value::full_value (void) const { err_wrong_type_arg ("full: invalid operation for %s type", type_name ()); } octave_value octave_base_value::as_double (void) const { err_invalid_conversion (type_name (), "double"); } octave_value octave_base_value::as_single (void) const { err_invalid_conversion (type_name (), "single"); } octave_value octave_base_value::as_int8 (void) const { err_invalid_conversion (type_name (), "int8"); } octave_value octave_base_value::as_int16 (void) const { err_invalid_conversion (type_name (), "int16"); } octave_value octave_base_value::as_int32 (void) const { err_invalid_conversion (type_name (), "int32"); } octave_value octave_base_value::as_int64 (void) const { err_invalid_conversion (type_name (), "int64"); } octave_value octave_base_value::as_uint8 (void) const { err_invalid_conversion (type_name (), "uint8"); } octave_value octave_base_value::as_uint16 (void) const { err_invalid_conversion (type_name (), "uint16"); } octave_value octave_base_value::as_uint32 (void) const { err_invalid_conversion (type_name (), "uint32"); } octave_value octave_base_value::as_uint64 (void) const { err_invalid_conversion (type_name (), "uint64"); } Matrix octave_base_value::size (void) { const dim_vector dv = dims (); Matrix mdv (1, dv.ndims ()); for (octave_idx_type i = 0; i < dv.ndims (); i++) mdv(i) = dv(i); return mdv; } octave_idx_type octave_base_value::xnumel (const octave_value_list& idx) { return octave::dims_to_numel (dims (), idx); } octave_value octave_base_value::subsref (const std::string&, const std::list<octave_value_list>&) { std::string nm = type_name (); error ("can't perform indexing operations for %s type", nm.c_str ()); } octave_value_list octave_base_value::subsref (const std::string&, const std::list<octave_value_list>&, int) { std::string nm = type_name (); error ("can't perform indexing operations for %s type", nm.c_str ()); } octave_value octave_base_value::subsref (const std::string& type, const std::list<octave_value_list>& idx, bool /* auto_add */) { // This way we may get a more meaningful error message. return subsref (type, idx); } octave_value octave_base_value::do_index_op (const octave_value_list&, bool) { std::string nm = type_name (); error ("can't perform indexing operations for %s type", nm.c_str ()); } idx_vector octave_base_value::index_vector (bool /* require_integers */) const { std::string nm = '<' + type_name () + '>'; octave::err_invalid_index (nm.c_str ()); } octave_value octave_base_value::subsasgn (const std::string& type, const std::list<octave_value_list>& idx, const octave_value& rhs) { octave_value retval; if (is_defined ()) { if (! isnumeric ()) { std::string nm = type_name (); error ("can't perform indexed assignment for %s type", nm.c_str ()); } switch (type[0]) { case '(': { if (type.length () == 1) retval = numeric_assign (type, idx, rhs); else if (isempty ()) { // Allow conversion of empty matrix to some other // type in cases like // // x = []; x(i).f = rhs octave_value tmp = octave_value::empty_conv (type, rhs); retval = tmp.subsasgn (type, idx, rhs); } else { std::string nm = type_name (); error ("in indexed assignment of %s, last rhs index must be ()", nm.c_str ()); } } break; case '{': case '.': { std::string nm = type_name (); error ("%s cannot be indexed with %c", nm.c_str (), type[0]); } break; default: panic_impossible (); } } else { // Create new object of appropriate type for given index and rhs // types and then call undef_subsasgn for that object. octave_value tmp = octave_value::empty_conv (type, rhs); retval = tmp.undef_subsasgn (type, idx, rhs); } return retval; } octave_value octave_base_value::undef_subsasgn (const std::string& type, const std::list<octave_value_list>& idx, const octave_value& rhs) { // In most cases, undef_subsasgn is handled the sams as subsasgn. One // exception is octave_class objects. return subsasgn (type, idx, rhs); } octave_idx_type octave_base_value::nnz (void) const { err_wrong_type_arg ("octave_base_value::nnz ()", type_name ()); } octave_idx_type octave_base_value::nzmax (void) const { return numel (); } octave_idx_type octave_base_value::nfields (void) const { err_wrong_type_arg ("octave_base_value::nfields ()", type_name ()); } octave_value octave_base_value::reshape (const dim_vector&) const { err_wrong_type_arg ("octave_base_value::reshape ()", type_name ()); } octave_value octave_base_value::permute (const Array<int>&, bool) const { err_wrong_type_arg ("octave_base_value::permute ()", type_name ()); } octave_value octave_base_value::resize (const dim_vector&, bool) const { err_wrong_type_arg ("octave_base_value::resize ()", type_name ()); } MatrixType octave_base_value::matrix_type (void) const { err_wrong_type_arg ("octave_base_value::matrix_type ()", type_name ()); } MatrixType octave_base_value::matrix_type (const MatrixType&) const { err_wrong_type_arg ("octave_base_value::matrix_type ()", type_name ()); } octave_value octave_base_value::all (int) const { return 0.0; } octave_value octave_base_value::any (int) const { return 0.0; } octave_value octave_base_value::convert_to_str (bool pad, bool force, char type) const { octave_value retval = convert_to_str_internal (pad, force, type); if (! force && isnumeric ()) warn_implicit_conversion ("Octave:num-to-str", type_name (), retval.type_name ()); return retval; } octave_value octave_base_value::convert_to_str_internal (bool, bool, char) const { err_wrong_type_arg ("octave_base_value::convert_to_str_internal ()", type_name ()); } void octave_base_value::convert_to_row_or_column_vector (void) { err_wrong_type_arg ("octave_base_value::convert_to_row_or_column_vector ()", type_name ()); } void octave_base_value::print (std::ostream&, bool) { err_wrong_type_arg ("octave_base_value::print ()", type_name ()); } void octave_base_value::print_raw (std::ostream&, bool) const { err_wrong_type_arg ("octave_base_value::print_raw ()", type_name ()); } bool octave_base_value::print_name_tag (std::ostream& os, const std::string& name) const { indent (os); if (print_as_scalar ()) os << name << " = "; else { os << name << " ="; newline (os); if (! Vcompact_format) newline (os); return true; } return false; } void octave_base_value::print_with_name (std::ostream& output_buf, const std::string& name, bool print_padding) { bool pad_after = print_name_tag (output_buf, name); print (output_buf); if (print_padding && pad_after && ! Vcompact_format) newline (output_buf); } float_display_format octave_base_value::get_edit_display_format (void) const { return float_display_format (); } void octave_base_value::print_info (std::ostream& os, const std::string& /* prefix */) const { os << "no info for type: " << type_name () << "\n"; } #define INT_CONV_METHOD(T, F) \ T \ octave_base_value::F ## _value (bool require_int, bool frc_str_conv) const \ { \ T retval = 0; \ \ double d = 0.0; \ \ try \ { \ d = double_value (frc_str_conv); \ } \ catch (octave::execution_exception& e) \ { \ err_wrong_type_arg (e, "octave_base_value::" #F "_value ()", type_name ()); \ } \ \ if (require_int && octave::math::x_nint (d) != d) \ error_with_cfn ("conversion of %g to " #T " value failed", d); \ else if (d < std::numeric_limits<T>::min ()) \ retval = std::numeric_limits<T>::min (); \ else if (d > std::numeric_limits<T>::max ()) \ retval = std::numeric_limits<T>::max (); \ else \ retval = static_cast<T> (octave::math::fix (d)); \ \ return retval; \ } INT_CONV_METHOD (short int, short) INT_CONV_METHOD (unsigned short int, ushort) INT_CONV_METHOD (int, int) INT_CONV_METHOD (unsigned int, uint) INT_CONV_METHOD (long int, long) INT_CONV_METHOD (unsigned long int, ulong) INT_CONV_METHOD (int64_t, int64) INT_CONV_METHOD (uint64_t, uint64) int octave_base_value::nint_value (bool frc_str_conv) const { double d = 0.0; try { d = double_value (frc_str_conv); } catch (octave::execution_exception& e) { err_wrong_type_arg (e, "octave_base_value::nint_value ()", type_name ()); } if (octave::math::isnan (d)) error ("conversion of NaN to integer value failed"); return static_cast<int> (octave::math::fix (d)); } double octave_base_value::double_value (bool) const { err_wrong_type_arg ("octave_base_value::double_value ()", type_name ()); } float octave_base_value::float_value (bool) const { err_wrong_type_arg ("octave_base_value::float_value ()", type_name ()); } Cell octave_base_value::cell_value () const { err_wrong_type_arg ("octave_base_value::cell_value()", type_name ()); } Matrix octave_base_value::matrix_value (bool) const { err_wrong_type_arg ("octave_base_value::matrix_value()", type_name ()); } FloatMatrix octave_base_value::float_matrix_value (bool) const { err_wrong_type_arg ("octave_base_value::float_matrix_value()", type_name ()); } NDArray octave_base_value::array_value (bool) const { err_wrong_type_arg ("octave_base_value::array_value()", type_name ()); } FloatNDArray octave_base_value::float_array_value (bool) const { err_wrong_type_arg ("octave_base_value::float_array_value()", type_name ()); } Complex octave_base_value::complex_value (bool) const { err_wrong_type_arg ("octave_base_value::complex_value()", type_name ()); } FloatComplex octave_base_value::float_complex_value (bool) const { err_wrong_type_arg ("octave_base_value::float_complex_value()", type_name ()); } ComplexMatrix octave_base_value::complex_matrix_value (bool) const { err_wrong_type_arg ("octave_base_value::complex_matrix_value()", type_name ()); } FloatComplexMatrix octave_base_value::float_complex_matrix_value (bool) const { err_wrong_type_arg ("octave_base_value::float_complex_matrix_value()", type_name ()); } ComplexNDArray octave_base_value::complex_array_value (bool) const { err_wrong_type_arg ("octave_base_value::complex_array_value()", type_name ()); } FloatComplexNDArray octave_base_value::float_complex_array_value (bool) const { err_wrong_type_arg ("octave_base_value::float_complex_array_value()", type_name ()); } bool octave_base_value::bool_value (bool) const { err_wrong_type_arg ("octave_base_value::bool_value()", type_name ()); } boolMatrix octave_base_value::bool_matrix_value (bool) const { err_wrong_type_arg ("octave_base_value::bool_matrix_value()", type_name ()); } boolNDArray octave_base_value::bool_array_value (bool) const { err_wrong_type_arg ("octave_base_value::bool_array_value()", type_name ()); } charMatrix octave_base_value::char_matrix_value (bool force) const { octave_value tmp = convert_to_str (false, force); return tmp.char_matrix_value (); } charNDArray octave_base_value::char_array_value (bool) const { err_wrong_type_arg ("octave_base_value::char_array_value()", type_name ()); } SparseMatrix octave_base_value::sparse_matrix_value (bool) const { err_wrong_type_arg ("octave_base_value::sparse_matrix_value()", type_name ()); } SparseComplexMatrix octave_base_value::sparse_complex_matrix_value (bool) const { err_wrong_type_arg ("octave_base_value::sparse_complex_matrix_value()", type_name ()); } SparseBoolMatrix octave_base_value::sparse_bool_matrix_value (bool) const { err_wrong_type_arg ("octave_base_value::sparse_bool_matrix_value()", type_name ()); } DiagMatrix octave_base_value::diag_matrix_value (bool) const { err_wrong_type_arg ("octave_base_value::diag_matrix_value()", type_name ()); } FloatDiagMatrix octave_base_value::float_diag_matrix_value (bool) const { err_wrong_type_arg ("octave_base_value::float_diag_matrix_value()", type_name ()); } ComplexDiagMatrix octave_base_value::complex_diag_matrix_value (bool) const { err_wrong_type_arg ("octave_base_value::complex_diag_matrix_value()", type_name ()); } FloatComplexDiagMatrix octave_base_value::float_complex_diag_matrix_value (bool) const { err_wrong_type_arg ("octave_base_value::float_complex_diag_matrix_value()", type_name ()); } PermMatrix octave_base_value::perm_matrix_value (void) const { err_wrong_type_arg ("octave_base_value::perm_matrix_value()", type_name ()); } octave_int8 octave_base_value::int8_scalar_value (void) const { err_wrong_type_arg ("octave_base_value::int8_scalar_value()", type_name ()); } octave_int16 octave_base_value::int16_scalar_value (void) const { err_wrong_type_arg ("octave_base_value::int16_scalar_value()", type_name ()); } octave_int32 octave_base_value::int32_scalar_value (void) const { err_wrong_type_arg ("octave_base_value::int32_scalar_value()", type_name ()); } octave_int64 octave_base_value::int64_scalar_value (void) const { err_wrong_type_arg ("octave_base_value::int64_scalar_value()", type_name ()); } octave_uint8 octave_base_value::uint8_scalar_value (void) const { err_wrong_type_arg ("octave_base_value::uint8_scalar_value()", type_name ()); } octave_uint16 octave_base_value::uint16_scalar_value (void) const { err_wrong_type_arg ("octave_base_value::uint16_scalar_value()", type_name ()); } octave_uint32 octave_base_value::uint32_scalar_value (void) const { err_wrong_type_arg ("octave_base_value::uint32_scalar_value()", type_name ()); } octave_uint64 octave_base_value::uint64_scalar_value (void) const { err_wrong_type_arg ("octave_base_value::uint64_scalar_value()", type_name ()); } int8NDArray octave_base_value::int8_array_value (void) const { err_wrong_type_arg ("octave_base_value::int8_array_value()", type_name ()); } int16NDArray octave_base_value::int16_array_value (void) const { err_wrong_type_arg ("octave_base_value::int16_array_value()", type_name ()); } int32NDArray octave_base_value::int32_array_value (void) const { err_wrong_type_arg ("octave_base_value::int32_array_value()", type_name ()); } int64NDArray octave_base_value::int64_array_value (void) const { err_wrong_type_arg ("octave_base_value::int64_array_value()", type_name ()); } uint8NDArray octave_base_value::uint8_array_value (void) const { err_wrong_type_arg ("octave_base_value::uint8_array_value()", type_name ()); } uint16NDArray octave_base_value::uint16_array_value (void) const { err_wrong_type_arg ("octave_base_value::uint16_array_value()", type_name ()); } uint32NDArray octave_base_value::uint32_array_value (void) const { err_wrong_type_arg ("octave_base_value::uint32_array_value()", type_name ()); } uint64NDArray octave_base_value::uint64_array_value (void) const { err_wrong_type_arg ("octave_base_value::uint64_array_value()", type_name ()); } string_vector octave_base_value::string_vector_value (bool pad) const { octave_value tmp = convert_to_str (pad, true); return tmp.string_vector_value (); } std::string octave_base_value::string_value (bool force) const { octave_value tmp = convert_to_str (force); return tmp.string_value (); } std::string octave_base_value::xstring_value (void) const { wrong_type_arg_error (); return std::string (); } Array<std::string> octave_base_value::cellstr_value (void) const { err_wrong_type_arg ("octave_base_value::cellstr_value()", type_name ()); } Range octave_base_value::range_value (void) const { err_wrong_type_arg ("octave_base_value::range_value()", type_name ()); } octave_map octave_base_value::map_value (void) const { err_wrong_type_arg ("octave_base_value::map_value()", type_name ()); } octave_scalar_map octave_base_value::scalar_map_value (void) const { octave_map tmp = map_value (); if (tmp.numel () != 1) error ("invalid conversion of multi-dimensional struct to scalar struct"); return octave_scalar_map (tmp.checkelem (0)); } string_vector octave_base_value::map_keys (void) const { err_wrong_type_arg ("octave_base_value::map_keys()", type_name ()); } size_t octave_base_value::nparents (void) const { err_wrong_type_arg ("octave_base_value::nparents()", type_name ()); } std::list<std::string> octave_base_value::parent_class_name_list (void) const { err_wrong_type_arg ("octave_base_value::parent_class_name_list()", type_name ()); } string_vector octave_base_value::parent_class_names (void) const { err_wrong_type_arg ("octave_base_value::parent_class_names()", type_name ()); } octave_classdef * octave_base_value::classdef_object_value (bool silent) { if (! silent) err_wrong_type_arg ("octave_base_value::classdef_object_value()", type_name ()); return nullptr; } octave_function * octave_base_value::function_value (bool silent) { if (! silent) err_wrong_type_arg ("octave_base_value::function_value()", type_name ()); return nullptr; } octave_user_function * octave_base_value::user_function_value (bool silent) { if (! silent) err_wrong_type_arg ("octave_base_value::user_function_value()", type_name ()); return nullptr; } octave_user_script * octave_base_value::user_script_value (bool silent) { if (! silent) err_wrong_type_arg ("octave_base_value::user_script_value()", type_name ()); return nullptr; } octave_user_code * octave_base_value::user_code_value (bool silent) { if (! silent) err_wrong_type_arg ("octave_base_value::user_code_value()", type_name ()); return nullptr; } octave_fcn_handle * octave_base_value::fcn_handle_value (bool silent) { if (! silent) err_wrong_type_arg ("octave_base_value::fcn_handle_value()", type_name ()); return nullptr; } octave_fcn_inline * octave_base_value::fcn_inline_value (bool silent) { if (! silent) err_wrong_type_arg ("octave_base_value::fcn_inline_value()", type_name ()); return nullptr; } octave_value_list octave_base_value::list_value (void) const { err_wrong_type_arg ("octave_base_value::list_value()", type_name ()); } bool octave_base_value::save_ascii (std::ostream&) { err_wrong_type_arg ("octave_base_value::save_ascii()", type_name ()); } bool octave_base_value::load_ascii (std::istream&) { err_wrong_type_arg ("octave_base_value::load_ascii()", type_name ()); } bool octave_base_value::save_binary (std::ostream&, bool) { err_wrong_type_arg ("octave_base_value::save_binary()", type_name ()); } bool octave_base_value::load_binary (std::istream&, bool, octave::mach_info::float_format) { err_wrong_type_arg ("octave_base_value::load_binary()", type_name ()); } bool octave_base_value::save_hdf5 (octave_hdf5_id, const char *, bool) { err_wrong_type_arg ("octave_base_value::save_binary()", type_name ()); } bool octave_base_value::load_hdf5 (octave_hdf5_id, const char *) { err_wrong_type_arg ("octave_base_value::load_binary()", type_name ()); } int octave_base_value::write (octave::stream&, int, oct_data_conv::data_type, int, octave::mach_info::float_format) const { err_wrong_type_arg ("octave_base_value::write()", type_name ()); } mxArray * octave_base_value::as_mxArray (bool) const { return nullptr; } octave_value octave_base_value::diag (octave_idx_type) const { err_wrong_type_arg ("octave_base_value::diag ()", type_name ()); } octave_value octave_base_value::diag (octave_idx_type, octave_idx_type) const { err_wrong_type_arg ("octave_base_value::diag ()", type_name ()); } octave_value octave_base_value::sort (octave_idx_type, sortmode) const { err_wrong_type_arg ("octave_base_value::sort ()", type_name ()); } octave_value octave_base_value::sort (Array<octave_idx_type> &, octave_idx_type, sortmode) const { err_wrong_type_arg ("octave_base_value::sort ()", type_name ()); } sortmode octave_base_value::issorted (sortmode) const { err_wrong_type_arg ("octave_base_value::issorted ()", type_name ()); } Array<octave_idx_type> octave_base_value::sort_rows_idx (sortmode) const { err_wrong_type_arg ("octave_base_value::sort_rows_idx ()", type_name ()); } sortmode octave_base_value::is_sorted_rows (sortmode) const { err_wrong_type_arg ("octave_base_value::is_sorted_rows ()", type_name ()); } const char * octave_base_value::get_umap_name (unary_mapper_t umap) { static const char *names[num_unary_mappers] = { "abs", "acos", "acosh", "angle", "arg", "asin", "asinh", "atan", "atanh", "cbrt", "ceil", "conj", "cos", "cosh", "erf", "erfinv", "erfcinv", "erfc", "erfcx", "erfi", "dawson", "exp", "expm1", "isfinite", "fix", "floor", "gamma", "imag", "isinf", "isna", "isnan", "lgamma", "log", "log2", "log10", "log1p", "real", "round", "roundb", "signum", "sin", "sinh", "sqrt", "tan", "tanh", "isalnum", "isalpha", "isascii", "iscntrl", "isdigit", "isgraph", "islower", "isprint", "ispunct", "isspace", "isupper", "isxdigit", "signbit", "tolower", "toupper" }; if (umap < 0 || umap >= num_unary_mappers) return "unknown"; else return names[umap]; } void octave_base_value::warn_load (const char *type) const { warning_with_id ("Octave:load-save-unavailable", "%s: loading %s files not available in this version of Octave", t_name.c_str (), type); } void octave_base_value::warn_save (const char *type) const { warning_with_id ("Octave:load-save-unavailable", "%s: saving %s files not available in this version of Octave", t_name.c_str (), type); } void octave_base_value::wrong_type_arg_error (void) const { err_wrong_type_arg (type_name ()); } octave_value octave_base_value::map (unary_mapper_t umap) const { error ("%s: not defined for %s", get_umap_name (umap), type_name ().c_str ()); } void octave_base_value::lock (void) { err_wrong_type_arg ("octave_base_value::lock ()", type_name ()); } void octave_base_value::unlock (void) { err_wrong_type_arg ("octave_base_value::unlock ()", type_name ()); } octave_value octave_base_value::dump (void) const { std::map<std::string, octave_value> m = {{ "class", this->class_name () }, { "type", this->type_name () }, { "dims", this->dims().as_array () }}; return octave_value (m); } OCTAVE_NORETURN static void err_indexed_assignment (const std::string& tn1, const std::string& tn2) { error ("assignment of '%s' to indexed '%s' not implemented", tn2.c_str (), tn1.c_str ()); } OCTAVE_NORETURN static void err_assign_conversion_failed (const std::string& tn1, const std::string& tn2) { error ("type conversion for assignment of '%s' to indexed '%s' failed", tn2.c_str (), tn1.c_str ()); } OCTAVE_NORETURN static void err_no_conversion (const std::string& on, const std::string& tn1, const std::string& tn2) { error ("operator %s: no conversion for assignment of '%s' to indexed '%s'", on.c_str (), tn2.c_str (), tn1.c_str ()); } octave_value octave_base_value::numeric_assign (const std::string& type, const std::list<octave_value_list>& idx, const octave_value& rhs) { octave_value retval; if (idx.front ().empty ()) error ("missing index in indexed assignment"); int t_lhs = type_id (); int t_rhs = rhs.type_id (); octave::type_info& ti = octave::__get_type_info__ ("octave_base_value::numeric_assign"); octave::type_info::assign_op_fcn f = ti.lookup_assign_op (octave_value::op_asn_eq, t_lhs, t_rhs); bool done = false; if (f) { f (*this, idx.front (), rhs.get_rep ()); done = true; } if (done) { count++; retval = octave_value (this); } else { int t_result = ti.lookup_pref_assign_conv (t_lhs, t_rhs); if (t_result >= 0) { octave_base_value::type_conv_fcn cf = ti.lookup_widening_op (t_lhs, t_result); if (! cf) err_indexed_assignment (type_name (), rhs.type_name ()); octave_base_value *tmp = cf (*this); if (! tmp) err_assign_conversion_failed (type_name (), rhs.type_name ()); octave_value val (tmp); retval = val.subsasgn (type, idx, rhs); done = true; } if (! done) { octave_value tmp_rhs; octave_base_value::type_conv_info cf_rhs = rhs.numeric_conversion_function (); octave_base_value::type_conv_info cf_this = numeric_conversion_function (); // Try biased (one-sided) conversions first. if (cf_rhs.type_id () >= 0 && (ti.lookup_assign_op (octave_value::op_asn_eq, t_lhs, cf_rhs.type_id ()) || ti.lookup_pref_assign_conv (t_lhs, cf_rhs.type_id ()) >= 0)) cf_this = nullptr; else if (cf_this.type_id () >= 0 && (ti.lookup_assign_op (octave_value::op_asn_eq, cf_this.type_id (), t_rhs) || ti.lookup_pref_assign_conv (cf_this.type_id (), t_rhs) >= 0)) cf_rhs = nullptr; if (cf_rhs) { octave_base_value *tmp = cf_rhs (rhs.get_rep ()); if (! tmp) err_assign_conversion_failed (type_name (), rhs.type_name ()); tmp_rhs = octave_value (tmp); } else tmp_rhs = rhs; count++; octave_value tmp_lhs = octave_value (this); if (cf_this) { octave_base_value *tmp = cf_this (*this); if (! tmp) err_assign_conversion_failed (type_name (), rhs.type_name ()); tmp_lhs = octave_value (tmp); } if (! cf_this && ! cf_rhs) err_no_conversion (octave_value::assign_op_as_string (octave_value::op_asn_eq), type_name (), rhs.type_name ()); retval = tmp_lhs.subsasgn (type, idx, tmp_rhs); done = true; } } // The assignment may have converted to a type that is wider than necessary. retval.maybe_mutate (); return retval; } // Current indentation. int octave_base_value::curr_print_indent_level = 0; // TRUE means we are at the beginning of a line. bool octave_base_value::beginning_of_line = true; // Each print() function should call this before printing anything. // // This doesn't need to be fast, but isn't there a better way? void octave_base_value::indent (std::ostream& os) const { assert (curr_print_indent_level >= 0); if (beginning_of_line) { // FIXME: do we need this? // os << prefix; for (int i = 0; i < curr_print_indent_level; i++) os << ' '; beginning_of_line = false; } } // All print() functions should use this to print new lines. void octave_base_value::newline (std::ostream& os) const { os << "\n"; beginning_of_line = true; } // For resetting print state. void octave_base_value::reset (void) const { beginning_of_line = true; curr_print_indent_level = 0; } octave_value octave_base_value::fast_elem_extract (octave_idx_type) const { return octave_value (); } bool octave_base_value::fast_elem_insert (octave_idx_type, const octave_value&) { return false; } bool octave_base_value::fast_elem_insert_self (void *, builtin_type_t) const { return false; } static octave_base_value * oct_conv_matrix_conv (const octave_base_value&) { return new octave_matrix (); } static octave_base_value * oct_conv_complex_matrix_conv (const octave_base_value&) { return new octave_complex_matrix (); } static octave_base_value * oct_conv_string_conv (const octave_base_value&) { return new octave_char_matrix_str (); } static octave_base_value * oct_conv_cell_conv (const octave_base_value&) { return new octave_cell (); } static inline octave_value_list sanitize (const octave_value_list& ovl) { octave_value_list retval = ovl; for (octave_idx_type i = 0; i < ovl.length (); i++) { if (retval(i).is_magic_colon ()) retval(i) = ":"; } return retval; } octave_value make_idx_args (const std::string& type, const std::list<octave_value_list>& idx, const std::string& who) { size_t len = type.length (); if (len != idx.size ()) error ("invalid index for %s", who.c_str ()); Cell type_field (1, len); Cell subs_field (1, len); auto p = idx.begin (); for (size_t i = 0; i < len; i++) { char t = type[i]; switch (t) { case '(': type_field(i) = "()"; subs_field(i) = Cell (sanitize (*p++)); break; case '{': type_field(i) = "{}"; subs_field(i) = Cell (sanitize (*p++)); break; case '.': { type_field(i) = "."; octave_value_list vlist = *p++; if (vlist.length () != 1) error ("only single argument permitted for '.' index"); octave_value val = vlist(0); if (! val.is_string ()) error ("string argument required for '.' index"); subs_field(i) = val; } break; default: panic_impossible (); break; } } octave_map m; m.assign ("type", type_field); m.assign ("subs", subs_field); return m; } bool called_from_builtin (void) { octave::tree_evaluator& tw = octave::__get_evaluator__ ("called_from_builtin"); octave_function *fcn = tw.caller_function (); // FIXME: we probably need a better check here, or some other // mechanism to avoid overloaded functions when builtin is used. // For example, what if someone overloads the builtin function? // Also, are there other places where using builtin is not properly // avoiding dispatch? return (fcn && fcn->name () == "builtin"); } void install_base_type_conversions (octave::type_info& ti) { INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_scalar, octave_matrix); INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_matrix, octave_matrix); INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_complex, octave_complex_matrix); INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_complex_matrix, octave_complex_matrix); INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_range, octave_matrix); INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_char_matrix_str, octave_char_matrix_str); INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_cell, octave_cell); INSTALL_WIDENOP_TI (ti, octave_base_value, octave_matrix, matrix_conv); INSTALL_WIDENOP_TI (ti, octave_base_value, octave_complex_matrix, complex_matrix_conv); INSTALL_WIDENOP_TI (ti, octave_base_value, octave_char_matrix_str, string_conv); INSTALL_WIDENOP_TI (ti, octave_base_value, octave_cell, cell_conv); } DEFUN (sparse_auto_mutate, args, nargout, doc: /* -*- texinfo -*- @deftypefn {} {@var{val} =} sparse_auto_mutate () @deftypefnx {} {@var{old_val} =} sparse_auto_mutate (@var{new_val}) @deftypefnx {} {} sparse_auto_mutate (@var{new_val}, "local") Query or set the internal variable that controls whether Octave will automatically mutate sparse matrices to full matrices to save memory. For example: @example @group s = speye (3); sparse_auto_mutate (false); s(:, 1) = 1; typeinfo (s) @result{} sparse matrix sparse_auto_mutate (true); s(1, :) = 1; typeinfo (s) @result{} matrix @end group @end example When called from inside a function with the @qcode{"local"} option, the variable is changed locally for the function and any subroutines it calls. The original variable value is restored when exiting the function. @end deftypefn */) { return SET_INTERNAL_VARIABLE (sparse_auto_mutate); } /* %!test %! s = speye (3); %! sparse_auto_mutate (false); %! s(:, 1) = 1; %! assert (typeinfo (s), "sparse matrix"); %! sparse_auto_mutate (true); %! s(1, :) = 1; %! assert (typeinfo (s), "matrix"); %! sparse_auto_mutate (false); */