Vaucanson  1.4.1
element_ops.hxx
1 // element_ops.hxx: this file is part of the Vaucanson project.
2 //
3 // Vaucanson, a generic library for finite state machines.
4 //
5 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 The Vaucanson Group.
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
11 //
12 // The complete GNU General Public Licence Notice can be found as the
13 // `COPYING' file in the root directory.
14 //
15 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
16 //
17 #ifndef VCSN_DESIGN_PATTERN_ELEMENT_OPS_HXX
18 # define VCSN_DESIGN_PATTERN_ELEMENT_OPS_HXX
19 
21 
23 # include <vaucanson/misc/static.hh>
24 # include <vaucanson/misc/unique.hh>
25 
26 namespace vcsn {
27 
28  /*-------------------------.
29  | Operator prototype forms |
30  `-------------------------*/
31 
32 #define ELEMENT_OP_PROTO_SYM(Op, Ret) \
33 template<typename S1, typename T1, typename S2, typename T2> \
34 static \
35 Ret \
36 operator Op(const Element<S1, T1>& e1, \
37  const Element<S2, T2>& e2)
38 
39 #define ELEMENT_OP_PROTO_LEFT_FOREIGN(Op, Ret) \
40 template<typename S1, typename T1, typename T2> \
41 static \
42 Ret \
43 operator Op(const Element<S1, T1>& e1, const T2& e2)
44 
45 #define ELEMENT_OP_PROTO_RIGHT_FOREIGN(Op, Ret) \
46 template<typename T1, typename S2, typename T2> \
47 static \
48 Ret \
49 operator Op(const T1& e1, const Element<S2, T2>& e2)
50 
51  /*--------------------------.
52  | Standard delegation forms |
53  `--------------------------*/
54 
55 #define DELEGATE_SYM(OpName) \
56  return op_ ## OpName(e1.structure(), e2.structure(), e1.value(), e2.value())
57 
58 #define DELEGATE_LEFT_FOREIGN(OpName) \
59  return op_ ## OpName(e1.structure(), \
60  e1.value(), \
61  op_convert(e1.structure(), SELECT(T1), e2))
62 
63 #define DELEGATE_RIGHT_FOREIGN(OpName) \
64  return op_ ## OpName(e2.structure(), \
65  op_convert(e2.structure(), SELECT(T2), e1), \
66  e2.value())
67 
68 
69  /*-----------------------------.
70  | Standard Boolean delegations |
71  `-----------------------------*/
72 
73 #define BOOLEAN_DELEGATION(Op, OpName) \
74  ELEMENT_OP_PROTO_SYM(Op, bool) \
75  { \
76  DELEGATE_SYM(OpName); \
77  } \
78  \
79  ELEMENT_OP_PROTO_LEFT_FOREIGN(Op, bool) \
80  { \
81  DELEGATE_LEFT_FOREIGN(OpName); \
82  } \
83  \
84  ELEMENT_OP_PROTO_RIGHT_FOREIGN(Op, bool) \
85  { \
86  DELEGATE_RIGHT_FOREIGN(OpName); \
87  }
88 
89  BOOLEAN_DELEGATION(==, eq)
90  BOOLEAN_DELEGATION(<, lt)
91 #undef BOOLEAN_DELEGATION
92 
93 #define BOOLEAN_CANONICAL_DELEGATION(Op, Not, E1, Del, E2) \
94  ELEMENT_OP_PROTO_SYM(Op, bool) \
95  { \
96  return Not (e ## E1 Del e ## E2); \
97  } \
98  \
99  ELEMENT_OP_PROTO_LEFT_FOREIGN(Op, bool) \
100  { \
101  return Not (e ## E1 Del e ## E2); \
102  } \
103  \
104  ELEMENT_OP_PROTO_RIGHT_FOREIGN(Op, bool) \
105  { \
106  return Not (e ## E1 Del e ## E2); \
107  }
108 
109  BOOLEAN_CANONICAL_DELEGATION(!=, !, 1, ==, 2)
110  BOOLEAN_CANONICAL_DELEGATION(> , , 2, <, 1)
111  BOOLEAN_CANONICAL_DELEGATION(>=, !, 1, <, 2)
112  BOOLEAN_CANONICAL_DELEGATION(<=, !, 2, <, 1)
113 #undef BOOLEAN_CANONICAL_DELEGATION
114 
115 #undef ELEMENT_PROTO_SYM
116 #undef ELEMENT_PROTO_LEFT_FOREIGN
117 #undef ELEMENT_PROTO_RIGHT_FOREIGN
118 #undef DELEGATE_SYM
119 #undef DELEGATE_LEFT_FOREIGN
120 #undef DELEGATE_RIGHT_FOREIGN
121 
122  /*----------------------------------.
123  | Standard arithmetical delegations |
124  `----------------------------------*/
125 
126 #define ELEMENT_OPERATOR(Op, HookName) \
127 template<typename S1, typename T1, typename S2, typename T2> \
128 static \
129 typename op_##HookName##_traits<S1, S2, T1, T2>::ret_t \
130 operator Op(const Element<S1, T1>& e1, const Element<S2, T2>& e2) \
131 { \
132  /* Compute return Element type */ \
133  typedef typename op_##HookName##_traits<S1, S2, T1, T2>::ret_t ret_t; \
134  \
135  /* Compute return structural element from return Element type */ \
136  const bool want_s1 = misc::static_eq<S1, typename ret_t::set_t>::value; \
137  typedef typename misc::static_if<want_s1, S1, S2>::t ret_set_t; \
138  const ret_set_t& s = misc::static_if<want_s1, const S1, const S2>:: \
139  choose(e1.structure(), e2.structure()); \
140  \
141  /* Delegate */ \
142  return Element<ret_set_t, typename ret_t::value_t> \
143  (s, op_##HookName(e1.structure(), \
144  e2.structure(), \
145  e1.value(), \
146  e2.value())); \
147 } \
148  \
149 template<typename S, typename T, typename U> \
150 static \
151 Element<S, T> \
152 operator Op(const Element<S, T>& e, const U& v) \
153 { \
154  return Element<S, T> (e.structure(), \
155  op_##HookName(e.structure(), \
156  e.value(), \
157  op_convert(e.structure(), \
158  SELECT(T), v))); \
159 } \
160  \
161 template<typename U, typename S, typename T> \
162 static \
163 Element<S, T> \
164 operator Op(const U& v, const Element<S, T>& e) \
165 { \
166  return Element<S, T> (e.structure(), \
167  op_ ## HookName(e.structure(), \
168  op_convert(e.structure(), \
169  SELECT(T), v), \
170  e.value())); \
171 }
172 
173 ELEMENT_OPERATOR(+, add)
174 ELEMENT_OPERATOR(-, sub)
175 ELEMENT_OPERATOR(*, mul)
176 ELEMENT_OPERATOR(/, div)
177 ELEMENT_OPERATOR(%, mod)
178 
179 #undef ELEMENT_OPERATOR
180 
181 /*-----------------------------------------------.
182 | Implementation of input and output delegations |
183 `-----------------------------------------------*/
184 
185 template<typename St, typename S, typename T>
186 static
187 St&
188 operator << (St& s, const Element<S, T>& e)
189 {
190  return op_rout(e.structure(), s, e.value());
191 }
192 
193 template<typename St, typename S, typename T>
194 static
195 St&
196 operator >> (St& s, Element<S, T>& e)
197 {
198  S structure = e.structure();
199  op_rin(structure, s, e.value());
200  e.attach(structure);
201  return s;
202 }
203 
204 /*------------------------------------------.
205 | Implementation of the negation delegation |
206 `------------------------------------------*/
207 
208 template<typename S, typename T>
209 static
210 Element<S, T>
211 operator-(const Element<S, T>& e)
212 {
213  return Element<S, T>(e.structure(), op_neg(e.structure(), e.value()));
214 }
215 
216 } // vcsn
217 
218 
219 /*--------------------------------------.
220 | Implementation of the swap delegation |
221 `--------------------------------------*/
222 
223 namespace std
224 {
225  template<typename S, typename T1, typename T2>
226  void
229  {
230  assertion(&e1.structure() == &e2.structure());
231  op_swap(e1.structure(), e1.value(), e2.value());
232  }
233 
234  template<typename S, typename T>
235  void
238  {
239  assertion(&e1.structure() == &e2.structure());
240  op_swap(e1.structure(), e1.value(), e2.value());
241  }
242 
243  template<typename S, typename T>
244  void
246  {
247  op_swap(e1.structure(), e1.value(), v2);
248  }
249 
250  template<typename T, typename S>
251  void
253  {
254  op_swap(e2.structure(), v1, e2.value());
255  }
256 } // std
257 
258 #endif // ! VCSN_DESIGN_PATTERN_ELEMENT_OPS_HXX