GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ops.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2013 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 the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 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 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if !defined (octave_ops_h)
25 #define octave_ops_h 1
26 
27 #include "Array-util.h"
28 
29 // Concatenation macros that enforce argument prescan
30 #define CONCAT2X(x,y) x ## y
31 #define CONCAT2(x,y) CONCAT2X(x,y)
32 
33 #define CONCAT3X(x,y,z) x ## y ## z
34 #define CONCAT3(x,y,z) CONCAT3X(x,y,z)
35 
36 extern void install_ops (void);
37 
38 #define INSTALL_UNOP(op, t, f) \
39  octave_value_typeinfo::register_unary_op \
40  (octave_value::op, t::static_type_id (), CONCAT2(oct_unop_, f));
41 
42 #define INSTALL_NCUNOP(op, t, f) \
43  octave_value_typeinfo::register_non_const_unary_op \
44  (octave_value::op, t::static_type_id (), CONCAT2(oct_unop_, f));
45 
46 #define INSTALL_BINOP(op, t1, t2, f) \
47  octave_value_typeinfo::register_binary_op \
48  (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
49  CONCAT2(oct_binop_, f));
50 
51 #define INSTALL_CATOP(t1, t2, f) \
52  octave_value_typeinfo::register_cat_op \
53  (t1::static_type_id (), t2::static_type_id (), CONCAT2(oct_catop_, f));
54 
55 #define INSTALL_ASSIGNOP(op, t1, t2, f) \
56  octave_value_typeinfo::register_assign_op \
57  (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
58  CONCAT2(oct_assignop_, f));
59 
60 #define INSTALL_ASSIGNANYOP(op, t1, f) \
61  octave_value_typeinfo::register_assignany_op \
62  (octave_value::op, t1::static_type_id (), CONCAT2(oct_assignop_, f));
63 
64 #define INSTALL_ASSIGNCONV(t1, t2, tr) \
65  octave_value_typeinfo::register_pref_assign_conv \
66  (t1::static_type_id (), t2::static_type_id (), tr::static_type_id ());
67 
68 #define INSTALL_CONVOP(t1, t2, f) \
69  octave_value_typeinfo::register_type_conv_op \
70  (t1::static_type_id (), t2::static_type_id (), CONCAT2(oct_conv_, f));
71 
72 #define INSTALL_WIDENOP(t1, t2, f) \
73  octave_value_typeinfo::register_widening_op \
74  (t1::static_type_id (), t2::static_type_id (), CONCAT2(oct_conv_, f));
75 
76 #define CAST_UNOP_ARG(t) \
77  t v = dynamic_cast<t> (a)
78 
79 #define CAST_BINOP_ARGS(t1, t2) \
80  t1 v1 = dynamic_cast<t1> (a1); \
81  t2 v2 = dynamic_cast<t2> (a2)
82 
83 #define CAST_CONV_ARG(t) \
84  t v = dynamic_cast<t> (a)
85 
86 #define ASSIGNOPDECL(name) \
87  static octave_value \
88  CONCAT2(oct_assignop_, name) (octave_base_value& a1, \
89  const octave_value_list& idx, \
90  const octave_base_value& a2)
91 
92 #define NULLASSIGNOPDECL(name) \
93  static octave_value \
94  CONCAT2(oct_assignop_, name) (octave_base_value& a, \
95  const octave_value_list& idx, \
96  const octave_base_value&)
97 
98 #define ASSIGNANYOPDECL(name) \
99  static octave_value \
100  CONCAT2(oct_assignop_, name) (octave_base_value& a1, \
101  const octave_value_list& idx, \
102  const octave_value& a2)
103 
104 #define DEFASSIGNOP(name, t1, t2) \
105  ASSIGNOPDECL (name)
106 
107 #define DEFASSIGNOP_FN(name, t1, t2, f) \
108  ASSIGNOPDECL (name) \
109  { \
110  CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
111  \
112  v1.f (idx, v2.CONCAT2(t1, _value) ()); \
113  return octave_value (); \
114  }
115 
116 #define DEFNULLASSIGNOP_FN(name, t, f) \
117  NULLASSIGNOPDECL (name) \
118  { \
119  CAST_UNOP_ARG (CONCAT2(octave_, t)&); \
120  \
121  v.f (idx); \
122  return octave_value (); \
123  }
124 
125 #define DEFNDASSIGNOP_FN(name, t1, t2, e, f) \
126  ASSIGNOPDECL (name) \
127  { \
128  CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
129  \
130  v1.f (idx, v2.CONCAT2(e, _value) ()); \
131  return octave_value (); \
132  }
133 
134 // FIXME: the following currently don't handle index.
135 #define DEFNDASSIGNOP_OP(name, t1, t2, f, op) \
136  ASSIGNOPDECL (name) \
137  { \
138  CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
139  \
140  assert (idx.empty ()); \
141  v1.matrix_ref () op v2.CONCAT2(f, _value) (); \
142  \
143  return octave_value (); \
144  }
145 
146 #define DEFNDASSIGNOP_FNOP(name, t1, t2, f, fnop) \
147  ASSIGNOPDECL (name) \
148  { \
149  CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
150  \
151  assert (idx.empty ()); \
152  fnop (v1.matrix_ref (), v2.CONCAT2(f, _value) ()); \
153  \
154  return octave_value (); \
155  }
156 
157 #define DEFASSIGNANYOP_FN(name, t1, f) \
158  ASSIGNANYOPDECL (name) \
159  { \
160  CONCAT2(octave_, t1)& v1 = dynamic_cast<CONCAT2(octave_, t1)&> (a1); \
161  \
162  v1.f (idx, a2); \
163  return octave_value (); \
164  }
165 
166 #define CONVDECL(name) \
167  static octave_base_value * \
168  CONCAT2(oct_conv_, name) (const octave_base_value& a)
169 
170 #define CONVDECLX(name) \
171  static octave_base_value * \
172  CONCAT2(oct_conv_, name) (const octave_base_value&)
173 
174 #define DEFCONV(name, a_dummy, b_dummy) \
175  CONVDECL (name)
176 
177 #define DEFCONVFNX(name, tfrom, ovtto, tto, e) \
178  CONVDECL (name) \
179  { \
180  CAST_CONV_ARG (const CONCAT2(octave_, tfrom)&); \
181  \
182  return new CONCAT2(octave_, ovtto) (CONCAT2(tto, NDArray) (v.CONCAT2(e, array_value) ())); \
183  }
184 
185 #define DEFCONVFNX2(name, tfrom, ovtto, e) \
186  CONVDECL (name) \
187  { \
188  CAST_CONV_ARG (const CONCAT2(octave_, tfrom)&); \
189  \
190  return new CONCAT2(octave_, ovtto) (v.CONCAT2(e, array_value) ()); \
191  }
192 
193 #define DEFDBLCONVFN(name, ovtfrom, e) \
194  CONVDECL (name) \
195  { \
196  CAST_CONV_ARG (const CONCAT2(octave_, ovtfrom)&); \
197  \
198  return new octave_matrix (NDArray (v.CONCAT2(e, _value) ())); \
199  }
200 
201 #define DEFFLTCONVFN(name, ovtfrom, e) \
202  CONVDECL (name) \
203  { \
204  CAST_CONV_ARG (const CONCAT2(octave_, ovtfrom)&); \
205  \
206  return new octave_float_matrix (FloatNDArray (v.CONCAT2(e, _value) ())); \
207  }
208 
209 #define DEFSTRINTCONVFN(name, tto) \
210  DEFCONVFNX(name, char_matrix_str, CONCAT2(tto, _matrix), tto, char_)
211 
212 #define DEFSTRDBLCONVFN(name, tfrom) \
213  DEFCONVFNX(name, tfrom, matrix, , char_)
214 
215 #define DEFSTRFLTCONVFN(name, tfrom) \
216  DEFCONVFNX(name, tfrom, float_matrix, Float, char_)
217 
218 #define DEFCONVFN(name, tfrom, tto) \
219  DEFCONVFNX2 (name, tfrom, CONCAT2(tto, _matrix), CONCAT2(tto, _))
220 
221 #define DEFCONVFN2(name, tfrom, sm, tto) \
222  DEFCONVFNX2 (name, CONCAT3(tfrom, _, sm), CONCAT2(tto, _matrix), CONCAT2(tto, _))
223 
224 #define UNOPDECL(name, a) \
225  static octave_value \
226  CONCAT2(oct_unop_, name) (const octave_base_value& a)
227 
228 #define DEFUNOPX(name, t) \
229  UNOPDECL (name, , )
230 
231 #define DEFUNOP(name, t) \
232  UNOPDECL (name, a)
233 
234 #define DEFUNOP_OP(name, t, op) \
235  UNOPDECL (name, a) \
236  { \
237  CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
238  return octave_value (op v.CONCAT2(t, _value) ()); \
239  }
240 
241 #define DEFNDUNOP_OP(name, t, e, op) \
242  UNOPDECL (name, a) \
243  { \
244  CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
245  return octave_value (op v.CONCAT2(e, _value) ()); \
246  }
247 
248 // FIXME: in some cases, the constructor isn't necessary.
249 
250 #define DEFUNOP_FN(name, t, f) \
251  UNOPDECL (name, a) \
252  { \
253  CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
254  return octave_value (f (v.CONCAT2(t, _value) ())); \
255  }
256 
257 #define DEFNDUNOP_FN(name, t, e, f) \
258  UNOPDECL (name, a) \
259  { \
260  CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
261  return octave_value (f (v.CONCAT2(e, _value) ())); \
262  }
263 
264 #define DEFNCUNOP_METHOD(name, t, method) \
265  static void \
266  CONCAT2(oct_unop_, name) (octave_base_value& a) \
267  { \
268  CAST_UNOP_ARG (CONCAT2(octave_, t)&); \
269  v.method (); \
270  }
271 
272 #define BINOPDECL(name, a1, a2) \
273  static octave_value \
274  CONCAT2(oct_binop_, name) (const octave_base_value& a1, const octave_base_value& a2)
275 
276 #define DEFBINOPX(name, t1, t2) \
277  BINOPDECL (name, , )
278 
279 #define DEFBINOP(name, t1, t2) \
280  BINOPDECL (name, a1, a2)
281 
282 #define DEFBINOP_OP(name, t1, t2, op) \
283  BINOPDECL (name, a1, a2) \
284  { \
285  CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
286  return octave_value \
287  (v1.CONCAT2(t1, _value) () op v2.CONCAT2(t2, _value) ()); \
288  }
289 
290 #define DEFCMPLXCMPOP_OP(name, t1, t2, op) \
291  BINOPDECL (name, a1, a2) \
292  { \
293  CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
294  gripe_warn_complex_cmp (); \
295  return octave_value \
296  (v1.CONCAT2(t1, _value) () op v2.CONCAT2(t2, _value) ()); \
297  }
298 
299 #define DEFSCALARBOOLOP_OP(name, t1, t2, op) \
300  BINOPDECL (name, a1, a2) \
301  { \
302  CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
303  if (xisnan (v1.CONCAT2(t1, _value) ()) || xisnan (v2.CONCAT2(t2, _value) ())) \
304  { \
305  gripe_nan_to_logical_conversion (); \
306  return octave_value (); \
307  } \
308  else \
309  return octave_value \
310  (v1.CONCAT2(t1, _value) () op v2.CONCAT2(t2, _value) ()); \
311  }
312 
313 #define DEFNDBINOP_OP(name, t1, t2, e1, e2, op) \
314  BINOPDECL (name, a1, a2) \
315  { \
316  CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
317  return octave_value \
318  (v1.CONCAT2(e1, _value) () op v2.CONCAT2(e2, _value) ()); \
319  }
320 
321 // FIXME: in some cases, the constructor isn't necessary.
322 
323 #define DEFBINOP_FN(name, t1, t2, f) \
324  BINOPDECL (name, a1, a2) \
325  { \
326  CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
327  return octave_value (f (v1.CONCAT2(t1, _value) (), v2.CONCAT2(t2, _value) ())); \
328  }
329 
330 #define DEFNDBINOP_FN(name, t1, t2, e1, e2, f) \
331  BINOPDECL (name, a1, a2) \
332  { \
333  CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
334  return octave_value (f (v1.CONCAT2(e1, _value) (), v2.CONCAT2(e2, _value) ())); \
335  }
336 
337 #define DEFNDCMPLXCMPOP_FN(name, t1, t2, e1, e2, f) \
338  BINOPDECL (name, a1, a2) \
339  { \
340  CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
341  return octave_value (f (v1.CONCAT2(e1, _value) (), v2.CONCAT2(e2, _value) ())); \
342  }
343 
344 #define CATOPDECL(name, a1, a2) \
345  static octave_value \
346  CONCAT2(oct_catop_, name) (octave_base_value& a1, const octave_base_value& a2, \
347  const Array<octave_idx_type>& ra_idx)
348 
349 #define DEFCATOPX(name, t1, t2) \
350  CATOPDECL (name, , )
351 
352 #define DEFCATOP(name, t1, t2) \
353  CATOPDECL (name, a1, a2)
354 
355 // FIXME: in some cases, the constructor isn't necessary.
356 
357 #define DEFCATOP_FN(name, t1, t2, f) \
358  CATOPDECL (name, a1, a2) \
359  { \
360  CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
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  CATOPDECL (name, a1, a2) \
366  { \
367  CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
368  return octave_value (v1.CONCAT2(e1, _value) () . f (v2.CONCAT2(e2, _value) (), ra_idx)); \
369  }
370 
371 #define DEFNDCHARCATOP_FN(name, t1, t2, f) \
372  CATOPDECL (name, a1, a2) \
373  { \
374  CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
375  \
376  return octave_value (v1.char_array_value () . f (v2.char_array_value (), ra_idx), \
377  ((a1.is_sq_string () || a2.is_sq_string ()) \
378  ? '\'' : '"')); \
379  }
380 
381 // For compatibility, the second arg is always converted to the type
382 // of the first. Hmm.
383 
384 #define DEFNDCATOP_FN2(name, t1, t2, tc1, tc2, e1, e2, f) \
385  CATOPDECL (name, a1, a2) \
386  { \
387  CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
388  return octave_value (tc1 (v1.CONCAT2(e1, _value) ()) . f (tc2 (v2.CONCAT2(e2, _value) ()), ra_idx)); \
389  }
390 
391 #define CATOP_NONCONFORMANT(msg) \
392  gripe_nonconformant (msg, \
393  a1.rows (), a1.columns (), \
394  a2.rows (), a2.columns ()); \
395  return octave_value ()
396 
397 #endif