GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ops.h
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2024 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 (octave_ops_h)
27 #define octave_ops_h 1
28 
29 #include "octave-config.h"
30 
31 #include "Array-util.h"
32 #include "error.h"
33 
35 
36 class type_info;
37 
38 OCTAVE_END_NAMESPACE(octave)
39 
40 // NOTE: If OCTAVE_ENABLE_INTERNAL_CHECKS is defined, then
41 // OCTAVE_DYNAMIC_CAST is only safe if you can ensure that the cast will
42 // succeed. Using static_cast disables the RTTI checks used by
43 // dynamic_cast that ensure an unsuccesful cast will either throw an
44 // error for reference types or or return nullptr for pointer types.
45 
46 #if defined (OCTAVE_ENABLE_INTERNAL_CHECKS)
47 # define OCTAVE_DYNAMIC_CAST dynamic_cast
48 #else
49 # define OCTAVE_DYNAMIC_CAST static_cast
50 #endif
51 
52 #define OCTAVE_CAST_BASE_VALUE(T, T_VAL, BASE_VAL) \
53  T T_VAL = OCTAVE_DYNAMIC_CAST<T> (BASE_VAL)
54 
55 // Concatenation macros that enforce argument prescan
56 #define CONCAT2X(x, y) x ## y
57 #define CONCAT2(x, y) CONCAT2X (x, y)
58 
59 #define CONCAT3X(x, y, z) x ## y ## z
60 #define CONCAT3(x, y, z) CONCAT3X (x, y, z)
61 
62 #define INSTALL_UNOP_TI(ti, op, t, f) \
63  ti.install_unary_op \
64  (octave_value::op, t::static_type_id (), CONCAT2 (oct_unop_, f));
65 
66 #define INSTALL_NCUNOP_TI(ti, op, t, f) \
67  ti.install_non_const_unary_op \
68  (octave_value::op, t::static_type_id (), CONCAT2 (oct_unop_, f));
69 
70 #define INSTALL_BINOP_TI(ti, op, t1, t2, f) \
71  ti.install_binary_op \
72  (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
73  CONCAT2 (oct_binop_, f));
74 
75 #define INSTALL_CATOP_TI(ti, t1, t2, f) \
76  ti.install_cat_op \
77  (t1::static_type_id (), t2::static_type_id (), CONCAT2 (oct_catop_, f));
78 
79 #define INSTALL_ASSIGNOP_TI(ti, op, t1, t2, f) \
80  ti.install_assign_op \
81  (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
82  CONCAT2 (oct_assignop_, f));
83 
84 #define INSTALL_ASSIGNANYOP_TI(ti, op, t1, f) \
85  ti.install_assignany_op \
86  (octave_value::op, t1::static_type_id (), CONCAT2 (oct_assignop_, f));
87 
88 #define INSTALL_ASSIGNCONV_TI(ti, t1, t2, tr) \
89  ti.install_pref_assign_conv \
90  (t1::static_type_id (), t2::static_type_id (), tr::static_type_id ());
91 
92 #define INSTALL_WIDENOP_TI(ti, t1, t2, f) \
93  ti.install_widening_op \
94  (t1::static_type_id (), t2::static_type_id (), CONCAT2 (oct_conv_, f));
95 
96 #define DEFASSIGNOP(name, t1, t2) \
97  static octave_value \
98  CONCAT2 (oct_assignop_, name) (octave_base_value& a1, \
99  const octave_value_list& idx, \
100  const octave_base_value& a2)
101 
102 #define DEFASSIGNOP_FN(name, t1, t2, f) \
103  static octave_value \
104  CONCAT2 (oct_assignop_, name) (octave_base_value& a1, \
105  const octave_value_list& idx, \
106  const octave_base_value& a2) \
107  { \
108  OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1); \
109  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
110  \
111  v1.f (idx, v2.CONCAT2 (t1, _value) ()); \
112  return octave_value (); \
113  }
114 
115 #define DEFNULLASSIGNOP_FN(name, t, f) \
116  static octave_value \
117  CONCAT2 (oct_assignop_, name) (octave_base_value& a, \
118  const octave_value_list& idx, \
119  const octave_base_value&) \
120  { \
121  OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t)&, v, a); \
122  \
123  v.f (idx); \
124  return octave_value (); \
125  }
126 
127 #define DEFNDASSIGNOP_FN(name, t1, t2, e, f) \
128  static octave_value \
129  CONCAT2 (oct_assignop_, name) (octave_base_value& a1, \
130  const octave_value_list& idx, \
131  const octave_base_value& a2) \
132  { \
133  OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1); \
134  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
135  \
136  v1.f (idx, v2.CONCAT2 (e, _value) ()); \
137  return octave_value (); \
138  }
139 
140 // FIXME: the following currently don't handle index.
141 #define DEFNDASSIGNOP_OP(name, t1, t2, f, op) \
142  static octave_value \
143  CONCAT2 (oct_assignop_, name) (octave_base_value& a1, \
144  const octave_value_list& idx, \
145  const octave_base_value& a2) \
146  { \
147  OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1); \
148  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
149  \
150  error_unless (idx.empty ()); \
151  v1.matrix_ref () op v2.CONCAT2 (f, _value) (); \
152  \
153  return octave_value (); \
154  }
155 
156 #define DEFNDASSIGNOP_FNOP(name, t1, t2, f, fnop) \
157  static octave_value \
158  CONCAT2 (oct_assignop_, name) (octave_base_value& a1, \
159  const octave_value_list& idx, \
160  const octave_base_value& a2) \
161  { \
162  OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1); \
163  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
164  \
165  error_unless (idx.empty ()); \
166  fnop (v1.matrix_ref (), v2.CONCAT2 (f, _value) ()); \
167  \
168  return octave_value (); \
169  }
170 
171 #define DEFASSIGNANYOP_FN(name, t1, f) \
172  static octave_value \
173  CONCAT2 (oct_assignop_, name) (octave_base_value& a1, \
174  const octave_value_list& idx, \
175  const octave_value& a2) \
176  { \
177  OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1); \
178  \
179  v1.f (idx, a2); \
180  return octave_value (); \
181  }
182 
183 #define CONVDECL(name) \
184  static octave_base_value * \
185  CONCAT2 (oct_conv_, name) (const octave_base_value& a)
186 
187 #define DEFCONV(name, a_dummy, b_dummy) \
188  CONVDECL (name)
189 
190 #define DEFUNOPX(name, t) \
191  static octave_value \
192  CONCAT2 (oct_unop_, name) (const octave_base_value&)
193 
194 #define DEFUNOP(name, t) \
195  static octave_value \
196  CONCAT2 (oct_unop_, name) (const octave_base_value& a)
197 
198 #define DEFUNOP_OP(name, t, op) \
199  static octave_value \
200  CONCAT2 (oct_unop_, name) (const octave_base_value& a) \
201  { \
202  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t)&, v, a); \
203  return octave_value (op v.CONCAT2 (t, _value) ()); \
204  }
205 
206 #define DEFNDUNOP_OP(name, t, e, op) \
207  static octave_value \
208  CONCAT2 (oct_unop_, name) (const octave_base_value& a) \
209  { \
210  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t)&, v, a); \
211  return octave_value (op v.CONCAT2 (e, _value) ()); \
212  }
213 
214 // FIXME: in some cases, the constructor isn't necessary.
215 
216 #define DEFUNOP_FN(name, t, f) \
217  static octave_value \
218  CONCAT2 (oct_unop_, name) (const octave_base_value& a) \
219  { \
220  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t)&, v, a); \
221  return octave_value (f (v.CONCAT2 (t, _value) ())); \
222  }
223 
224 #define DEFNDUNOP_FN(name, t, e, f) \
225  static octave_value \
226  CONCAT2 (oct_unop_, name) (const octave_base_value& a) \
227  { \
228  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t)&, v, a); \
229  return octave_value (f (v.CONCAT2 (e, _value) ())); \
230  }
231 
232 #define DEFNCUNOP_METHOD(name, t, method) \
233  static void \
234  CONCAT2 (oct_unop_, name) (octave_base_value& a) \
235  { \
236  OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t)&, v, a); \
237  v.method (); \
238  }
239 
240 #define DEFBINOPX(name, t1, t2) \
241  static octave_value \
242  CONCAT2 (oct_binop_, name) (const octave_base_value&, \
243  const octave_base_value&)
244 
245 #define DEFBINOP(name, t1, t2) \
246  static octave_value \
247  CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
248  const octave_base_value& a2)
249 
250 #define DEFBINOP_OP(name, t1, t2, op) \
251  static octave_value \
252  CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
253  const octave_base_value& a2) \
254  { \
255  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
256  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
257  \
258  return octave_value \
259  (v1.CONCAT2 (t1, _value) () op v2.CONCAT2 (t2, _value) ()); \
260  }
261 
262 #define DEFCMPLXCMPOP_OP(name, t1, t2, op) \
263  static octave_value \
264  CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
265  const octave_base_value& a2) \
266  { \
267  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
268  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
269  \
270  warn_complex_cmp (); \
271  \
272  return octave_value \
273  (v1.CONCAT2 (t1, _value) () op v2.CONCAT2 (t2, _value) ()); \
274  }
275 
276 #define DEFSCALARBOOLOP_OP(name, t1, t2, op) \
277  static octave_value \
278  CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
279  const octave_base_value& a2) \
280  { \
281  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
282  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
283  \
284  if (octave::math::isnan (v1.CONCAT2 (t1, _value) ()) || octave::math::isnan (v2.CONCAT2 (t2, _value) ())) \
285  octave::err_nan_to_logical_conversion (); \
286  \
287  return octave_value \
288  (v1.CONCAT2 (t1, _value) () op v2.CONCAT2 (t2, _value) ()); \
289  }
290 
291 #define DEFNDBINOP_OP(name, t1, t2, e1, e2, op) \
292  static octave_value \
293  CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
294  const octave_base_value& a2) \
295  { \
296  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
297  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
298  \
299  return octave_value \
300  (v1.CONCAT2 (e1, _value) () op v2.CONCAT2 (e2, _value) ()); \
301  }
302 
303 // FIXME: in some cases, the constructor isn't necessary.
304 
305 #define DEFBINOP_FN(name, t1, t2, f) \
306  static octave_value \
307  CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
308  const octave_base_value& a2) \
309  { \
310  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
311  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
312  \
313  return octave_value (f (v1.CONCAT2 (t1, _value) (), v2.CONCAT2 (t2, _value) ())); \
314  }
315 
316 #define DEFNDBINOP_FN(name, t1, t2, e1, e2, f) \
317  static octave_value \
318  CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
319  const octave_base_value& a2) \
320  { \
321  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
322  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
323  \
324  return octave_value (f (v1.CONCAT2 (e1, _value) (), v2.CONCAT2 (e2, _value) ())); \
325  }
326 
327 #define DEFNDCMPLXCMPOP_FN(name, t1, t2, e1, e2, f) \
328  static octave_value \
329  CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
330  const octave_base_value& a2) \
331  { \
332  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
333  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
334  \
335  return octave_value (f (v1.CONCAT2 (e1, _value) (), v2.CONCAT2 (e2, _value) ())); \
336  }
337 
338 #define DEFCATOPX(name, t1, t2) \
339  static octave_value \
340  CONCAT2 (oct_catop_, name) (const octave_base_value&, \
341  const octave_base_value&, \
342  const Array<octave_idx_type>& ra_idx)
343 
344 #define DEFCATOP(name, t1, t2) \
345  static octave_value \
346  CONCAT2 (oct_catop_, name) (const octave_base_value& a1, \
347  const octave_base_value& a2, \
348  const Array<octave_idx_type>& ra_idx)
349 
350 // FIXME: in some cases, the constructor isn't necessary.
351 
352 #define DEFCATOP_FN(name, t1, t2, f) \
353  static octave_value \
354  CONCAT2 (oct_catop_, name) (const octave_base_value& a1, \
355  const octave_base_value& a2, \
356  const Array<octave_idx_type>& ra_idx) \
357  { \
358  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
359  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
360  \
361  return octave_value (v1.CONCAT2 (t1, _value) () . f (v2.CONCAT2 (t2, _value) (), ra_idx)); \
362  }
363 
364 #define DEFNDCATOP_FN(name, t1, t2, e1, e2, f) \
365  static octave_value \
366  CONCAT2 (oct_catop_, name) (const octave_base_value& a1, \
367  const octave_base_value& a2, \
368  const Array<octave_idx_type>& ra_idx) \
369  { \
370  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
371  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
372  \
373  return octave_value (v1.CONCAT2 (e1, _value) () . f (v2.CONCAT2 (e2, _value) (), ra_idx)); \
374  }
375 
376 #define DEFNDCHARCATOP_FN(name, t1, t2, f) \
377  static octave_value \
378  CONCAT2 (oct_catop_, name) (const octave_base_value& a1, \
379  const octave_base_value& a2, \
380  const Array<octave_idx_type>& ra_idx) \
381  { \
382  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
383  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
384  \
385  return octave_value (v1.char_array_value () . f (v2.char_array_value (), ra_idx), \
386  ((a1.is_sq_string () || a2.is_sq_string ()) \
387  ? '\'' : '"')); \
388  }
389 
390 // For compatibility, the second arg is always converted to the type
391 // of the first. Hmm.
392 
393 #define DEFNDCATOP_FN2(name, t1, t2, tc1, tc2, e1, e2, f) \
394  static octave_value \
395  CONCAT2 (oct_catop_, name) (const octave_base_value& a1, \
396  const octave_base_value& a2, \
397  const Array<octave_idx_type>& ra_idx) \
398  { \
399  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
400  OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
401  \
402  return octave_value (tc1 (v1.CONCAT2 (e1, _value) ()) . f (tc2 (v2.CONCAT2 (e2, _value) ()), ra_idx)); \
403  }
404 
405 #endif
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn