GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
op-class.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2007-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 //! @file op-class.cc
27 //! Unary and binary operators for classdef and old style classes.
28 
29 #if defined (HAVE_CONFIG_H)
30 # include "config.h"
31 #endif
32 
33 #include "oct-time.h"
34 
35 #include "errwarn.h"
36 #include "interpreter-private.h"
37 #include "load-path.h"
38 #include "ovl.h"
39 #include "ov.h"
40 #include "ov-class.h"
41 #include "ov-typeinfo.h"
42 #include "ops.h"
43 #include "symtab.h"
44 #include "parse.h"
45 
46 //! Default unary class operator.
47 //!
48 //! @param a operand
49 //! @param opname operator name
50 
51 static octave_value
52 oct_unop_default (const octave_value& a, const std::string& opname)
53 {
54  std::string class_name = a.class_name ();
55 
56  octave_value meth
57  = octave::__get_symbol_table__ ("oct_unop_" + opname)
58  .find_method (opname, class_name);
59 
60  if (meth.is_defined ())
61  {
62  // Call overloaded unary class operator.
64  ovl (a), 1);
65 
66  // Return first element if present.
67  if (tmp.length () > 0)
68  return tmp(0);
69 
70  return octave_value ();
71  }
72 
73  // Matlab compatibility: If (conjugate) transpose is not overloaded and
74  // the number of dimensions is maximal two, just transpose the array of
75  // that class.
76 
77  if ((opname == "transpose") || (opname == "ctranspose"))
78  {
79  if (a.ndims () > 2)
80  error ("%s not defined for N-D objects of %s class", opname.c_str (),
81  class_name.c_str ());
82 
83  if (a.is_classdef_object ())
84  {
85  // FIXME: Default transposition for classdef arrays.
86 
87  error ("%s method not defined for %s class", opname.c_str (),
88  class_name.c_str ());
89  }
90  else
91  {
92  const octave_class& v
93  = dynamic_cast<const octave_class&> (a.get_rep ());
94 
95  return octave_value (v.map_value ().transpose (),
96  v.class_name (),
98  }
99  }
100  else
101  error ("%s method not defined for %s class", opname.c_str (),
102  class_name.c_str ());
103 }
104 
105 //! Helper macro to define unary class operators.
106 
107 #define DEF_CLASS_UNOP(opname) \
108  static octave_value \
109  oct_unop_ ## opname (const octave_value& a) \
110  { \
111  return oct_unop_default (a, #opname); \
112  }
113 
114 DEF_CLASS_UNOP (not) // !a or ~a
115 DEF_CLASS_UNOP (uplus) // +a
116 DEF_CLASS_UNOP (uminus) // -a
118 DEF_CLASS_UNOP (ctranspose) // a'
119 #undef DEF_CLASS_UNOP
120 
121 //! Default binary class operator.
122 //!
123 //! @param a1 first operand
124 //! @param a2 second operand
125 //! @param opname operator name
126 //!
127 //! The operator precedence is as follows:
128 //!
129 //! 1. If exactly one of the operands is a user defined class object, then
130 //! the class method of that operand is invoked.
131 //!
132 //! 2. If both operands are user defined class objects, then
133 //! 2.1 The superior class method is invoked.
134 //! 2.2 The leftmost class method is invoked if both classes are the same
135 //! or their precedence is not defined by superiorto/inferiorto.
136 
137 static octave_value
139  const std::string& opname)
140 {
141  octave::symbol_table& symtab
142  = octave::__get_symbol_table__ ("oct_binop_" + opname);
143 
144  // Dispatch to first (leftmost) operand by default.
145  std::string dispatch_type = a1.class_name ();
146 
147  // Determine, if second operand takes precedence (see rules above).
148  if (! a1.isobject ()
149  || (a1.isobject () && a2.isobject ()
150  && symtab.is_superiorto (a2.class_name (), dispatch_type)))
151  dispatch_type = a2.class_name ();
152 
153  octave_value meth = symtab.find_method (opname, dispatch_type);
154 
155  if (meth.is_undefined ())
156  error ("%s method not defined for %s class", opname.c_str (),
157  dispatch_type.c_str ());
158 
160  ovl (a1, a2), 1);
161 
162  if (tmp.length () > 0)
163  return tmp(0);
164 
165  return octave_value ();
166 }
167 
168 //! Helper macro to define binary class operators.
169 
170 #define DEF_CLASS_BINOP(opname) \
171  static octave_value \
172  oct_binop_ ## opname (const octave_value& a1, const octave_value& a2) \
173  { \
174  return oct_binop_default (a1, a2, #opname); \
175  }
176 
177 DEF_CLASS_BINOP (plus) // a1 + a2
178 DEF_CLASS_BINOP (minus) // a1 - a2
179 DEF_CLASS_BINOP (mtimes) // a1 * a2
180 DEF_CLASS_BINOP (mrdivide) // a1 / a2
181 DEF_CLASS_BINOP (mpower) // a1 ^ a2
182 DEF_CLASS_BINOP (mldivide) // a1 \ a2
183 DEF_CLASS_BINOP (lt) // a1 < a2
184 DEF_CLASS_BINOP (le) // a1 <= a2
185 DEF_CLASS_BINOP (eq) // a1 <= a2
186 DEF_CLASS_BINOP (ge) // a1 >= a2
187 DEF_CLASS_BINOP (gt) // a1 > a2
188 DEF_CLASS_BINOP (ne) // a1 ~= a2 or a1 != a2
189 DEF_CLASS_BINOP (times) // a1 .* a2
190 DEF_CLASS_BINOP (rdivide) // a1 ./ a2
191 DEF_CLASS_BINOP (power) // a1 .^ a2
192 DEF_CLASS_BINOP (ldivide) // a1 .\ a2
193 DEF_CLASS_BINOP (and) // a1 & a2
194 DEF_CLASS_BINOP (or) // a1 | a2
195 #undef DEF_CLASS_BINOP
196 
197 void
199 {
205 
224 }
bool is_superiorto(const std::string &a, const std::string &b)
Definition: symtab.cc:537
octave_value find_method(const std::string &name, const std::string &dispatch_type)
Definition: symtab.cc:125
bool install_unary_class_op(octave_value::unary_op op, unary_class_op_fcn f)
Definition: ov-typeinfo.h:80
bool install_binary_class_op(octave_value::binary_op op, binary_class_op_fcn f)
Definition: ov-typeinfo.h:97
virtual bool isobject(void) const
Definition: ov-base.h:391
virtual std::string class_name(void) const
Definition: ov-base.h:874
std::list< std::string > parent_class_name_list(void) const
Definition: ov-class.h:171
std::string class_name(void) const
Definition: ov-class.h:216
octave_map map_value(void) const
Definition: ov-class.h:167
octave_map transpose(void) const
Definition: oct-map.cc:499
octave_idx_type length(void) const
Definition: ovl.h:113
bool is_classdef_object(void) const
Definition: ov.h:611
const octave_base_value & get_rep(void) const
Definition: ov.h:1292
@ op_hermitian
Definition: ov.h:88
@ op_uminus
Definition: ov.h:86
@ op_not
Definition: ov.h:84
@ op_transpose
Definition: ov.h:87
@ op_uplus
Definition: ov.h:85
bool is_defined(void) const
Definition: ov.h:551
std::string class_name(void) const
Definition: ov.h:1256
int ndims(void) const
Definition: ov.h:510
octave_function * function_value(bool silent=false) const
@ op_ldiv
Definition: ov.h:102
@ op_ne
Definition: ov.h:108
@ op_el_or
Definition: ov.h:114
@ op_el_ldiv
Definition: ov.h:112
@ op_pow
Definition: ov.h:101
@ op_ge
Definition: ov.h:106
@ op_div
Definition: ov.h:100
@ op_el_pow
Definition: ov.h:111
@ op_mul
Definition: ov.h:99
@ op_add
Definition: ov.h:97
@ op_sub
Definition: ov.h:98
@ op_el_mul
Definition: ov.h:109
@ op_le
Definition: ov.h:104
@ op_lt
Definition: ov.h:103
@ op_gt
Definition: ov.h:107
@ op_eq
Definition: ov.h:105
@ op_el_and
Definition: ov.h:113
@ op_el_div
Definition: ov.h:110
bool isobject(void) const
Definition: ov.h:620
bool is_undefined(void) const
Definition: ov.h:554
void error(const char *fmt,...)
Definition: error.cc:968
octave_value_list feval(const char *name, const octave_value_list &args, int nargout)
Evaluate an Octave function (built-in or interpreted) and return the list of result values.
Definition: oct-parse.cc:9580
symbol_table & __get_symbol_table__(const std::string &who)
static octave_value oct_binop_or(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:194
static octave_value oct_binop_times(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:189
static octave_value oct_binop_mldivide(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:182
static octave_value oct_unop_uplus(const octave_value &a)
Definition: op-class.cc:115
static octave_value oct_binop_mpower(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:181
static octave_value oct_binop_power(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:191
#define DEF_CLASS_BINOP(opname)
Helper macro to define binary class operators.
Definition: op-class.cc:170
static octave_value oct_binop_mtimes(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:179
static octave_value oct_binop_le(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:184
static octave_value oct_unop_not(const octave_value &a)
Definition: op-class.cc:114
static octave_value oct_binop_ldivide(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:192
static octave_value oct_unop_uminus(const octave_value &a)
Definition: op-class.cc:116
static octave_value oct_binop_default(const octave_value &a1, const octave_value &a2, const std::string &opname)
Default binary class operator.
Definition: op-class.cc:138
void install_class_ops(octave::type_info &ti)
Definition: op-class.cc:198
static octave_value oct_binop_ne(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:188
static octave_value oct_unop_transpose(const octave_value &a)
Definition: op-class.cc:117
static octave_value oct_binop_lt(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:183
static octave_value oct_binop_gt(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:187
static octave_value oct_binop_rdivide(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:190
static octave_value oct_unop_default(const octave_value &a, const std::string &opname)
Default unary class operator.
Definition: op-class.cc:52
static octave_value oct_unop_ctranspose(const octave_value &a)
Definition: op-class.cc:118
static octave_value oct_binop_ge(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:186
static octave_value oct_binop_and(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:193
static octave_value oct_binop_eq(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:185
#define DEF_CLASS_UNOP(opname)
Helper macro to define unary class operators.
Definition: op-class.cc:107
static octave_value oct_binop_plus(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:177
static octave_value oct_binop_mrdivide(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:180
static octave_value oct_binop_minus(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:178
const octave_base_value & a2
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:211
static void transpose(octave_idx_type N, const octave_idx_type *ridx, const octave_idx_type *cidx, octave_idx_type *ridx2, octave_idx_type *cidx2)
Definition: symrcm.cc:389