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
34
OCTAVE_BEGIN_NAMESPACE
(octave)
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
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
Array-util.h
type_info
Definition
ov-typeinfo.h:43
OCTAVE_BEGIN_NAMESPACE
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
error.h
libinterp
operators
ops.h
Generated on Sat Aug 2 2025 06:52:12 for GNU Octave by
1.9.8