GNU Octave  8.1.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-2023 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 
47 
48 //! Default unary class operator.
49 //!
50 //! @param a operand
51 //! @param opname operator name
52 
53 static octave_value
54 oct_unop_default (const octave_value& a, const std::string& opname)
55 {
56  std::string class_name = a.class_name ();
57 
58  octave::symbol_table& symtab = octave::__get_symbol_table__ ();
59 
60  octave_value meth = symtab.find_method (opname, class_name);
61 
62  if (meth.is_defined ())
63  {
64  // Call overloaded unary class operator.
66  ovl (a), 1);
67 
68  // Return first element if present.
69  if (tmp.length () > 0)
70  return tmp(0);
71 
72  return octave_value ();
73  }
74 
75  // Matlab compatibility: If (conjugate) transpose is not overloaded and
76  // the number of dimensions is maximal two, just transpose the array of
77  // that class.
78 
79  if ((opname == "transpose") || (opname == "ctranspose"))
80  {
81  if (a.ndims () > 2)
82  error ("%s not defined for N-D objects of %s class", opname.c_str (),
83  class_name.c_str ());
84 
85  if (a.is_classdef_object ())
86  {
87  // FIXME: Default transposition for classdef arrays.
88 
89  error ("%s method not defined for %s class", opname.c_str (),
90  class_name.c_str ());
91  }
92  else
93  {
94  const octave_class& v
95  = dynamic_cast<const octave_class&> (a.get_rep ());
96 
97  return octave_value (v.map_value ().transpose (),
98  v.class_name (),
100  }
101  }
102  else
103  error ("%s method not defined for %s class", opname.c_str (),
104  class_name.c_str ());
105 }
106 
107 //! Helper macro to define unary class operators.
108 
109 #define DEF_CLASS_UNOP(opname) \
110  static octave_value \
111  oct_unop_ ## opname (const octave_value& a) \
112  { \
113  return oct_unop_default (a, #opname); \
114  }
115 
116 DEF_CLASS_UNOP (not) // !a or ~a
117 DEF_CLASS_UNOP (uplus) // +a
118 DEF_CLASS_UNOP (uminus) // -a
120 DEF_CLASS_UNOP (ctranspose) // a'
121 #undef DEF_CLASS_UNOP
122 
123 //! Default binary class operator.
124 //!
125 //! @param a1 first operand
126 //! @param a2 second operand
127 //! @param opname operator name
128 //!
129 //! The operator precedence is as follows:
130 //!
131 //! 1. If exactly one of the operands is a user defined class object, then
132 //! the class method of that operand is invoked.
133 //!
134 //! 2. If both operands are user defined class objects, then
135 //! 2.1 The superior class method is invoked.
136 //! 2.2 The leftmost class method is invoked if both classes are the same
137 //! or their precedence is not defined by superiorto/inferiorto.
138 
139 static octave_value
141  const std::string& opname)
142 {
143  octave::symbol_table& symtab = octave::__get_symbol_table__ ();
144 
145  // Dispatch to first (leftmost) operand by default.
146  std::string dispatch_type = a1.class_name ();
147 
148  // Determine, if second operand takes precedence (see rules above).
149  if (! a1.isobject ()
150  || (a1.isobject () && a2.isobject ()
151  && symtab.is_superiorto (a2.class_name (), dispatch_type)))
152  dispatch_type = a2.class_name ();
153 
154  octave_value meth = symtab.find_method (opname, dispatch_type);
155 
156  if (meth.is_undefined ())
157  error ("%s method not defined for %s class", opname.c_str (),
158  dispatch_type.c_str ());
159 
161  ovl (a1, a2), 1);
162 
163  if (tmp.length () > 0)
164  return tmp(0);
165 
166  return octave_value ();
167 }
168 
169 //! Helper macro to define binary class operators.
170 
171 #define DEF_CLASS_BINOP(opname) \
172  static octave_value \
173  oct_binop_ ## opname (const octave_value& a1, const octave_value& a2) \
174  { \
175  return oct_binop_default (a1, a2, #opname); \
176  }
177 
178 DEF_CLASS_BINOP (plus) // a1 + a2
179 DEF_CLASS_BINOP (minus) // a1 - a2
180 DEF_CLASS_BINOP (mtimes) // a1 * a2
181 DEF_CLASS_BINOP (mrdivide) // a1 / a2
182 DEF_CLASS_BINOP (mpower) // a1 ^ a2
183 DEF_CLASS_BINOP (mldivide) // a1 \ a2
184 DEF_CLASS_BINOP (lt) // a1 < a2
185 DEF_CLASS_BINOP (le) // a1 <= a2
186 DEF_CLASS_BINOP (eq) // a1 <= a2
187 DEF_CLASS_BINOP (ge) // a1 >= a2
188 DEF_CLASS_BINOP (gt) // a1 > a2
189 DEF_CLASS_BINOP (ne) // a1 ~= a2 or a1 != a2
190 DEF_CLASS_BINOP (times) // a1 .* a2
191 DEF_CLASS_BINOP (rdivide) // a1 ./ a2
192 DEF_CLASS_BINOP (power) // a1 .^ a2
193 DEF_CLASS_BINOP (ldivide) // a1 .\ a2
194 DEF_CLASS_BINOP (and) // a1 & a2
195 DEF_CLASS_BINOP (or) // a1 | a2
196 #undef DEF_CLASS_BINOP
197 
198 void
199 install_class_ops (octave::type_info& ti)
200 {
201  ti.install_unary_class_op (octave_value::op_not, oct_unop_not);
202  ti.install_unary_class_op (octave_value::op_uplus, oct_unop_uplus);
203  ti.install_unary_class_op (octave_value::op_uminus, oct_unop_uminus);
204  ti.install_unary_class_op (octave_value::op_transpose, oct_unop_transpose);
205  ti.install_unary_class_op (octave_value::op_hermitian, oct_unop_ctranspose);
206 
207  ti.install_binary_class_op (octave_value::op_add, oct_binop_plus);
208  ti.install_binary_class_op (octave_value::op_sub, oct_binop_minus);
209  ti.install_binary_class_op (octave_value::op_mul, oct_binop_mtimes);
210  ti.install_binary_class_op (octave_value::op_div, oct_binop_mrdivide);
211  ti.install_binary_class_op (octave_value::op_pow, oct_binop_mpower);
212  ti.install_binary_class_op (octave_value::op_ldiv, oct_binop_mldivide);
213  ti.install_binary_class_op (octave_value::op_lt, oct_binop_lt);
214  ti.install_binary_class_op (octave_value::op_le, oct_binop_le);
215  ti.install_binary_class_op (octave_value::op_eq, oct_binop_eq);
216  ti.install_binary_class_op (octave_value::op_ge, oct_binop_ge);
217  ti.install_binary_class_op (octave_value::op_gt, oct_binop_gt);
218  ti.install_binary_class_op (octave_value::op_ne, oct_binop_ne);
219  ti.install_binary_class_op (octave_value::op_el_mul, oct_binop_times);
220  ti.install_binary_class_op (octave_value::op_el_div, oct_binop_rdivide);
221  ti.install_binary_class_op (octave_value::op_el_pow, oct_binop_power);
222  ti.install_binary_class_op (octave_value::op_el_ldiv, oct_binop_ldivide);
223  ti.install_binary_class_op (octave_value::op_el_and, oct_binop_and);
224  ti.install_binary_class_op (octave_value::op_el_or, oct_binop_or);
225 }
226 
OCTAVE_END_NAMESPACE(octave)
virtual bool isobject(void) const
Definition: ov-base.h:433
virtual std::string class_name(void) const
Definition: ov-base.h:932
std::list< std::string > parent_class_name_list(void) const
Definition: ov-class.h:176
std::string class_name(void) const
Definition: ov-class.h:225
octave_map map_value(void) const
Definition: ov-class.h:172
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:700
OCTINTERP_API octave_function * function_value(bool silent=false) const
const octave_base_value & get_rep(void) const
Definition: ov.h:1483
@ op_hermitian
Definition: ov.h:82
@ op_uminus
Definition: ov.h:80
@ op_not
Definition: ov.h:78
@ op_transpose
Definition: ov.h:81
@ op_uplus
Definition: ov.h:79
bool is_defined(void) const
Definition: ov.h:637
std::string class_name(void) const
Definition: ov.h:1454
int ndims(void) const
Definition: ov.h:596
@ op_ldiv
Definition: ov.h:96
@ op_ne
Definition: ov.h:102
@ op_el_or
Definition: ov.h:108
@ op_el_ldiv
Definition: ov.h:106
@ op_pow
Definition: ov.h:95
@ op_ge
Definition: ov.h:100
@ op_div
Definition: ov.h:94
@ op_el_pow
Definition: ov.h:105
@ op_mul
Definition: ov.h:93
@ op_add
Definition: ov.h:91
@ op_sub
Definition: ov.h:92
@ op_el_mul
Definition: ov.h:103
@ op_le
Definition: ov.h:98
@ op_lt
Definition: ov.h:97
@ op_gt
Definition: ov.h:101
@ op_eq
Definition: ov.h:99
@ op_el_and
Definition: ov.h:107
@ op_el_div
Definition: ov.h:104
bool isobject(void) const
Definition: ov.h:709
bool is_undefined(void) const
Definition: ov.h:640
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void error(const char *fmt,...)
Definition: error.cc:979
symbol_table & __get_symbol_table__(void)
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:10370
static octave_value oct_binop_or(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:195
static octave_value oct_binop_times(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:190
static octave_value oct_binop_mldivide(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:183
static octave_value oct_unop_uplus(const octave_value &a)
Definition: op-class.cc:117
static octave_value oct_binop_mpower(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:182
static octave_value oct_binop_power(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:192
#define DEF_CLASS_BINOP(opname)
Helper macro to define binary class operators.
Definition: op-class.cc:171
static octave_value oct_binop_mtimes(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:180
static octave_value oct_binop_le(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:185
static octave_value oct_unop_not(const octave_value &a)
Definition: op-class.cc:116
static octave_value oct_binop_ldivide(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:193
static octave_value oct_unop_uminus(const octave_value &a)
Definition: op-class.cc:118
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:140
void install_class_ops(octave::type_info &ti)
Definition: op-class.cc:199
static octave_value oct_binop_ne(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:189
static octave_value oct_unop_transpose(const octave_value &a)
Definition: op-class.cc:119
static octave_value oct_binop_lt(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:184
static octave_value oct_binop_gt(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:188
static octave_value oct_binop_rdivide(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:191
static octave_value oct_unop_default(const octave_value &a, const std::string &opname)
Default unary class operator.
Definition: op-class.cc:54
static octave_value oct_unop_ctranspose(const octave_value &a)
Definition: op-class.cc:120
static octave_value oct_binop_ge(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:187
static octave_value oct_binop_and(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:194
static octave_value oct_binop_eq(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:186
#define DEF_CLASS_UNOP(opname)
Helper macro to define unary class operators.
Definition: op-class.cc:109
static octave_value oct_binop_plus(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:178
static octave_value oct_binop_mrdivide(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:181
static octave_value oct_binop_minus(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:179
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:391