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 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 Ret operator Op(const Element<S1, T1>& x1,                      \
00035                 const Element<S2, T2>& x2)
00036 
00037 #define ELEMENT_OP_PROTO_LEFT_FOREIGN(Op, Ret)                  \
00038 template<typename S1, typename T1, typename T2>                 \
00039 Ret operator Op(const Element<S1, T1>& x1, const T2& x2)
00040 
00041 #define ELEMENT_OP_PROTO_RIGHT_FOREIGN(Op, Ret)                 \
00042 template<typename T1, typename S2, typename T2>                 \
00043 Ret operator Op(const T1& x1, const Element<S2, T2>& x2)
00044 
00045   /*--------------------------.
00046   | Standard delegation forms |
00047   `--------------------------*/
00048 
00049 #define DELEGATE_SYM(OpName) \
00050  return op_ ## OpName(x1.structure(), x2.structure(), x1.value(), x2.value())
00051 
00052 #define DELEGATE_LEFT_FOREIGN(OpName) \
00053   return op_ ## OpName(x1.structure(),                                  \
00054                        x1.value(),                                      \
00055                        op_convert(x1.structure(), SELECT(T1), x2))
00056 
00057 #define DELEGATE_RIGHT_FOREIGN(OpName) \
00058   return op_ ## OpName(x2.structure(),                                  \
00059                        op_convert(x2.structure(), SELECT(T2), x1),      \
00060                        x2.value())
00061 
00062 
00063   /*-----------------------------.
00064   | Standard Boolean delegations |
00065   `-----------------------------*/
00066 
00067 #define BOOLEAN_DELEGATION(Op, OpName)                                          \
00068   ELEMENT_OP_PROTO_SYM(Op, bool) { DELEGATE_SYM(OpName); }                      \
00069   ELEMENT_OP_PROTO_LEFT_FOREIGN(Op, bool) { DELEGATE_LEFT_FOREIGN(OpName); }    \
00070   ELEMENT_OP_PROTO_RIGHT_FOREIGN(Op, bool) { DELEGATE_RIGHT_FOREIGN(OpName); }
00071 
00072   BOOLEAN_DELEGATION(==, eq)
00073   BOOLEAN_DELEGATION(<, lt)
00074 #undef BOOLEAN_DELEGATION
00075 
00076 #define BOOLEAN_CANONICAL_DELEGATION(Op, Not, X1, Del, X2)                              \
00077   ELEMENT_OP_PROTO_SYM(Op, bool) { return Not (x ## X1 Del x ## X2); }                  \
00078   ELEMENT_OP_PROTO_LEFT_FOREIGN(Op, bool) { return Not (x ## X1 Del x ## X2); }         \
00079   ELEMENT_OP_PROTO_RIGHT_FOREIGN(Op, bool) { return Not (x ## X1 Del x ## X2); }
00080 
00081   BOOLEAN_CANONICAL_DELEGATION(!=, !, 1, ==, 2)
00082   BOOLEAN_CANONICAL_DELEGATION(> ,  , 2, <, 1)
00083   BOOLEAN_CANONICAL_DELEGATION(>=, !, 1, <, 2)
00084   BOOLEAN_CANONICAL_DELEGATION(<=, !, 2, <, 1)
00085 #undef BOOLEAN_CANONICAL_DELEGATION
00086 
00087 #undef ELEMENT_PROTO_SYM
00088 #undef ELEMENT_PROTO_LEFT_FOREIGN
00089 #undef ELEMENT_PROTO_RIGHT_FOREIGN
00090 #undef DELEGATE_SYM
00091 #undef DELEGATE_LEFT_FOREIGN
00092 #undef DELEGATE_RIGHT_FOREIGN
00093 
00094     /*----------------------------------.
00095     | Standard arithmetical delegations |
00096     `----------------------------------*/
00097 
00098 #define ELEMENT_OPERATOR(Op, HookName)                                                  \
00099 template<typename S1, typename T1, typename S2, typename T2>                            \
00100 static                                                                          \
00101 typename op_##HookName##_traits<S1, S2, T1, T2>::ret_t                                  \
00102 operator Op(const Element<S1, T1>& e1, const Element<S2, T2>& e2)                       \
00103 {                                                                                       \
00104   /* Compute return Element type */                                                     \
00105   typedef typename op_##HookName##_traits<S1, S2, T1, T2>::ret_t ret_t;                 \
00106                                                                                         \
00107   /* Compute return structural element from return Element type */                      \
00108   const bool want_s1 = utility::static_eq<S1, typename ret_t::set_t>::value;            \
00109   typedef typename utility::static_if<want_s1, S1, S2>::t ret_set_t;                    \
00110   const ret_set_t& s = utility::static_if<want_s1, const S1, const S2>::     \
00111     choose(e1.structure(), e2.structure());                                  \
00112                                                                                         \
00113   /* Delegate */                                                                        \
00114   return Element<ret_set_t, typename ret_t::value_t>                                    \
00115     (s, op_##HookName(e1.structure(),                                        \
00116                       e2.structure(),                                        \
00117                       e1.value(),                                            \
00118                       e2.value()));                                          \
00119 }                                                                                       \
00120                                                                                         \
00121 template<typename S, typename T, typename U>                                            \
00122 static Element<S, T>                                                            \
00123 operator Op(const Element<S, T>& e, const U& v)                                         \
00124 {                                                                                       \
00125   return Element<S, T> (e.structure(),                                       \
00126                         op_##HookName(e.structure(),                         \
00127                                       e.value(),                                        \
00128                                       op_convert(e.structure(),              \
00129                                                  SELECT(T), v)));            \
00130 }                                                                                       \
00131                                                                                         \
00132 template<typename U, typename S, typename T>                                            \
00133 static Element<S, T>                                                            \
00134 operator Op(const U& v, const Element<S, T>& e)                                         \
00135 {                                                                                       \
00136   return Element<S, T> (e.structure(),                                       \
00137                         op_ ## HookName(e.structure(),                       \
00138                                         op_convert(e.structure(),            \
00139                                                    SELECT(T), v),            \
00140                                         e.value()));                                    \
00141 }
00142 
00143 ELEMENT_OPERATOR(+, add)
00144 ELEMENT_OPERATOR(-, sub)
00145 ELEMENT_OPERATOR(*, mul)
00146 ELEMENT_OPERATOR(/, div)
00147 ELEMENT_OPERATOR(%, mod)
00148 
00149 #undef ELEMENT_OPERATOR
00150 
00151 /*-----------------------------------------------.
00152 | Implementation of input and output delegations |
00153 `-----------------------------------------------*/
00154 
00155 template<typename St, typename S, typename T>
00156 static St&
00157 operator << (St& s, const Element<S, T>& e)
00158 {
00159   return op_rout(e.structure(), s, e.value());
00160 }
00161 
00162 template<typename St, typename S, typename T>
00163 static St&
00164 operator >> (St& s, Element<S, T>& e)
00165 {
00166   S structure = e.structure();
00167   op_rin(structure, s, e.value());
00168   e.attach(structure);
00169   return s;
00170 }
00171 
00172 /*------------------------------------------.
00173 | Implementation of the negation delegation |
00174 `------------------------------------------*/
00175 
00176 template<typename S, typename T>
00177 static Element<S, T>
00178 operator-(const Element<S, T>& e)
00179 {
00180   return Element<S, T>(e.structure(), op_neg(e.structure(), e.value()));
00181 }
00182 
00183 } // vcsn
00184 
00185 
00186 /*--------------------------------------.
00187 | Implementation of the swap delegation |
00188 `--------------------------------------*/
00189 
00190 namespace std
00191 {
00192   template<typename S, typename T1, typename T2>
00193   void swap(vcsn::Element<S, T1>& e1,
00194             vcsn::Element<S, T2>& e2)
00195   {
00196     assertion(&e1.structure() == &e2.structure());
00197     op_swap(e1.structure(), e1.value(), e2.value());
00198   }
00199 
00200   template<typename S, typename T>
00201   void swap(vcsn::Element<S, T>& e1, T& v2)
00202   {
00203     op_swap(e1.structure(), e1.value(), v2);
00204   }
00205 
00206   template<typename T, typename S>
00207   void swap(T& v1, vcsn::Element<S, T>& e2)
00208   {
00209     op_swap(e2.structure(), v1, e2.value());
00210   }
00211 } // std
00212 
00213 #endif // ! VCSN_DESIGN_PATTERN_ELEMENT_OPS_HXX

Generated on Fri Jul 28 12:18:31 2006 for Vaucanson by  doxygen 1.4.6