GNU Octave  4.4.1
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-2018 John W. Eaton
4 Copyright (C) 2009 VZLU Prague, a.s.
5 
6 This file is part of Octave.
7 
8 Octave is free software: you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <https://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if ! defined (octave_ops_h)
25 #define octave_ops_h 1
26 
27 #include "octave-config.h"
28 
29 #include "Array-util.h"
30 
31 namespace octave
32 {
33  class type_info;
34 }
35 
36 // Concatenation macros that enforce argument prescan
37 #define CONCAT2X(x, y) x ## y
38 #define CONCAT2(x, y) CONCAT2X (x, y)
39 
40 #define CONCAT3X(x, y, z) x ## y ## z
41 #define CONCAT3(x, y, z) CONCAT3X (x, y, z)
42 
43 extern void install_ops (octave::type_info&);
44 
45 #define INSTALL_UNOP_TI(ti, op, t, f) \
46  ti.install_unary_op \
47  (octave_value::op, t::static_type_id (), CONCAT2 (oct_unop_, f));
48 
49 #define INSTALL_NCUNOP_TI(ti, op, t, f) \
50  ti.install_non_const_unary_op \
51  (octave_value::op, t::static_type_id (), CONCAT2 (oct_unop_, f));
52 
53 #define INSTALL_BINOP_TI(ti, op, t1, t2, f) \
54  ti.install_binary_op \
55  (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
56  CONCAT2 (oct_binop_, f));
57 
58 #define INSTALL_CATOP_TI(ti, t1, t2, f) \
59  ti.install_cat_op \
60  (t1::static_type_id (), t2::static_type_id (), CONCAT2 (oct_catop_, f));
61 
62 #define INSTALL_ASSIGNOP_TI(ti, op, t1, t2, f) \
63  ti.install_assign_op \
64  (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
65  CONCAT2 (oct_assignop_, f));
66 
67 #define INSTALL_ASSIGNANYOP_TI(ti, op, t1, f) \
68  ti.install_assignany_op \
69  (octave_value::op, t1::static_type_id (), CONCAT2 (oct_assignop_, f));
70 
71 #define INSTALL_ASSIGNCONV_TI(ti, t1, t2, tr) \
72  ti.install_pref_assign_conv \
73  (t1::static_type_id (), t2::static_type_id (), tr::static_type_id ());
74 
75 #define INSTALL_WIDENOP_TI(ti, t1, t2, f) \
76  ti.install_widening_op \
77  (t1::static_type_id (), t2::static_type_id (), CONCAT2 (oct_conv_, f));
78 
79 // The following INSTALL_* macros are obsolete.
80 
81 #define INSTALL_UNOP(op, t, f) \
82  octave_value_typeinfo::register_unary_op \
83  (octave_value::op, t::static_type_id (), CONCAT2 (oct_unop_, f));
84 
85 #define INSTALL_NCUNOP(op, t, f) \
86  octave_value_typeinfo::register_non_const_unary_op \
87  (octave_value::op, t::static_type_id (), CONCAT2 (oct_unop_, f));
88 
89 #define INSTALL_BINOP(op, t1, t2, f) \
90  octave_value_typeinfo::register_binary_op \
91  (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
92  CONCAT2 (oct_binop_, f));
93 
94 #define INSTALL_CATOP(t1, t2, f) \
95  octave_value_typeinfo::register_cat_op \
96  (t1::static_type_id (), t2::static_type_id (), CONCAT2 (oct_catop_, f));
97 
98 #define INSTALL_ASSIGNOP(op, t1, t2, f) \
99  octave_value_typeinfo::register_assign_op \
100  (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
101  CONCAT2 (oct_assignop_, f));
102 
103 #define INSTALL_ASSIGNANYOP(op, t1, f) \
104  octave_value_typeinfo::register_assignany_op \
105  (octave_value::op, t1::static_type_id (), CONCAT2 (oct_assignop_, f));
106 
107 #define INSTALL_ASSIGNCONV(t1, t2, tr) \
108  octave_value_typeinfo::register_pref_assign_conv \
109  (t1::static_type_id (), t2::static_type_id (), tr::static_type_id ());
110 
111 #define INSTALL_WIDENOP(t1, t2, f) \
112  octave_value_typeinfo::register_widening_op \
113  (t1::static_type_id (), t2::static_type_id (), CONCAT2 (oct_conv_, f));
114 
115 #define DEFASSIGNOP(name, t1, t2) \
116  static octave_value \
117  CONCAT2 (oct_assignop_, name) (octave_base_value& a1, \
118  const octave_value_list& idx, \
119  const octave_base_value& a2)
120 
121 #define DEFASSIGNOP_FN(name, t1, t2, f) \
122  static octave_value \
123  CONCAT2 (oct_assignop_, name) (octave_base_value& a1, \
124  const octave_value_list& idx, \
125  const octave_base_value& a2) \
126  { \
127  CONCAT2 (octave_, t1)& v1 = dynamic_cast<CONCAT2 (octave_, t1)&> (a1); \
128  const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
129  \
130  v1.f (idx, v2.CONCAT2 (t1, _value) ()); \
131  return octave_value (); \
132  }
133 
134 #define DEFNULLASSIGNOP_FN(name, t, f) \
135  static octave_value \
136  CONCAT2 (oct_assignop_, name) (octave_base_value& a, \
137  const octave_value_list& idx, \
138  const octave_base_value&) \
139  { \
140  CONCAT2 (octave_, t)& v = dynamic_cast<CONCAT2 (octave_, t)&> (a); \
141  \
142  v.f (idx); \
143  return octave_value (); \
144  }
145 
146 #define DEFNDASSIGNOP_FN(name, t1, t2, e, f) \
147  static octave_value \
148  CONCAT2 (oct_assignop_, name) (octave_base_value& a1, \
149  const octave_value_list& idx, \
150  const octave_base_value& a2) \
151  { \
152  CONCAT2 (octave_, t1)& v1 = dynamic_cast<CONCAT2 (octave_, t1)&> (a1); \
153  const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
154  \
155  v1.f (idx, v2.CONCAT2 (e, _value) ()); \
156  return octave_value (); \
157  }
158 
159 // FIXME: the following currently don't handle index.
160 #define DEFNDASSIGNOP_OP(name, t1, t2, f, op) \
161  static octave_value \
162  CONCAT2 (oct_assignop_, name) (octave_base_value& a1, \
163  const octave_value_list& idx, \
164  const octave_base_value& a2) \
165  { \
166  CONCAT2 (octave_, t1)& v1 = dynamic_cast<CONCAT2 (octave_, t1)&> (a1); \
167  const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
168  \
169  assert (idx.empty ()); \
170  v1.matrix_ref () op v2.CONCAT2 (f, _value) (); \
171  \
172  return octave_value (); \
173  }
174 
175 #define DEFNDASSIGNOP_FNOP(name, t1, t2, f, fnop) \
176  static octave_value \
177  CONCAT2 (oct_assignop_, name) (octave_base_value& a1, \
178  const octave_value_list& idx, \
179  const octave_base_value& a2) \
180  { \
181  CONCAT2 (octave_, t1)& v1 = dynamic_cast<CONCAT2 (octave_, t1)&> (a1); \
182  const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
183  \
184  assert (idx.empty ()); \
185  fnop (v1.matrix_ref (), v2.CONCAT2 (f, _value) ()); \
186  \
187  return octave_value (); \
188  }
189 
190 #define DEFASSIGNANYOP_FN(name, t1, f) \
191  static octave_value \
192  CONCAT2 (oct_assignop_, name) (octave_base_value& a1, \
193  const octave_value_list& idx, \
194  const octave_value& a2) \
195  { \
196  CONCAT2 (octave_, t1)& v1 = dynamic_cast<CONCAT2 (octave_, t1)&> (a1); \
197  \
198  v1.f (idx, a2); \
199  return octave_value (); \
200  }
201 
202 #define CONVDECL(name) \
203  static octave_base_value * \
204  CONCAT2 (oct_conv_, name) (const octave_base_value& a)
205 
206 #define DEFCONV(name, a_dummy, b_dummy) \
207  CONVDECL (name)
208 
209 #define DEFUNOPX(name, t) \
210  static octave_value \
211  CONCAT2 (oct_unop_, name) (const octave_base_value&)
212 
213 #define DEFUNOP(name, t) \
214  static octave_value \
215  CONCAT2 (oct_unop_, name) (const octave_base_value& a)
216 
217 #define DEFUNOP_OP(name, t, op) \
218  static octave_value \
219  CONCAT2 (oct_unop_, name) (const octave_base_value& a) \
220  { \
221  const CONCAT2 (octave_, t)& v = dynamic_cast<const CONCAT2 (octave_, t)&> (a); \
222  return octave_value (op v.CONCAT2 (t, _value) ()); \
223  }
224 
225 #define DEFNDUNOP_OP(name, t, e, op) \
226  static octave_value \
227  CONCAT2 (oct_unop_, name) (const octave_base_value& a) \
228  { \
229  const CONCAT2 (octave_, t)& v = dynamic_cast<const CONCAT2 (octave_, t)&> (a); \
230  return octave_value (op v.CONCAT2 (e, _value) ()); \
231  }
232 
233 // FIXME: in some cases, the constructor isn't necessary.
234 
235 #define DEFUNOP_FN(name, t, f) \
236  static octave_value \
237  CONCAT2 (oct_unop_, name) (const octave_base_value& a) \
238  { \
239  const CONCAT2 (octave_, t)& v = dynamic_cast<const CONCAT2 (octave_, t)&> (a); \
240  return octave_value (f (v.CONCAT2 (t, _value) ())); \
241  }
242 
243 #define DEFNDUNOP_FN(name, t, e, f) \
244  static octave_value \
245  CONCAT2 (oct_unop_, name) (const octave_base_value& a) \
246  { \
247  const CONCAT2 (octave_, t)& v = dynamic_cast<const CONCAT2 (octave_, t)&> (a); \
248  return octave_value (f (v.CONCAT2 (e, _value) ())); \
249  }
250 
251 #define DEFNCUNOP_METHOD(name, t, method) \
252  static void \
253  CONCAT2 (oct_unop_, name) (octave_base_value& a) \
254  { \
255  CONCAT2 (octave_, t)& v = dynamic_cast<CONCAT2 (octave_, t)&> (a); \
256  v.method (); \
257  }
258 
259 #define DEFBINOPX(name, t1, t2) \
260  static octave_value \
261  CONCAT2 (oct_binop_, name) (const octave_base_value&, \
262  const octave_base_value&)
263 
264 #define DEFBINOP(name, t1, t2) \
265  static octave_value \
266  CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
267  const octave_base_value& a2)
268 
269 #define DEFBINOP_OP(name, t1, t2, op) \
270  static octave_value \
271  CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
272  const octave_base_value& a2) \
273  { \
274  const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
275  const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
276  \
277  return octave_value \
278  (v1.CONCAT2 (t1, _value) () op v2.CONCAT2 (t2, _value) ()); \
279  }
280 
281 #define DEFCMPLXCMPOP_OP(name, t1, t2, op) \
282  static octave_value \
283  CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
284  const octave_base_value& a2) \
285  { \
286  const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
287  const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
288  \
289  warn_complex_cmp (); \
290  \
291  return octave_value \
292  (v1.CONCAT2 (t1, _value) () op v2.CONCAT2 (t2, _value) ()); \
293  }
294 
295 #define DEFSCALARBOOLOP_OP(name, t1, t2, op) \
296  static octave_value \
297  CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
298  const octave_base_value& a2) \
299  { \
300  const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
301  const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
302  \
303  if (octave::math::isnan (v1.CONCAT2 (t1, _value) ()) || octave::math::isnan (v2.CONCAT2 (t2, _value) ())) \
304  octave::err_nan_to_logical_conversion (); \
305  \
306  return octave_value \
307  (v1.CONCAT2 (t1, _value) () op v2.CONCAT2 (t2, _value) ()); \
308  }
309 
310 #define DEFNDBINOP_OP(name, t1, t2, e1, e2, op) \
311  static octave_value \
312  CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
313  const octave_base_value& a2) \
314  { \
315  const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
316  const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
317  \
318  return octave_value \
319  (v1.CONCAT2 (e1, _value) () op v2.CONCAT2 (e2, _value) ()); \
320  }
321 
322 // FIXME: in some cases, the constructor isn't necessary.
323 
324 #define DEFBINOP_FN(name, t1, t2, f) \
325  static octave_value \
326  CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
327  const octave_base_value& a2) \
328  { \
329  const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
330  const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
331  \
332  return octave_value (f (v1.CONCAT2 (t1, _value) (), v2.CONCAT2 (t2, _value) ())); \
333  }
334 
335 #define DEFNDBINOP_FN(name, t1, t2, e1, e2, f) \
336  static octave_value \
337  CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
338  const octave_base_value& a2) \
339  { \
340  const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
341  const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
342  \
343  return octave_value (f (v1.CONCAT2 (e1, _value) (), v2.CONCAT2 (e2, _value) ())); \
344  }
345 
346 #define DEFNDCMPLXCMPOP_FN(name, t1, t2, e1, e2, f) \
347  static octave_value \
348  CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
349  const octave_base_value& a2) \
350  { \
351  const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
352  const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
353  \
354  return octave_value (f (v1.CONCAT2 (e1, _value) (), v2.CONCAT2 (e2, _value) ())); \
355  }
356 
357 #define DEFCATOPX(name, t1, t2) \
358  static octave_value \
359  CONCAT2 (oct_catop_, name) (octave_base_value&, const octave_base_value&, \
360  const Array<octave_idx_type>& ra_idx)
361 
362 #define DEFCATOP(name, t1, t2) \
363  static octave_value \
364  CONCAT2 (oct_catop_, name) (octave_base_value& a1, \
365  const octave_base_value& a2, \
366  const Array<octave_idx_type>& ra_idx)
367 
368 // FIXME: in some cases, the constructor isn't necessary.
369 
370 #define DEFCATOP_FN(name, t1, t2, f) \
371  static octave_value \
372  CONCAT2 (oct_catop_, name) (octave_base_value& a1, \
373  const octave_base_value& a2, \
374  const Array<octave_idx_type>& ra_idx) \
375  { \
376  CONCAT2 (octave_, t1)& v1 = dynamic_cast<CONCAT2 (octave_, t1)&> (a1); \
377  const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
378  \
379  return octave_value (v1.CONCAT2 (t1, _value) () . f (v2.CONCAT2 (t2, _value) (), ra_idx)); \
380  }
381 
382 #define DEFNDCATOP_FN(name, t1, t2, e1, e2, f) \
383  static octave_value \
384  CONCAT2 (oct_catop_, name) (octave_base_value& a1, \
385  const octave_base_value& a2, \
386  const Array<octave_idx_type>& ra_idx) \
387  { \
388  CONCAT2 (octave_, t1)& v1 = dynamic_cast<CONCAT2 (octave_, t1)&> (a1); \
389  const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
390  \
391  return octave_value (v1.CONCAT2 (e1, _value) () . f (v2.CONCAT2 (e2, _value) (), ra_idx)); \
392  }
393 
394 #define DEFNDCHARCATOP_FN(name, t1, t2, f) \
395  static octave_value \
396  CONCAT2 (oct_catop_, name) (octave_base_value& a1, \
397  const octave_base_value& a2, \
398  const Array<octave_idx_type>& ra_idx) \
399  { \
400  CONCAT2 (octave_, t1)& v1 = dynamic_cast<CONCAT2 (octave_, t1)&> (a1); \
401  const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
402  \
403  return octave_value (v1.char_array_value () . f (v2.char_array_value (), ra_idx), \
404  ((a1.is_sq_string () || a2.is_sq_string ()) \
405  ? '\'' : '"')); \
406  }
407 
408 // For compatibility, the second arg is always converted to the type
409 // of the first. Hmm.
410 
411 #define DEFNDCATOP_FN2(name, t1, t2, tc1, tc2, e1, e2, f) \
412  static octave_value \
413  CONCAT2 (oct_catop_, name) (octave_base_value& a1, \
414  const octave_base_value& a2, \
415  const Array<octave_idx_type>& ra_idx) \
416  { \
417  CONCAT2 (octave_, t1)& v1 = dynamic_cast<CONCAT2 (octave_, t1)&> (a1); \
418  const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
419  \
420  return octave_value (tc1 (v1.CONCAT2 (e1, _value) ()) . f (tc2 (v2.CONCAT2 (e2, _value) ()), ra_idx)); \
421  }
422 
423 #endif
void install_ops(octave::type_info &)