GNU Octave 7.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-2022 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
46OCTAVE_NAMESPACE_BEGIN
47
48//! Default unary class operator.
49//!
50//! @param a operand
51//! @param opname operator name
52
53static octave_value
54oct_unop_default (const octave_value& a, const std::string& opname)
55{
56 std::string class_name = a.class_name ();
57
58 octave_value meth
59 = octave::__get_symbol_table__ ("oct_unop_" + opname)
60 .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
116DEF_CLASS_UNOP (not) // !a or ~a
117DEF_CLASS_UNOP (uplus) // +a
118DEF_CLASS_UNOP (uminus) // -a
120DEF_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
139static octave_value
141 const std::string& opname)
142{
143 octave::symbol_table& symtab
144 = octave::__get_symbol_table__ ("oct_binop_" + opname);
145
146 // Dispatch to first (leftmost) operand by default.
147 std::string dispatch_type = a1.class_name ();
148
149 // Determine, if second operand takes precedence (see rules above).
150 if (! a1.isobject ()
151 || (a1.isobject () && a2.isobject ()
152 && symtab.is_superiorto (a2.class_name (), dispatch_type)))
153 dispatch_type = a2.class_name ();
154
155 octave_value meth = symtab.find_method (opname, dispatch_type);
156
157 if (meth.is_undefined ())
158 error ("%s method not defined for %s class", opname.c_str (),
159 dispatch_type.c_str ());
160
162 ovl (a1, a2), 1);
163
164 if (tmp.length () > 0)
165 return tmp(0);
166
167 return octave_value ();
168}
169
170//! Helper macro to define binary class operators.
171
172#define DEF_CLASS_BINOP(opname) \
173 static octave_value \
174 oct_binop_ ## opname (const octave_value& a1, const octave_value& a2) \
175 { \
176 return oct_binop_default (a1, a2, #opname); \
177 }
178
179DEF_CLASS_BINOP (plus) // a1 + a2
180DEF_CLASS_BINOP (minus) // a1 - a2
181DEF_CLASS_BINOP (mtimes) // a1 * a2
182DEF_CLASS_BINOP (mrdivide) // a1 / a2
183DEF_CLASS_BINOP (mpower) // a1 ^ a2
184DEF_CLASS_BINOP (mldivide) // a1 \ a2
185DEF_CLASS_BINOP (lt) // a1 < a2
186DEF_CLASS_BINOP (le) // a1 <= a2
187DEF_CLASS_BINOP (eq) // a1 <= a2
188DEF_CLASS_BINOP (ge) // a1 >= a2
189DEF_CLASS_BINOP (gt) // a1 > a2
190DEF_CLASS_BINOP (ne) // a1 ~= a2 or a1 != a2
191DEF_CLASS_BINOP (times) // a1 .* a2
192DEF_CLASS_BINOP (rdivide) // a1 ./ a2
193DEF_CLASS_BINOP (power) // a1 .^ a2
194DEF_CLASS_BINOP (ldivide) // a1 .\ a2
195DEF_CLASS_BINOP (and) // a1 & a2
196DEF_CLASS_BINOP (or) // a1 | a2
197#undef DEF_CLASS_BINOP
198
199void
200install_class_ops (octave::type_info& ti)
201{
202 ti.install_unary_class_op (octave_value::op_not, oct_unop_not);
203 ti.install_unary_class_op (octave_value::op_uplus, oct_unop_uplus);
204 ti.install_unary_class_op (octave_value::op_uminus, oct_unop_uminus);
205 ti.install_unary_class_op (octave_value::op_transpose, oct_unop_transpose);
206 ti.install_unary_class_op (octave_value::op_hermitian, oct_unop_ctranspose);
207
208 ti.install_binary_class_op (octave_value::op_add, oct_binop_plus);
209 ti.install_binary_class_op (octave_value::op_sub, oct_binop_minus);
210 ti.install_binary_class_op (octave_value::op_mul, oct_binop_mtimes);
211 ti.install_binary_class_op (octave_value::op_div, oct_binop_mrdivide);
212 ti.install_binary_class_op (octave_value::op_pow, oct_binop_mpower);
213 ti.install_binary_class_op (octave_value::op_ldiv, oct_binop_mldivide);
214 ti.install_binary_class_op (octave_value::op_lt, oct_binop_lt);
215 ti.install_binary_class_op (octave_value::op_le, oct_binop_le);
216 ti.install_binary_class_op (octave_value::op_eq, oct_binop_eq);
217 ti.install_binary_class_op (octave_value::op_ge, oct_binop_ge);
218 ti.install_binary_class_op (octave_value::op_gt, oct_binop_gt);
219 ti.install_binary_class_op (octave_value::op_ne, oct_binop_ne);
220 ti.install_binary_class_op (octave_value::op_el_mul, oct_binop_times);
221 ti.install_binary_class_op (octave_value::op_el_div, oct_binop_rdivide);
222 ti.install_binary_class_op (octave_value::op_el_pow, oct_binop_power);
223 ti.install_binary_class_op (octave_value::op_el_ldiv, oct_binop_ldivide);
224 ti.install_binary_class_op (octave_value::op_el_and, oct_binop_and);
225 ti.install_binary_class_op (octave_value::op_el_or, oct_binop_or);
226}
227
228OCTAVE_NAMESPACE_END
virtual bool isobject(void) const
Definition: ov-base.h:425
virtual std::string class_name(void) const
Definition: ov-base.h:922
std::string class_name(void) const
Definition: ov-class.h:223
octave_map map_value(void) const
Definition: ov-class.h:171
std::list< std::string > parent_class_name_list(void) const
Definition: ov-class.h:175
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
@ 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:1451
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
const octave_base_value & get_rep(void) const
Definition: ov.h:1480
bool isobject(void) const
Definition: ov.h:709
bool is_undefined(void) const
Definition: ov.h:640
octave_value find_method(const std::string &name, const std::string &dispatch_type)
Definition: symtab.cc:125
void error(const char *fmt,...)
Definition: error.cc:980
OCTINTERP_API octave_value_list feval(const char *name, const octave_value_list &args=octave_value_list(), int nargout=0)
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:196
static octave_value oct_binop_times(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:191
static octave_value oct_binop_mldivide(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:184
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:183
static octave_value oct_binop_power(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:193
#define DEF_CLASS_BINOP(opname)
Helper macro to define binary class operators.
Definition: op-class.cc:172
static octave_value oct_binop_mtimes(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:181
static octave_value oct_binop_le(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:186
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:194
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:200
static octave_value oct_binop_ne(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:190
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:185
static octave_value oct_binop_gt(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:189
static octave_value oct_binop_rdivide(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:192
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:188
static octave_value oct_binop_and(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:195
static octave_value oct_binop_eq(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:187
#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:179
static OCTAVE_NAMESPACE_BEGIN 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_binop_mrdivide(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:182
static octave_value oct_binop_minus(const octave_value &a1, const octave_value &a2)
Definition: op-class.cc:180
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