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