ops.h

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 Copyright (C) 2009 VZLU Prague, a.s.
00005 
00006 This file is part of Octave.
00007 
00008 Octave is free software; you can redistribute it and/or modify it
00009 under the terms of the GNU General Public License as published by the
00010 Free Software Foundation; either version 3 of the License, or (at your
00011 option) any later version.
00012 
00013 Octave is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Octave; see the file COPYING.  If not, see
00020 <http://www.gnu.org/licenses/>.
00021 
00022 */
00023 
00024 #if !defined (octave_ops_h)
00025 #define octave_ops_h 1
00026 
00027 #include "Array-util.h"
00028 
00029 // Concatenation macros that enforce argument prescan
00030 #define CONCAT2X(x,y) x ## y
00031 #define CONCAT2(x,y) CONCAT2X(x,y)
00032 
00033 #define CONCAT3X(x,y,z) x ## y ## z
00034 #define CONCAT3(x,y,z) CONCAT3X(x,y,z)
00035 
00036 extern void install_ops (void);
00037 
00038 #define INSTALL_UNOP(op, t, f) \
00039   octave_value_typeinfo::register_unary_op \
00040     (octave_value::op, t::static_type_id (), CONCAT2(oct_unop_, f));
00041 
00042 #define INSTALL_NCUNOP(op, t, f) \
00043   octave_value_typeinfo::register_non_const_unary_op \
00044     (octave_value::op, t::static_type_id (), CONCAT2(oct_unop_, f));
00045 
00046 #define INSTALL_BINOP(op, t1, t2, f) \
00047   octave_value_typeinfo::register_binary_op \
00048     (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
00049      CONCAT2(oct_binop_, f));
00050 
00051 #define INSTALL_CATOP(t1, t2, f) \
00052   octave_value_typeinfo::register_cat_op \
00053     (t1::static_type_id (), t2::static_type_id (), CONCAT2(oct_catop_, f));
00054 
00055 #define INSTALL_ASSIGNOP(op, t1, t2, f) \
00056   octave_value_typeinfo::register_assign_op \
00057     (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
00058      CONCAT2(oct_assignop_, f));
00059 
00060 #define INSTALL_ASSIGNANYOP(op, t1, f) \
00061   octave_value_typeinfo::register_assignany_op \
00062     (octave_value::op, t1::static_type_id (), CONCAT2(oct_assignop_, f));
00063 
00064 #define INSTALL_ASSIGNCONV(t1, t2, tr) \
00065   octave_value_typeinfo::register_pref_assign_conv \
00066     (t1::static_type_id (), t2::static_type_id (), tr::static_type_id ());
00067 
00068 #define INSTALL_CONVOP(t1, t2, f) \
00069   octave_value_typeinfo::register_type_conv_op \
00070     (t1::static_type_id (), t2::static_type_id (), CONCAT2(oct_conv_, f));
00071 
00072 #define INSTALL_WIDENOP(t1, t2, f) \
00073   octave_value_typeinfo::register_widening_op \
00074     (t1::static_type_id (), t2::static_type_id (), CONCAT2(oct_conv_, f));
00075 
00076 #define CAST_UNOP_ARG(t) \
00077   t v = dynamic_cast<t> (a)
00078 
00079 #define CAST_BINOP_ARGS(t1, t2) \
00080   t1 v1 = dynamic_cast<t1> (a1);                \
00081   t2 v2 = dynamic_cast<t2> (a2)
00082 
00083 #define CAST_CONV_ARG(t) \
00084   t v = dynamic_cast<t> (a)
00085 
00086 #define ASSIGNOPDECL(name) \
00087   static octave_value \
00088   CONCAT2(oct_assignop_, name) (octave_base_value& a1, \
00089                          const octave_value_list& idx, \
00090                          const octave_base_value& a2)
00091 
00092 #define NULLASSIGNOPDECL(name) \
00093   static octave_value \
00094   CONCAT2(oct_assignop_, name) (octave_base_value& a, \
00095                          const octave_value_list& idx, \
00096                          const octave_base_value&)
00097 
00098 #define ASSIGNANYOPDECL(name) \
00099   static octave_value \
00100   CONCAT2(oct_assignop_, name) (octave_base_value& a1, \
00101                          const octave_value_list& idx, \
00102                          const octave_value& a2)
00103 
00104 #define DEFASSIGNOP(name, t1, t2) \
00105   ASSIGNOPDECL (name)
00106 
00107 #define DEFASSIGNOP_FN(name, t1, t2, f) \
00108   ASSIGNOPDECL (name) \
00109   { \
00110     CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
00111  \
00112     v1.f (idx, v2.CONCAT2(t1, _value) ()); \
00113     return octave_value (); \
00114   }
00115 
00116 #define DEFNULLASSIGNOP_FN(name, t, f) \
00117   NULLASSIGNOPDECL (name) \
00118   { \
00119     CAST_UNOP_ARG (CONCAT2(octave_, t)&); \
00120  \
00121     v.f (idx); \
00122     return octave_value (); \
00123   }
00124 
00125 #define DEFNDASSIGNOP_FN(name, t1, t2, e, f) \
00126   ASSIGNOPDECL (name) \
00127   { \
00128     CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
00129  \
00130     v1.f (idx, v2.CONCAT2(e, _value) ()); \
00131     return octave_value (); \
00132   }
00133 
00134 // FIXME: the following currently don't handle index.
00135 #define DEFNDASSIGNOP_OP(name, t1, t2, f, op) \
00136   ASSIGNOPDECL (name) \
00137   { \
00138     CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
00139  \
00140     assert (idx.empty ()); \
00141     v1.matrix_ref () op v2.CONCAT2(f, _value) (); \
00142  \
00143     return octave_value (); \
00144   }
00145 
00146 #define DEFNDASSIGNOP_FNOP(name, t1, t2, f, fnop) \
00147   ASSIGNOPDECL (name) \
00148   { \
00149     CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
00150  \
00151     assert (idx.empty ()); \
00152     fnop (v1.matrix_ref (), v2.CONCAT2(f, _value) ()); \
00153  \
00154     return octave_value (); \
00155   }
00156 
00157 #define DEFASSIGNANYOP_FN(name, t1, f) \
00158   ASSIGNANYOPDECL (name) \
00159   { \
00160     CONCAT2(octave_, t1)& v1 = dynamic_cast<CONCAT2(octave_, t1)&> (a1); \
00161  \
00162     v1.f (idx, a2); \
00163     return octave_value (); \
00164   }
00165 
00166 #define CONVDECL(name) \
00167   static octave_base_value * \
00168   CONCAT2(oct_conv_, name) (const octave_base_value& a)
00169 
00170 #define CONVDECLX(name) \
00171   static octave_base_value * \
00172   CONCAT2(oct_conv_, name) (const octave_base_value&)
00173 
00174 #define DEFCONV(name, a_dummy, b_dummy) \
00175   CONVDECL (name)
00176 
00177 #define DEFCONVFNX(name, tfrom, ovtto, tto, e) \
00178   CONVDECL (name) \
00179   { \
00180     CAST_CONV_ARG (const CONCAT2(octave_, tfrom)&); \
00181  \
00182     return new CONCAT2(octave_, ovtto) (CONCAT2(tto, NDArray) (v.CONCAT2(e, array_value) ())); \
00183   }
00184 
00185 #define DEFCONVFNX2(name, tfrom, ovtto, e) \
00186   CONVDECL (name) \
00187   { \
00188     CAST_CONV_ARG (const CONCAT2(octave_, tfrom)&); \
00189  \
00190     return new CONCAT2(octave_, ovtto) (v.CONCAT2(e, array_value) ()); \
00191   }
00192 
00193 #define DEFDBLCONVFN(name, ovtfrom, e) \
00194   CONVDECL (name) \
00195   { \
00196     CAST_CONV_ARG (const CONCAT2(octave_, ovtfrom)&); \
00197  \
00198     return new octave_matrix (NDArray (v.CONCAT2(e, _value) ())); \
00199   }
00200 
00201 #define DEFFLTCONVFN(name, ovtfrom, e) \
00202   CONVDECL (name) \
00203   { \
00204     CAST_CONV_ARG (const CONCAT2(octave_, ovtfrom)&); \
00205  \
00206     return new octave_float_matrix (FloatNDArray (v.CONCAT2(e, _value) ())); \
00207   }
00208 
00209 #define DEFSTRINTCONVFN(name, tto) \
00210   DEFCONVFNX(name, char_matrix_str, CONCAT2(tto, _matrix), tto, char_)
00211 
00212 #define DEFSTRDBLCONVFN(name, tfrom) \
00213   DEFCONVFNX(name, tfrom, matrix, , char_)
00214 
00215 #define DEFSTRFLTCONVFN(name, tfrom) \
00216   DEFCONVFNX(name, tfrom, float_matrix, Float, char_)
00217 
00218 #define DEFCONVFN(name, tfrom, tto) \
00219   DEFCONVFNX2 (name, tfrom, CONCAT2(tto, _matrix), CONCAT2(tto, _))
00220 
00221 #define DEFCONVFN2(name, tfrom, sm, tto) \
00222   DEFCONVFNX2 (name, CONCAT3(tfrom, _, sm), CONCAT2(tto, _matrix), CONCAT2(tto, _))
00223 
00224 #define UNOPDECL(name, a) \
00225   static octave_value \
00226   CONCAT2(oct_unop_, name) (const octave_base_value& a)
00227 
00228 #define DEFUNOPX(name, t) \
00229   UNOPDECL (name, , )
00230 
00231 #define DEFUNOP(name, t) \
00232   UNOPDECL (name, a)
00233 
00234 #define DEFUNOP_OP(name, t, op) \
00235   UNOPDECL (name, a) \
00236   { \
00237     CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
00238     return octave_value (op v.CONCAT2(t, _value) ()); \
00239   }
00240 
00241 #define DEFNDUNOP_OP(name, t, e, op) \
00242   UNOPDECL (name, a) \
00243   { \
00244     CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
00245     return octave_value (op v.CONCAT2(e, _value) ()); \
00246   }
00247 
00248 // FIXME -- in some cases, the constructor isn't necessary.
00249 
00250 #define DEFUNOP_FN(name, t, f) \
00251   UNOPDECL (name, a) \
00252   { \
00253     CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
00254     return octave_value (f (v.CONCAT2(t, _value) ())); \
00255   }
00256 
00257 #define DEFNDUNOP_FN(name, t, e, f) \
00258   UNOPDECL (name, a) \
00259   { \
00260     CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
00261     return octave_value (f (v.CONCAT2(e, _value) ())); \
00262   }
00263 
00264 #define DEFNCUNOP_METHOD(name, t, method) \
00265   static void \
00266   CONCAT2(oct_unop_, name) (octave_base_value& a) \
00267   { \
00268     CAST_UNOP_ARG (CONCAT2(octave_, t)&); \
00269     v.method (); \
00270   }
00271 
00272 #define BINOPDECL(name, a1, a2) \
00273   static octave_value \
00274   CONCAT2(oct_binop_, name) (const octave_base_value& a1, const octave_base_value& a2)
00275 
00276 #define DEFBINOPX(name, t1, t2) \
00277   BINOPDECL (name, , )
00278 
00279 #define DEFBINOP(name, t1, t2) \
00280   BINOPDECL (name, a1, a2)
00281 
00282 #define DEFBINOP_OP(name, t1, t2, op) \
00283   BINOPDECL (name, a1, a2) \
00284   { \
00285     CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
00286     return octave_value \
00287       (v1.CONCAT2(t1, _value) () op v2.CONCAT2(t2, _value) ()); \
00288   }
00289 
00290 #define DEFCMPLXCMPOP_OP(name, t1, t2, op) \
00291   BINOPDECL (name, a1, a2) \
00292   { \
00293     CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
00294     gripe_warn_complex_cmp (); \
00295     return octave_value \
00296       (v1.CONCAT2(t1, _value) () op v2.CONCAT2(t2, _value) ()); \
00297   }
00298 
00299 #define DEFSCALARBOOLOP_OP(name, t1, t2, op) \
00300   BINOPDECL (name, a1, a2) \
00301   { \
00302     CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
00303     if (xisnan (v1.CONCAT2(t1, _value) ()) || xisnan (v2.CONCAT2(t2, _value) ())) \
00304       { \
00305         gripe_nan_to_logical_conversion (); \
00306         return octave_value (); \
00307       } \
00308     else \
00309       return octave_value \
00310         (v1.CONCAT2(t1, _value) () op v2.CONCAT2(t2, _value) ()); \
00311   }
00312 
00313 #define DEFNDBINOP_OP(name, t1, t2, e1, e2, op) \
00314   BINOPDECL (name, a1, a2) \
00315   { \
00316     CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
00317     return octave_value \
00318       (v1.CONCAT2(e1, _value) () op v2.CONCAT2(e2, _value) ()); \
00319   }
00320 
00321 // FIXME -- in some cases, the constructor isn't necessary.
00322 
00323 #define DEFBINOP_FN(name, t1, t2, f) \
00324   BINOPDECL (name, a1, a2) \
00325   { \
00326     CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
00327     return octave_value (f (v1.CONCAT2(t1, _value) (), v2.CONCAT2(t2, _value) ())); \
00328   }
00329 
00330 #define DEFNDBINOP_FN(name, t1, t2, e1, e2, f) \
00331   BINOPDECL (name, a1, a2) \
00332   { \
00333     CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
00334     return octave_value (f (v1.CONCAT2(e1, _value) (), v2.CONCAT2(e2, _value) ())); \
00335   }
00336 
00337 #define DEFNDCMPLXCMPOP_FN(name, t1, t2, e1, e2, f) \
00338   BINOPDECL (name, a1, a2) \
00339   { \
00340     CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
00341     return octave_value (f (v1.CONCAT2(e1, _value) (), v2.CONCAT2(e2, _value) ())); \
00342   }
00343 
00344 #define BINOP_NONCONFORMANT(msg) \
00345   gripe_nonconformant (msg, \
00346                        a1.rows (), a1.columns (), \
00347                        a2.rows (), a2.columns ()); \
00348   return octave_value ()
00349 
00350 #define CATOPDECL(name, a1, a2) \
00351   static octave_value \
00352   CONCAT2(oct_catop_, name) (octave_base_value& a1, const octave_base_value& a2, \
00353                       const Array<octave_idx_type>& ra_idx)
00354 
00355 #define DEFCATOPX(name, t1, t2) \
00356   CATOPDECL (name, , )
00357 
00358 #define DEFCATOP(name, t1, t2)  \
00359   CATOPDECL (name, a1, a2)
00360 
00361 // FIXME -- in some cases, the constructor isn't necessary.
00362 
00363 #define DEFCATOP_FN(name, t1, t2, f) \
00364   CATOPDECL (name, a1, a2) \
00365   { \
00366     CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
00367     return octave_value (v1.CONCAT2(t1, _value) () . f (v2.CONCAT2(t2, _value) (), ra_idx)); \
00368   }
00369 
00370 #define DEFNDCATOP_FN(name, t1, t2, e1, e2, f) \
00371   CATOPDECL (name, a1, a2) \
00372   { \
00373     CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
00374     return octave_value (v1.CONCAT2(e1, _value) () . f (v2.CONCAT2(e2, _value) (), ra_idx)); \
00375   }
00376 
00377 #define DEFNDCHARCATOP_FN(name, t1, t2, f) \
00378   CATOPDECL (name, a1, a2) \
00379   { \
00380     CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
00381  \
00382     return octave_value (v1.char_array_value () . f (v2.char_array_value (), ra_idx), \
00383                          ((a1.is_sq_string () || a2.is_sq_string ()) \
00384                           ? '\'' : '"')); \
00385   }
00386 
00387 // For compatibility, the second arg is always converted to the type
00388 // of the first.  Hmm.
00389 
00390 #define DEFNDCATOP_FN2(name, t1, t2, tc1, tc2, e1, e2, f) \
00391   CATOPDECL (name, a1, a2) \
00392   { \
00393     CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
00394     return octave_value (tc1 (v1.CONCAT2(e1, _value) ()) . f (tc2 (v2.CONCAT2(e2, _value) ()), ra_idx)); \
00395   }
00396 
00397 #define CATOP_NONCONFORMANT(msg) \
00398   gripe_nonconformant (msg, \
00399                        a1.rows (), a1.columns (), \
00400                        a2.rows (), a2.columns ()); \
00401   return octave_value ()
00402 
00403 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines