Vaucanson 1.4
element_ops.hxx
00001 // element_ops.hxx: this file is part of the Vaucanson project.
00002 //
00003 // Vaucanson, a generic library for finite state machines.
00004 //
00005 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 The Vaucanson Group.
00006 //
00007 // This program is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2
00010 // of the License, or (at your option) any later version.
00011 //
00012 // The complete GNU General Public Licence Notice can be found as the
00013 // `COPYING' file in the root directory.
00014 //
00015 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
00016 //
00017 #ifndef VCSN_DESIGN_PATTERN_ELEMENT_OPS_HXX
00018 # define VCSN_DESIGN_PATTERN_ELEMENT_OPS_HXX
00019 
00020 # include <vaucanson/design_pattern/element_ops.hh>
00021 
00022 # include <vaucanson/misc/selectors.hh>
00023 # include <vaucanson/misc/static.hh>
00024 # include <vaucanson/misc/unique.hh>
00025 
00026 namespace vcsn {
00027 
00028   /*-------------------------.
00029   | Operator prototype forms |
00030   `-------------------------*/
00031 
00032 #define ELEMENT_OP_PROTO_SYM(Op, Ret)                           \
00033 template<typename S1, typename T1, typename S2, typename T2>    \
00034 static                                                          \
00035 Ret                                                             \
00036 operator Op(const Element<S1, T1>& e1,                          \
00037             const Element<S2, T2>& e2)
00038 
00039 #define ELEMENT_OP_PROTO_LEFT_FOREIGN(Op, Ret)          \
00040 template<typename S1, typename T1, typename T2>         \
00041 static                                                  \
00042 Ret                                                     \
00043 operator Op(const Element<S1, T1>& e1, const T2& e2)
00044 
00045 #define ELEMENT_OP_PROTO_RIGHT_FOREIGN(Op, Ret)         \
00046 template<typename T1, typename S2, typename T2>         \
00047 static                                                  \
00048 Ret                                                     \
00049 operator Op(const T1& e1, const Element<S2, T2>& e2)
00050 
00051   /*--------------------------.
00052   | Standard delegation forms |
00053   `--------------------------*/
00054 
00055 #define DELEGATE_SYM(OpName) \
00056  return op_ ## OpName(e1.structure(), e2.structure(), e1.value(), e2.value())
00057 
00058 #define DELEGATE_LEFT_FOREIGN(OpName) \
00059   return op_ ## OpName(e1.structure(),                                  \
00060                        e1.value(),                                      \
00061                        op_convert(e1.structure(), SELECT(T1), e2))
00062 
00063 #define DELEGATE_RIGHT_FOREIGN(OpName) \
00064   return op_ ## OpName(e2.structure(),                                  \
00065                        op_convert(e2.structure(), SELECT(T2), e1),      \
00066                        e2.value())
00067 
00068 
00069   /*-----------------------------.
00070   | Standard Boolean delegations |
00071   `-----------------------------*/
00072 
00073 #define BOOLEAN_DELEGATION(Op, OpName)          \
00074   ELEMENT_OP_PROTO_SYM(Op, bool)                \
00075   {                                             \
00076     DELEGATE_SYM(OpName);                       \
00077   }                                             \
00078                                                 \
00079   ELEMENT_OP_PROTO_LEFT_FOREIGN(Op, bool)       \
00080   {                                             \
00081     DELEGATE_LEFT_FOREIGN(OpName);              \
00082   }                                             \
00083                                                 \
00084   ELEMENT_OP_PROTO_RIGHT_FOREIGN(Op, bool)      \
00085   {                                             \
00086     DELEGATE_RIGHT_FOREIGN(OpName);             \
00087   }
00088 
00089   BOOLEAN_DELEGATION(==, eq)
00090   BOOLEAN_DELEGATION(<, lt)
00091 #undef BOOLEAN_DELEGATION
00092 
00093 #define BOOLEAN_CANONICAL_DELEGATION(Op, Not, E1, Del, E2)      \
00094   ELEMENT_OP_PROTO_SYM(Op, bool)                                \
00095   {                                                             \
00096     return Not (e ## E1 Del e ## E2);                           \
00097   }                                                             \
00098                                                                 \
00099   ELEMENT_OP_PROTO_LEFT_FOREIGN(Op, bool)                       \
00100   {                                                             \
00101     return Not (e ## E1 Del e ## E2);                           \
00102   }                                                             \
00103                                                                 \
00104   ELEMENT_OP_PROTO_RIGHT_FOREIGN(Op, bool)                      \
00105   {                                                             \
00106     return Not (e ## E1 Del e ## E2);                           \
00107   }
00108 
00109   BOOLEAN_CANONICAL_DELEGATION(!=, !, 1, ==, 2)
00110   BOOLEAN_CANONICAL_DELEGATION(> ,  , 2, <, 1)
00111   BOOLEAN_CANONICAL_DELEGATION(>=, !, 1, <, 2)
00112   BOOLEAN_CANONICAL_DELEGATION(<=, !, 2, <, 1)
00113 #undef BOOLEAN_CANONICAL_DELEGATION
00114 
00115 #undef ELEMENT_PROTO_SYM
00116 #undef ELEMENT_PROTO_LEFT_FOREIGN
00117 #undef ELEMENT_PROTO_RIGHT_FOREIGN
00118 #undef DELEGATE_SYM
00119 #undef DELEGATE_LEFT_FOREIGN
00120 #undef DELEGATE_RIGHT_FOREIGN
00121 
00122     /*----------------------------------.
00123     | Standard arithmetical delegations |
00124     `----------------------------------*/
00125 
00126 #define ELEMENT_OPERATOR(Op, HookName)                                  \
00127 template<typename S1, typename T1, typename S2, typename T2>            \
00128 static                                                                  \
00129 typename op_##HookName##_traits<S1, S2, T1, T2>::ret_t                  \
00130 operator Op(const Element<S1, T1>& e1, const Element<S2, T2>& e2)       \
00131 {                                                                       \
00132   /* Compute return Element type */                                     \
00133   typedef typename op_##HookName##_traits<S1, S2, T1, T2>::ret_t ret_t; \
00134                                                                         \
00135   /* Compute return structural element from return Element type */      \
00136   const bool want_s1 = misc::static_eq<S1, typename ret_t::set_t>::value; \
00137   typedef typename misc::static_if<want_s1, S1, S2>::t ret_set_t;       \
00138   const ret_set_t& s = misc::static_if<want_s1, const S1, const S2>::   \
00139     choose(e1.structure(), e2.structure());                             \
00140                                                                         \
00141   /* Delegate */                                                        \
00142   return Element<ret_set_t, typename ret_t::value_t>                    \
00143     (s, op_##HookName(e1.structure(),                                   \
00144                       e2.structure(),                                   \
00145                       e1.value(),                                       \
00146                       e2.value()));                                     \
00147 }                                                                       \
00148                                                                         \
00149 template<typename S, typename T, typename U>                            \
00150 static                                                                  \
00151 Element<S, T>                                                           \
00152 operator Op(const Element<S, T>& e, const U& v)                         \
00153 {                                                                       \
00154   return Element<S, T> (e.structure(),                                  \
00155                         op_##HookName(e.structure(),                    \
00156                                       e.value(),                        \
00157                                       op_convert(e.structure(),         \
00158                                                  SELECT(T), v)));       \
00159 }                                                                       \
00160                                                                         \
00161 template<typename U, typename S, typename T>                            \
00162 static                                                                  \
00163 Element<S, T>                                                           \
00164 operator Op(const U& v, const Element<S, T>& e)                         \
00165 {                                                                       \
00166   return Element<S, T> (e.structure(),                                  \
00167                         op_ ## HookName(e.structure(),                  \
00168                                         op_convert(e.structure(),       \
00169                                                    SELECT(T), v),       \
00170                                         e.value()));                    \
00171 }
00172 
00173 ELEMENT_OPERATOR(+, add)
00174 ELEMENT_OPERATOR(-, sub)
00175 ELEMENT_OPERATOR(*, mul)
00176 ELEMENT_OPERATOR(/, div)
00177 ELEMENT_OPERATOR(%, mod)
00178 
00179 #undef ELEMENT_OPERATOR
00180 
00181 /*-----------------------------------------------.
00182 | Implementation of input and output delegations |
00183 `-----------------------------------------------*/
00184 
00185 template<typename St, typename S, typename T>
00186 static
00187 St&
00188 operator << (St& s, const Element<S, T>& e)
00189 {
00190   return op_rout(e.structure(), s, e.value());
00191 }
00192 
00193 template<typename St, typename S, typename T>
00194 static 
00195 St&
00196 operator >> (St& s, Element<S, T>& e)
00197 {
00198   S structure = e.structure();
00199   op_rin(structure, s, e.value());
00200   e.attach(structure);
00201   return s;
00202 }
00203 
00204 /*------------------------------------------.
00205 | Implementation of the negation delegation |
00206 `------------------------------------------*/
00207 
00208 template<typename S, typename T>
00209 static 
00210 Element<S, T>
00211 operator-(const Element<S, T>& e)
00212 {
00213   return Element<S, T>(e.structure(), op_neg(e.structure(), e.value()));
00214 }
00215 
00216 } // vcsn
00217 
00218 
00219 /*--------------------------------------.
00220 | Implementation of the swap delegation |
00221 `--------------------------------------*/
00222 
00223 namespace std
00224 {
00225   template<typename S, typename T1, typename T2>
00226   void
00227   swap(vcsn::Element<S, T1>& e1,
00228        vcsn::Element<S, T2>& e2)
00229   {
00230     assertion(&e1.structure() == &e2.structure());
00231     op_swap(e1.structure(), e1.value(), e2.value());
00232   }
00233 
00234   template<typename S, typename T>
00235   void
00236   swap(vcsn::Element<S, T>& e1,
00237        vcsn::Element<S, T>& e2)
00238   {
00239     assertion(&e1.structure() == &e2.structure());
00240     op_swap(e1.structure(), e1.value(), e2.value());
00241   }
00242 
00243   template<typename S, typename T>
00244   void
00245   swap(vcsn::Element<S, T>& e1, T& v2)
00246   {
00247     op_swap(e1.structure(), e1.value(), v2);
00248   }
00249 
00250   template<typename T, typename S>
00251   void
00252   swap(T& v1, vcsn::Element<S, T>& e2)
00253   {
00254     op_swap(e2.structure(), v1, e2.value());
00255   }
00256 } // std
00257 
00258 #endif // ! VCSN_DESIGN_PATTERN_ELEMENT_OPS_HXX