Mercurial > octave
annotate src/ops.h @ 7997:2b8952e133c9
implement checked conversions between integers
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Wed, 30 Jul 2008 15:20:13 +0200 |
parents | 935be827eaf8 |
children | 283989f2da9b |
rev | line source |
---|---|
2376 | 1 /* |
2 | |
7017 | 3 Copyright (C) 1996, 1997, 1998, 2003, 2004, 2005, 2006, 2007 |
4 John W. Eaton | |
2376 | 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 | |
7016 | 10 Free Software Foundation; either version 3 of the License, or (at your |
11 option) any later version. | |
2376 | 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 | |
7016 | 19 along with Octave; see the file COPYING. If not, see |
20 <http://www.gnu.org/licenses/>. | |
2376 | 21 |
22 */ | |
23 | |
24 #if !defined (octave_ops_h) | |
25 #define octave_ops_h 1 | |
26 | |
4669 | 27 #include "Array-util.h" |
28 | |
2376 | 29 extern void install_ops (void); |
30 | |
3203 | 31 #define INSTALL_UNOP(op, t, f) \ |
32 octave_value_typeinfo::register_unary_op \ | |
33 (octave_value::op, t::static_type_id (), oct_unop_ ## f); | |
34 | |
35 #define INSTALL_NCUNOP(op, t, f) \ | |
36 octave_value_typeinfo::register_non_const_unary_op \ | |
37 (octave_value::op, t::static_type_id (), oct_unop_ ## f); | |
38 | |
2376 | 39 #define INSTALL_BINOP(op, t1, t2, f) \ |
40 octave_value_typeinfo::register_binary_op \ | |
3203 | 41 (octave_value::op, t1::static_type_id (), t2::static_type_id (), \ |
42 oct_binop_ ## f); | |
2376 | 43 |
4915 | 44 #define INSTALL_CATOP(t1, t2, f) \ |
45 octave_value_typeinfo::register_cat_op \ | |
46 (t1::static_type_id (), t2::static_type_id (), oct_catop_ ## f); | |
47 | |
2879 | 48 #define INSTALL_ASSIGNOP(op, t1, t2, f) \ |
2376 | 49 octave_value_typeinfo::register_assign_op \ |
3203 | 50 (octave_value::op, t1::static_type_id (), t2::static_type_id (), \ |
51 oct_assignop_ ## f); | |
2376 | 52 |
3195 | 53 #define INSTALL_ASSIGNANYOP(op, t1, f) \ |
54 octave_value_typeinfo::register_assignany_op \ | |
3203 | 55 (octave_value::op, t1::static_type_id (), oct_assignop_ ## f); |
3195 | 56 |
2376 | 57 #define INSTALL_ASSIGNCONV(t1, t2, tr) \ |
58 octave_value_typeinfo::register_pref_assign_conv \ | |
59 (t1::static_type_id (), t2::static_type_id (), tr::static_type_id ()); | |
60 | |
4901 | 61 #define INSTALL_CONVOP(t1, t2, f) \ |
62 octave_value_typeinfo::register_type_conv_op \ | |
63 (t1::static_type_id (), t2::static_type_id (), oct_conv_ ## f); | |
64 | |
2376 | 65 #define INSTALL_WIDENOP(t1, t2, f) \ |
66 octave_value_typeinfo::register_widening_op \ | |
3203 | 67 (t1::static_type_id (), t2::static_type_id (), oct_conv_ ## f); |
2376 | 68 |
69 #define BOOL_OP1(xt, xn, get_x, yt, yn, get_y) \ | |
70 xt xn = get_x; \ | |
71 yt yn = get_y; | |
72 | |
73 #define BOOL_OP2(x) \ | |
5275 | 74 octave_idx_type nr = x.rows (); \ |
75 octave_idx_type nc = x.columns (); | |
2376 | 76 |
77 #define BOOL_OP3(test) \ | |
2825 | 78 boolMatrix retval (nr, nc); \ |
5275 | 79 for (octave_idx_type j = 0; j < nc; j++) \ |
80 for (octave_idx_type i = 0; i < nr; i++) \ | |
2376 | 81 retval (i, j) = test; \ |
82 return retval; | |
83 | |
2601 | 84 #define SC_MX_BOOL_OP(st, sn, get_s, mt, mn, get_m, test, empty_result) \ |
2376 | 85 do \ |
86 { \ | |
87 BOOL_OP1 (st, sn, get_s, mt, mn, get_m) \ | |
88 BOOL_OP2 (mn) \ | |
2612 | 89 if (nr == 0 || nc == 0) \ |
2601 | 90 return empty_result; \ |
2376 | 91 BOOL_OP3 (test) \ |
92 } \ | |
93 while (0) | |
94 | |
2601 | 95 #define MX_SC_BOOL_OP(mt, mn, get_m, st, sn, get_s, test, empty_result) \ |
2376 | 96 do \ |
97 { \ | |
98 BOOL_OP1 (mt, mn, get_m, st, sn, get_s) \ | |
99 BOOL_OP2 (mn) \ | |
2612 | 100 if (nr == 0 || nc == 0) \ |
2601 | 101 return empty_result; \ |
2376 | 102 BOOL_OP3 (test) \ |
103 } \ | |
104 while (0) | |
105 | |
106 #define MX_MX_BOOL_OP(m1t, m1n, get_m1, m2t, m2n, get_m2, test, op, \ | |
2613 | 107 one_empty_result, two_empty_result) \ |
2376 | 108 do \ |
109 { \ | |
110 BOOL_OP1 (m1t, m1n, get_m1, m2t, m2n, get_m2) \ | |
5275 | 111 octave_idx_type m1_nr = m1n.rows (); \ |
112 octave_idx_type m1_nc = m1n.cols (); \ | |
113 octave_idx_type m2_nr = m2n.rows (); \ | |
114 octave_idx_type m2_nc = m2n.cols (); \ | |
2613 | 115 if (m1_nr == m2_nr && m1_nc == m2_nc) \ |
2376 | 116 { \ |
2613 | 117 if (m1_nr == 0 && m1_nc == 0) \ |
118 return two_empty_result; \ | |
119 else \ | |
120 { \ | |
121 BOOL_OP2 (m1n) \ | |
122 BOOL_OP3 (test) \ | |
123 } \ | |
2376 | 124 } \ |
2613 | 125 else \ |
126 { \ | |
127 if ((m1_nr == 0 && m1_nc == 0) || (m2_nr == 0 && m2_nc == 0)) \ | |
128 return one_empty_result; \ | |
129 else \ | |
130 { \ | |
131 gripe_nonconformant ("operator " op, m1_nr, m1_nc, \ | |
132 m2_nr, m2_nc); \ | |
2825 | 133 return boolMatrix (); \ |
2613 | 134 } \ |
135 } \ | |
2376 | 136 } \ |
137 while (0) | |
138 | |
3203 | 139 #define CAST_UNOP_ARG(t) \ |
5760 | 140 t v = dynamic_cast<t> (a) |
3203 | 141 |
2376 | 142 #define CAST_BINOP_ARGS(t1, t2) \ |
5760 | 143 t1 v1 = dynamic_cast<t1> (a1); \ |
144 t2 v2 = dynamic_cast<t2> (a2) | |
2376 | 145 |
146 #define CAST_CONV_ARG(t) \ | |
5760 | 147 t v = dynamic_cast<t> (a) |
2376 | 148 |
2914 | 149 #define ASSIGNOPDECL(name) \ |
150 static octave_value \ | |
5759 | 151 oct_assignop_ ## name (octave_base_value& a1, \ |
152 const octave_value_list& idx, \ | |
153 const octave_base_value& a2) | |
154 | |
155 #define ASSIGNANYOPDECL(name) \ | |
156 static octave_value \ | |
157 oct_assignop_ ## name (octave_base_value& a1, \ | |
3203 | 158 const octave_value_list& idx, \ |
159 const octave_value& a2) | |
2914 | 160 |
161 #define DEFASSIGNOP(name, t1, t2) \ | |
162 ASSIGNOPDECL (name) | |
163 | |
164 #define DEFASSIGNOP_FN(name, t1, t2, f) \ | |
165 ASSIGNOPDECL (name) \ | |
166 { \ | |
167 CAST_BINOP_ARGS (octave_ ## t1&, const octave_ ## t2&); \ | |
168 \ | |
169 v1.f (idx, v2.t1 ## _value ()); \ | |
170 return octave_value (); \ | |
171 } | |
172 | |
4686 | 173 #define DEFNDASSIGNOP_FN(name, t1, t2, e, f) \ |
174 ASSIGNOPDECL (name) \ | |
175 { \ | |
176 CAST_BINOP_ARGS (octave_ ## t1&, const octave_ ## t2&); \ | |
177 \ | |
178 v1.f (idx, v2.e ## _value ()); \ | |
179 return octave_value (); \ | |
180 } | |
181 | |
3195 | 182 #define DEFASSIGNANYOP_FN(name, t1, f) \ |
5759 | 183 ASSIGNANYOPDECL (name) \ |
3195 | 184 { \ |
5760 | 185 octave_ ## t1& v1 = dynamic_cast<octave_ ## t1&> (a1); \ |
3195 | 186 \ |
187 v1.f (idx, a2); \ | |
188 return octave_value (); \ | |
189 } | |
190 | |
2914 | 191 #define CONVDECL(name) \ |
5759 | 192 static octave_base_value * \ |
193 oct_conv_ ## name (const octave_base_value& a) | |
3203 | 194 |
195 #define CONVDECLX(name) \ | |
5759 | 196 static octave_base_value * \ |
197 oct_conv_ ## name (const octave_base_value&) | |
2914 | 198 |
4901 | 199 #define DEFCONV(name, a_dummy, b_dummy) \ |
2914 | 200 CONVDECL (name) |
201 | |
4901 | 202 #define DEFCONVFNX(name, tfrom, ovtto, tto, e) \ |
203 CONVDECL (name) \ | |
204 { \ | |
205 CAST_CONV_ARG (const octave_ ## tfrom&); \ | |
206 \ | |
207 return new octave_ ## ovtto (tto ## NDArray (v.e ## array_value ())); \ | |
208 } | |
209 | |
7997
2b8952e133c9
implement checked conversions between integers
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
210 #define DEFCONVFNX2(name, tfrom, ovtto, e) \ |
2b8952e133c9
implement checked conversions between integers
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
211 CONVDECL (name) \ |
2b8952e133c9
implement checked conversions between integers
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
212 { \ |
2b8952e133c9
implement checked conversions between integers
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
213 CAST_CONV_ARG (const octave_ ## tfrom&); \ |
2b8952e133c9
implement checked conversions between integers
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
214 \ |
2b8952e133c9
implement checked conversions between integers
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
215 return new octave_ ## ovtto (v.e ## array_value ()); \ |
2b8952e133c9
implement checked conversions between integers
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
216 } |
2b8952e133c9
implement checked conversions between integers
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
217 |
4901 | 218 #define DEFDBLCONVFN(name, ovtfrom, e) \ |
219 CONVDECL (name) \ | |
220 { \ | |
221 CAST_CONV_ARG (const octave_ ## ovtfrom&); \ | |
222 \ | |
223 return new octave_matrix (NDArray (v.e ## _value ())); \ | |
224 } | |
225 | |
5032 | 226 #define DEFSTRINTCONVFN(name, tto) \ |
227 DEFCONVFNX(name, char_matrix_str, tto ## _matrix, tto, char_) | |
228 | |
5992 | 229 #define DEFSTRDBLCONVFN(name, tfrom) \ |
230 DEFCONVFNX(name, tfrom, matrix, , char_) | |
5032 | 231 |
4901 | 232 #define DEFCONVFN(name, tfrom, tto) \ |
7997
2b8952e133c9
implement checked conversions between integers
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
233 DEFCONVFNX2 (name, tfrom, tto ## _matrix, tto ## _) |
4901 | 234 |
235 #define DEFCONVFN2(name, tfrom, sm, tto) \ | |
7997
2b8952e133c9
implement checked conversions between integers
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
236 DEFCONVFNX2 (name, tfrom ## _ ## sm, tto ## _matrix, tto ## _) |
4901 | 237 |
3203 | 238 #define UNOPDECL(name, a) \ |
239 static octave_value \ | |
5759 | 240 oct_unop_ ## name (const octave_base_value& a) |
3203 | 241 |
242 #define DEFUNOPX(name, t) \ | |
243 UNOPDECL (name, , ) | |
244 | |
245 #define DEFUNOP(name, t) \ | |
246 UNOPDECL (name, a) | |
247 | |
248 #define DEFUNOP_OP(name, t, op) \ | |
249 UNOPDECL (name, a) \ | |
250 { \ | |
251 CAST_UNOP_ARG (const octave_ ## t&); \ | |
252 return octave_value (op v.t ## _value ()); \ | |
253 } | |
254 | |
4550 | 255 #define DEFNDUNOP_OP(name, t, e, op) \ |
4543 | 256 UNOPDECL (name, a) \ |
257 { \ | |
258 CAST_UNOP_ARG (const octave_ ## t&); \ | |
4550 | 259 return octave_value (op v.e ## _value ()); \ |
4543 | 260 } |
261 | |
5775 | 262 // FIXME -- in some cases, the constructor isn't necessary. |
3203 | 263 |
264 #define DEFUNOP_FN(name, t, f) \ | |
265 UNOPDECL (name, a) \ | |
266 { \ | |
267 CAST_UNOP_ARG (const octave_ ## t&); \ | |
268 return octave_value (f (v.t ## _value ())); \ | |
269 } | |
270 | |
4550 | 271 #define DEFNDUNOP_FN(name, t, e, f) \ |
4543 | 272 UNOPDECL (name, a) \ |
273 { \ | |
274 CAST_UNOP_ARG (const octave_ ## t&); \ | |
4550 | 275 return octave_value (f (v.e ## _value ())); \ |
4543 | 276 } |
277 | |
3203 | 278 #define DEFNCUNOP_METHOD(name, t, method) \ |
279 static void \ | |
5759 | 280 oct_unop_ ## name (octave_base_value& a) \ |
3203 | 281 { \ |
282 CAST_UNOP_ARG (octave_ ## t&); \ | |
283 v.method (); \ | |
284 } | |
285 | |
2914 | 286 #define BINOPDECL(name, a1, a2) \ |
287 static octave_value \ | |
5759 | 288 oct_binop_ ## name (const octave_base_value& a1, const octave_base_value& a2) |
2914 | 289 |
290 #define DEFBINOPX(name, t1, t2) \ | |
291 BINOPDECL (name, , ) | |
292 | |
293 #define DEFBINOP(name, t1, t2) \ | |
294 BINOPDECL (name, a1, a2) | |
295 | |
296 #define DEFBINOP_OP(name, t1, t2, op) \ | |
297 BINOPDECL (name, a1, a2) \ | |
298 { \ | |
299 CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ | |
300 return octave_value \ | |
301 (v1.t1 ## _value () op v2.t2 ## _value ()); \ | |
302 } | |
303 | |
7922
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
304 #define DEFSCALARBOOLOP_OP(name, t1, t2, op) \ |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
305 BINOPDECL (name, a1, a2) \ |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
306 { \ |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
307 CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
308 if (xisnan (v1.t1 ## _value ()) || xisnan (v2.t2 ## _value ())) \ |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
309 { \ |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
310 error ("invalid conversion from NaN to logical"); \ |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
311 return octave_value (); \ |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
312 } \ |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
313 else \ |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
314 return octave_value \ |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
315 (v1.t1 ## _value () op v2.t2 ## _value ()); \ |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
316 } |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
317 |
4543 | 318 #define DEFNDBINOP_OP(name, t1, t2, e1, e2, op) \ |
319 BINOPDECL (name, a1, a2) \ | |
320 { \ | |
321 CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ | |
322 return octave_value \ | |
323 (v1.e1 ## _value () op v2.e2 ## _value ()); \ | |
324 } | |
325 | |
5775 | 326 // FIXME -- in some cases, the constructor isn't necessary. |
2914 | 327 |
328 #define DEFBINOP_FN(name, t1, t2, f) \ | |
329 BINOPDECL (name, a1, a2) \ | |
330 { \ | |
331 CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ | |
332 return octave_value (f (v1.t1 ## _value (), v2.t2 ## _value ())); \ | |
333 } | |
334 | |
4543 | 335 #define DEFNDBINOP_FN(name, t1, t2, e1, e2, f) \ |
336 BINOPDECL (name, a1, a2) \ | |
337 { \ | |
338 CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ | |
339 return octave_value (f (v1.e1 ## _value (), v2.e2 ## _value ())); \ | |
340 } | |
341 | |
2914 | 342 #define BINOP_NONCONFORMANT(msg) \ |
343 gripe_nonconformant (msg, \ | |
344 a1.rows (), a1.columns (), \ | |
345 a2.rows (), a2.columns ()); \ | |
346 return octave_value () | |
347 | |
4915 | 348 #define CATOPDECL(name, a1, a2) \ |
349 static octave_value \ | |
5759 | 350 oct_catop_ ## name (octave_base_value& a1, const octave_base_value& a2, \ |
6871 | 351 const Array<octave_idx_type>& ra_idx) |
4915 | 352 |
353 #define DEFCATOPX(name, t1, t2) \ | |
354 CATOPDECL (name, , ) | |
355 | |
356 #define DEFCATOP(name, t1, t2) \ | |
357 CATOPDECL (name, a1, a2) | |
358 | |
5775 | 359 // FIXME -- in some cases, the constructor isn't necessary. |
4915 | 360 |
361 #define DEFCATOP_FN(name, t1, t2, f) \ | |
5075 | 362 CATOPDECL (name, a1, a2) \ |
4915 | 363 { \ |
5073 | 364 CAST_BINOP_ARGS (octave_ ## t1&, const octave_ ## t2&); \ |
5533 | 365 return octave_value (v1.t1 ## _value () . f (v2.t2 ## _value (), ra_idx)); \ |
4915 | 366 } |
367 | |
5075 | 368 #define DEFNDCATOP_FN(name, t1, t2, e1, e2, f) \ |
369 CATOPDECL (name, a1, a2) \ | |
4915 | 370 { \ |
5073 | 371 CAST_BINOP_ARGS (octave_ ## t1&, const octave_ ## t2&); \ |
5533 | 372 return octave_value (v1.e1 ## _value () . f (v2.e2 ## _value (), ra_idx)); \ |
373 } | |
374 | |
375 #define DEFNDCHARCATOP_FN(name, t1, t2, f) \ | |
376 CATOPDECL (name, a1, a2) \ | |
377 { \ | |
378 CAST_BINOP_ARGS (octave_ ## t1&, const octave_ ## t2&); \ | |
379 \ | |
380 return octave_value (v1.char_array_value () . f (v2.char_array_value (), ra_idx), \ | |
381 true, ((a1.is_sq_string () || a2.is_sq_string ()) \ | |
382 ? '\'' : '"')); \ | |
4915 | 383 } |
384 | |
5075 | 385 // For compatibility, the second arg is always converted to the type |
386 // of the first. Hmm. | |
387 | |
388 #define DEFNDCATOP_FN2(name, t1, t2, tc1, tc2, e1, e2, f) \ | |
389 CATOPDECL (name, a1, a2) \ | |
390 { \ | |
391 CAST_BINOP_ARGS (octave_ ## t1&, const octave_ ## t2&); \ | |
392 return octave_value (tc1 (v1.e1 ## _value ()) . f (tc2 (v2.e2 ## _value ()), ra_idx)); \ | |
393 } | |
394 | |
4915 | 395 #define CATOP_NONCONFORMANT(msg) \ |
396 gripe_nonconformant (msg, \ | |
397 a1.rows (), a1.columns (), \ | |
398 a2.rows (), a2.columns ()); \ | |
399 return octave_value () | |
400 | |
2376 | 401 #endif |
402 | |
403 /* | |
404 ;;; Local Variables: *** | |
405 ;;; mode: C++ *** | |
406 ;;; End: *** | |
407 */ |