GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
ops.h
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2025 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
36class type_info;
37
38OCTAVE_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
142#define DEFNDASSIGNOP_OP(name, t1, t2, f, op) \
143 static octave_value \
144 CONCAT2 (oct_assignop_, name) (octave_base_value& a1, \
145 const octave_value_list& idx, \
146 const octave_base_value& a2) \
147 { \
148 OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1); \
149 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
150 \
151 if (! idx.empty ()) \
152 error ("unexpected: index is not empty in oct_assignop_ " #name " - please report this bug"); \
153 v1.matrix_ref () op v2.CONCAT2 (f, _value) (); \
154 \
155 return octave_value (); \
156 }
157
158#define DEFNDASSIGNOP_FNOP(name, t1, t2, f, fnop) \
159 static octave_value \
160 CONCAT2 (oct_assignop_, name) (octave_base_value& a1, \
161 const octave_value_list& idx, \
162 const octave_base_value& a2) \
163 { \
164 OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1); \
165 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
166 \
167 if (! idx.empty ()) \
168 error ("unexpected: index is not empty in oct_assignop_ " #name " - please report this bug"); \
169 fnop (v1.matrix_ref (), v2.CONCAT2 (f, _value) ()); \
170 \
171 return octave_value (); \
172 }
173
174#define DEFASSIGNANYOP_FN(name, t1, f) \
175 static octave_value \
176 CONCAT2 (oct_assignop_, name) (octave_base_value& a1, \
177 const octave_value_list& idx, \
178 const octave_value& a2) \
179 { \
180 OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1); \
181 \
182 v1.f (idx, a2); \
183 return octave_value (); \
184 }
185
186#define CONVDECL(name) \
187 static octave_base_value * \
188 CONCAT2 (oct_conv_, name) (const octave_base_value& a)
189
190#define DEFCONV(name, a_dummy, b_dummy) \
191 CONVDECL (name)
192
193#define DEFUNOPX(name, t) \
194 static octave_value \
195 CONCAT2 (oct_unop_, name) (const octave_base_value&)
196
197#define DEFUNOP(name, t) \
198 static octave_value \
199 CONCAT2 (oct_unop_, name) (const octave_base_value& a)
200
201#define DEFUNOP_OP(name, t, op) \
202 static octave_value \
203 CONCAT2 (oct_unop_, name) (const octave_base_value& a) \
204 { \
205 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t)&, v, a); \
206 return octave_value (op v.CONCAT2 (t, _value) ()); \
207 }
208
209#define DEFNDUNOP_OP(name, t, e, op) \
210 static octave_value \
211 CONCAT2 (oct_unop_, name) (const octave_base_value& a) \
212 { \
213 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t)&, v, a); \
214 return octave_value (op v.CONCAT2 (e, _value) ()); \
215 }
216
217// FIXME: in some cases, the constructor isn't necessary.
218
219#define DEFUNOP_FN(name, t, f) \
220 static octave_value \
221 CONCAT2 (oct_unop_, name) (const octave_base_value& a) \
222 { \
223 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t)&, v, a); \
224 return octave_value (f (v.CONCAT2 (t, _value) ())); \
225 }
226
227#define DEFNDUNOP_FN(name, t, e, f) \
228 static octave_value \
229 CONCAT2 (oct_unop_, name) (const octave_base_value& a) \
230 { \
231 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t)&, v, a); \
232 return octave_value (f (v.CONCAT2 (e, _value) ())); \
233 }
234
235#define DEFNCUNOP_METHOD(name, t, method) \
236 static void \
237 CONCAT2 (oct_unop_, name) (octave_base_value& a) \
238 { \
239 OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t)&, v, a); \
240 v.method (); \
241 }
242
243#define DEFBINOPX(name, t1, t2) \
244 static octave_value \
245 CONCAT2 (oct_binop_, name) (const octave_base_value&, \
246 const octave_base_value&)
247
248#define DEFBINOP(name, t1, t2) \
249 static octave_value \
250 CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
251 const octave_base_value& a2)
252
253#define DEFBINOP_OP(name, t1, t2, op) \
254 static octave_value \
255 CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
256 const octave_base_value& a2) \
257 { \
258 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
259 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
260 \
261 return octave_value \
262 (v1.CONCAT2 (t1, _value) () op v2.CONCAT2 (t2, _value) ()); \
263 }
264
265#define DEFCMPLXCMPOP_OP(name, t1, t2, op) \
266 static octave_value \
267 CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
268 const octave_base_value& a2) \
269 { \
270 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
271 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
272 \
273 warn_complex_cmp (); \
274 \
275 return octave_value \
276 (v1.CONCAT2 (t1, _value) () op v2.CONCAT2 (t2, _value) ()); \
277 }
278
279#define DEFSCALARBOOLOP_OP(name, t1, t2, op) \
280 static octave_value \
281 CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
282 const octave_base_value& a2) \
283 { \
284 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
285 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
286 \
287 if (octave::math::isnan (v1.CONCAT2 (t1, _value) ()) || octave::math::isnan (v2.CONCAT2 (t2, _value) ())) \
288 octave::err_nan_to_logical_conversion (); \
289 \
290 return octave_value \
291 (v1.CONCAT2 (t1, _value) () op v2.CONCAT2 (t2, _value) ()); \
292 }
293
294#define DEFNDBINOP_OP(name, t1, t2, e1, e2, op) \
295 static octave_value \
296 CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
297 const octave_base_value& a2) \
298 { \
299 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
300 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
301 \
302 return octave_value \
303 (v1.CONCAT2 (e1, _value) () op v2.CONCAT2 (e2, _value) ()); \
304 }
305
306// FIXME: in some cases, the constructor isn't necessary.
307
308#define DEFBINOP_FN(name, t1, t2, f) \
309 static octave_value \
310 CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
311 const octave_base_value& a2) \
312 { \
313 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
314 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
315 \
316 return octave_value (f (v1.CONCAT2 (t1, _value) (), v2.CONCAT2 (t2, _value) ())); \
317 }
318
319#define DEFNDBINOP_FN(name, t1, t2, e1, e2, f) \
320 static octave_value \
321 CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
322 const octave_base_value& a2) \
323 { \
324 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
325 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
326 \
327 return octave_value (f (v1.CONCAT2 (e1, _value) (), v2.CONCAT2 (e2, _value) ())); \
328 }
329
330#define DEFNDCMPLXCMPOP_FN(name, t1, t2, e1, e2, f) \
331 static octave_value \
332 CONCAT2 (oct_binop_, name) (const octave_base_value& a1, \
333 const octave_base_value& a2) \
334 { \
335 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
336 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
337 \
338 return octave_value (f (v1.CONCAT2 (e1, _value) (), v2.CONCAT2 (e2, _value) ())); \
339 }
340
341#define DEFCATOPX(name, t1, t2) \
342 static octave_value \
343 CONCAT2 (oct_catop_, name) (const octave_base_value&, \
344 const octave_base_value&, \
345 const Array<octave_idx_type>& ra_idx)
346
347#define DEFCATOP(name, t1, t2) \
348 static octave_value \
349 CONCAT2 (oct_catop_, name) (const octave_base_value& a1, \
350 const octave_base_value& a2, \
351 const Array<octave_idx_type>& ra_idx)
352
353// FIXME: in some cases, the constructor isn't necessary.
354
355#define DEFCATOP_FN(name, t1, t2, f) \
356 static octave_value \
357 CONCAT2 (oct_catop_, name) (const octave_base_value& a1, \
358 const octave_base_value& a2, \
359 const Array<octave_idx_type>& ra_idx) \
360 { \
361 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
362 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
363 \
364 return octave_value (v1.CONCAT2 (t1, _value) () . f (v2.CONCAT2 (t2, _value) (), ra_idx)); \
365 }
366
367#define DEFNDCATOP_FN(name, t1, t2, e1, e2, f) \
368 static octave_value \
369 CONCAT2 (oct_catop_, name) (const octave_base_value& a1, \
370 const octave_base_value& a2, \
371 const Array<octave_idx_type>& ra_idx) \
372 { \
373 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
374 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
375 \
376 return octave_value (v1.CONCAT2 (e1, _value) () . f (v2.CONCAT2 (e2, _value) (), ra_idx)); \
377 }
378
379#define DEFNDCHARCATOP_FN(name, t1, t2, f) \
380 static octave_value \
381 CONCAT2 (oct_catop_, name) (const octave_base_value& a1, \
382 const octave_base_value& a2, \
383 const Array<octave_idx_type>& ra_idx) \
384 { \
385 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
386 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
387 \
388 return octave_value (v1.char_array_value () . f (v2.char_array_value (), ra_idx), \
389 ((a1.is_sq_string () || a2.is_sq_string ()) \
390 ? '\'' : '"')); \
391 }
392
393// For compatibility, the second arg is always converted to the type
394// of the first. Hmm.
395
396#define DEFNDCATOP_FN2(name, t1, t2, tc1, tc2, e1, e2, f) \
397 static octave_value \
398 CONCAT2 (oct_catop_, name) (const octave_base_value& a1, \
399 const octave_base_value& a2, \
400 const Array<octave_idx_type>& ra_idx) \
401 { \
402 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1); \
403 OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2); \
404 \
405 return octave_value (tc1 (v1.CONCAT2 (e1, _value) ()) . f (tc2 (v2.CONCAT2 (e2, _value) ()), ra_idx)); \
406 }
407
408#endif
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn