GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
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