Logo  0.95.0-final
Finite Element Embedded Library and Language in C++
Feel++ Feel++ on Github Feel++ community
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ppoperators.hpp
Go to the documentation of this file.
1 /* -*- mode: c++; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; show-trailing-whitespace: t -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
2 
3  This file is part of the Feel library
4 
5  Author(s): Christophe Prud'homme <christophe.prudhomme@feelpp.org>
6  Date: 2005-06-01
7 
8  Copyright (C) 2005,2006 EPFL
9  Copyright (C) 2007-2011 Université Joseph Fourier (Grenoble I)
10 
11  This library is free software; you can redistribute it and/or
12  modify it under the terms of the GNU Lesser General Public
13  License as published by the Free Software Foundation; either
14  version 3.0 of the License, or (at your option) any later version.
15 
16  This library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public
22  License along with this library; if not, write to the Free Software
23  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 */
30 #if !defined( PP_OPERATORS_HPP )
31 #define PP_OPERATORS_HPP 1
32 
33 #include <feel/feelconfig.h>
34 #if defined( FEELPP_HAS_QD_H )
35 # include <qd/qd.h>
36 #endif
37 
39 # include <boost/preprocessor/comparison/less.hpp>
40 # include <boost/preprocessor/comparison/equal.hpp>
41 # include <boost/preprocessor/logical/and.hpp>
42 # include <boost/preprocessor/control/if.hpp>
43 # include <boost/preprocessor/list/at.hpp>
44 # include <boost/preprocessor/list/cat.hpp>
45 # include <boost/preprocessor/list/for_each_product.hpp>
46 # include <boost/preprocessor/logical/or.hpp>
47 # include <boost/preprocessor/tuple/to_list.hpp>
48 # include <boost/preprocessor/tuple/eat.hpp>
49 # include <boost/preprocessor/facilities/empty.hpp>
50 # include <boost/preprocessor/punctuation/comma.hpp>
51 # include <boost/preprocessor/facilities/identity.hpp>
52 
53 
54 # /* Information about C operators */
55 #
56 # /* Accessors for the operator datatype. */
57 # define VF_OP_SYMBOL(O) BOOST_PP_TUPLE_ELEM(9, 0, O)
58 # define VF_OP_NAME(O) BOOST_PP_TUPLE_ELEM(9, 1, O)
59 # define VF_OP_IS_FLOATING(O) BOOST_PP_TUPLE_ELEM(9, 2, O)
60 # define VF_OP_IS_LOGICAL(O) BOOST_PP_TUPLE_ELEM(9, 3, O)
61 # define VF_OP_IS_SHIFT(O) BOOST_PP_TUPLE_ELEM(9, 4, O)
62 # define VF_OP_IS_ADD(O) BOOST_PP_TUPLE_ELEM(9, 5, O)
63 # define VF_OP_IS_SYMETRIC(O) BOOST_PP_TUPLE_ELEM(9, 6, O)
64 # define VF_OP_SHAPE(O) BOOST_PP_TUPLE_ELEM(9, 7, O)
65 # define VF_OP_IMORDER(O) BOOST_PP_TUPLE_ELEM(9, 8, O)
66 #
67 # /* List of applicative unary operators. */
68 # define VF_APPLICATIVE_UNARY_OPS \
69  BOOST_PP_TUPLE_TO_LIST( \
70  3, \
71  ( \
72  ( ! , vf_logical_not, 1, 1, 0,0,0), \
73  ( ~ , vf_bitwise_not, 0, 0, 0,0,0), \
74  ( - , vf_neg, 1, 0, 0,0,0) \
75  ) \
76  ) \
77 
78 #
79 #if 0
80 # /* List of applicative binary operators. */
81 # define VF_APPLICATIVE_BINARY_OPS \
82  BOOST_PP_TUPLE_TO_LIST( \
83  18, \
84  ( \
85  ( * , vf_mul ,1 ,0 ,0 ,0 ,1), \
86  ( / , vf_div ,1 ,0 ,0 ,0 ,0), \
87  ( % , vf_mod ,0 ,0 ,0 ,0 ,0), \
88  ( + , vf_add ,1 ,0 ,0 ,1 ,1), \
89  ( - , vf_sub ,1 ,0 ,0 ,1 ,0), \
90  ( << , vf_shift_left ,0 ,0 ,1 ,0 ,0), \
91  ( >> , vf_shift_right ,0 ,0 ,1 ,0 ,0), \
92  ( < , vf_less ,1 ,1 ,0 ,0 ,0), \
93  ( <= , vf_less_equal ,1 ,1 ,0 ,0 ,0), \
94  ( >= , vf_greater_equal ,1 ,1 ,0 ,0 ,0), \
95  ( > , vf_greater ,1 ,1 ,0 ,0 ,0), \
96  ( == , vf_equal ,1 ,1 ,0 ,0 ,0), \
97  ( != , vf_not_equal ,1 ,1 ,0 ,0 ,0), \
98  ( & , vf_bitwise_and ,0 ,0 ,0 ,0 ,0), \
99  ( | , vf_bitwise_or ,0 ,0 ,0 ,0 ,0), \
100  ( ^ , vf_bitwise_xor ,0 ,0 ,0 ,0 ,0), \
101  ( && , vf_logical_and ,1 ,1 ,0 ,0 ,0), \
102  ( || , vf_logical_or ,1 ,1 ,0 ,0, 0) \
103  ) \
104  ) \
105 
106 #else
107 # // get rid of operator^ which is used for power computation
108 # /* List of applicative binary operators. */
109 # define VF_APPLICATIVE_BINARY_OPS \
110  BOOST_PP_TUPLE_TO_LIST( \
111  12, \
112  ( \
113  ( * , vf_mul ,1 ,0 ,0 ,0 ,1, shape_op_mul ,2 ), \
114  ( / , vf_div ,1 ,0 ,0 ,0 ,0, shape_op_div ,1 ), \
115  ( + , vf_add ,1 ,0 ,0 ,1 ,1, shape_op_samerank ,1 ), \
116  ( - , vf_sub ,1 ,0 ,0 ,1 ,0, shape_op_samerank ,1 ), \
117  ( < , vf_less ,1 ,1 ,0 ,0 ,0, shape_op_id ,0 ), \
118  ( <= , vf_less_equal ,1 ,1 ,0 ,0 ,0, shape_op_id ,0 ), \
119  ( >= , vf_greater_equal ,1 ,1 ,0 ,0 ,0, shape_op_id ,0 ), \
120  ( > , vf_greater ,1 ,1 ,0 ,0 ,0, shape_op_id ,0 ), \
121  ( == , vf_equal ,1 ,1 ,0 ,0 ,0, shape_op_id ,0 ), \
122  ( != , vf_not_equal ,1 ,1 ,0 ,0 ,0, shape_op_id ,0 ), \
123  ( && , vf_logical_and ,1 ,1 ,0 ,0 ,0, shape_op_id ,0 ), \
124  ( || , vf_logical_or ,1 ,1 ,0 ,0, 0, shape_op_id ,0 ) \
125  ) \
126  ) \
127 
128 #endif
129 #
130 # /* Accessors for the type datatype. */
131 # define VF_TYPE_NAME(T) BOOST_PP_TUPLE_ELEM(5, 0, T)
132 # define VF_TYPE_ABBREVIATION(T) BOOST_PP_TUPLE_ELEM(5, 1, T)
133 # define VF_TYPE_IS_FLOATING(T) BOOST_PP_TUPLE_ELEM(5, 2, T)
134 # define VF_TYPE_RANK(T) BOOST_PP_TUPLE_ELEM(5, 3, T)
135 # define VF_TYPE_IS_EXPR(T) BOOST_PP_TUPLE_ELEM(5, 4, T)
136 #
137 #if 0
138 # define VF_BUILTIN_TYPES \
139  BOOST_PP_TUPLE_TO_LIST( \
140  12, \
141  ( \
142  ( signed char ,sc, 0, 1,0), \
143  ( char ,ch, 0, 1,0), \
144  ( unsigned char ,uc, 0, 1,0), \
145  ( short ,ss, 0, 2,0), \
146  ( unsigned short ,us, 0, 2,0), \
147  VF_TYPE_INT, \
148  ( unsigned ,ui, 0, 4,0), \
149  ( long ,sl, 0, 5,0), \
150  ( unsigned long ,ul, 0, 6,0), \
151  ( float ,fl, 1, 7,0), \
152  ( double ,db, 1, 8,0), \
153  ( long double ,ld, 1, 9,0) \
154  ) \
155  ) \
156 
157 #else
158 # if defined( DISABLE_FEELPP_HAS_QD_H ) && defined( DISABLE_FEELPP_HAS_MPFR )
159 # define VF_BUILTIN_TYPES \
160  BOOST_PP_TUPLE_TO_LIST( \
161  12, \
162  ( \
163  VF_TYPE_INT, \
164  ( unsigned ,ui, 0, 4,0), \
165  ( long ,sl, 0, 5,0), \
166  ( unsigned long ,ul, 0, 6,0), \
167  ( float ,fl, 1, 7,0), \
168  ( double ,db, 1, 8,0), \
169  ( long double ,ld, 1, 9,0), \
170  ( std::complex<float> ,cfl, 1, 10,0), \
171  ( std::complex<double> ,cld, 1, 11,0), \
172  ( mp_type ,mp, 1,12,0), \
173  ( dd_real ,dd, 1,13,0), \
174  ( qd_real ,dd, 1,14,0) \
175  ) \
176  ) \
177 
178 # elif defined (DISABLE_FEELPP_HAS_QD_H )
179 # define VF_BUILTIN_TYPES \
180  BOOST_PP_TUPLE_TO_LIST( \
181  11, \
182  ( \
183  VF_TYPE_INT, \
184  ( unsigned ,ui, 0, 4,0), \
185  ( long ,sl, 0, 5,0), \
186  ( unsigned long ,ul, 0, 6,0), \
187  ( float ,fl, 1, 7,0), \
188  ( double ,db, 1, 8,0), \
189  ( long double ,ld, 1, 9,0), \
190  ( std::complex<float> ,cfl, 1, 10,0), \
191  ( std::complex<double> ,cld, 1, 11,0), \
192  ( dd_real ,dd, 1,12,0), \
193  ( qd_real ,dd, 1,13,0) \
194  ) \
195  ) \
196 
197 # elif defined (DISABLE_FEELPP_HAS_MPFR )
198 # define VF_BUILTIN_TYPES \
199  BOOST_PP_TUPLE_TO_LIST( \
200  10, \
201  ( \
202  VF_TYPE_INT, \
203  ( unsigned ,ui, 0, 4,0), \
204  ( long ,sl, 0, 5,0), \
205  ( unsigned long ,ul, 0, 6,0), \
206  ( float ,fl, 1, 7,0), \
207  ( double ,db, 1, 8,0), \
208  ( long double ,ld, 1, 9,0), \
209  ( std::complex<float> ,cfl, 1, 10,0), \
210  ( std::complex<double> ,cld, 1, 11,0), \
211  ( mp_type ,mp, 1,12,0) \
212  ) \
213  ) \
214 
215 #else
216 # define VF_BUILTIN_TYPES \
217  BOOST_PP_TUPLE_TO_LIST( \
218  9, \
219  ( \
220  VF_TYPE_INT, \
221  ( unsigned ,ui, 0, 4,0), \
222  ( long ,sl, 0, 5,0), \
223  ( unsigned long ,ul, 0, 6,0), \
224  ( float ,fl, 1, 7,0), \
225  ( double ,db, 1, 8,0), \
226  ( long double ,ld, 1, 9,0), \
227  ( std::complex<float> ,cfl, 1, 10,0), \
228  ( std::complex<double> ,cld, 1, 11,0) \
229  ) \
230  ) \
231 
232 # endif
233 #endif
234 #
235 # /* Type int is needed in some type computations. */
236 # define VF_TYPE_INT (int, si, 0, 3, 0)
237 #
238 # define VF_VALUE_TYPE(L) \
239  BOOST_PP_LIST_CAT(BOOST_PP_TUPLE_TO_LIST(2,(value_type_,VF_TYPE_ABBREVIATION(L)))) \
240 
241 #
242 # define VF_TYPE_CV(L) \
243  BOOST_PP_IF(VF_TYPE_IS_EXPR(L), \
244  BOOST_PP_IDENTITY(const&), \
245  BOOST_PP_EMPTY )() \
246 
247 #
248 # define VF_TYPE_VALUE_TYPE(L) \
249  BOOST_PP_IF(VF_TYPE_IS_EXPR(L), \
250  typename VF_TYPE_NAME(L)::value_type, \
251  VF_TYPE_NAME( L ) ) \
252 
253 #
254 # define VF_TYPE_TYPE(L) \
255  BOOST_PP_IF(VF_TYPE_IS_EXPR(L), \
256  VF_TYPE_NAME(L), \
257  Cst<VF_TYPE_NAME( L )> ) \
258 
259 #
260 # define VF_TYPE_TYPE_EXPR(L) \
261  BOOST_PP_IF(VF_TYPE_IS_EXPR(L), \
262  Expr<VF_TYPE_NAME(L)>, \
263  VF_TYPE_NAME( L ) ) \
264 
265 #
266 # define VF_TYPE_TYPE_EXPR_CST(L) \
267  BOOST_PP_IF(VF_TYPE_IS_EXPR(L), \
268  Expr<VF_TYPE_NAME(L)>, \
269  Cst<VF_TYPE_NAME( L )> ) \
270 
271 #
272 # define VF_TYPE_TYPE_CST(L) \
273  BOOST_PP_IF(BOOST_PP_NOT(VF_TYPE_IS_EXPR(L)), \
274  BOOST_PP_IDENTITY(Cst<VF_TYPE_NAME( L )>), \
275  BOOST_PP_EMPTY )() \
276 
277 #
278 # define VF_TEMPLATE_TYPE(L) \
279  BOOST_PP_IF(VF_TYPE_IS_EXPR(L), \
280  class VF_TYPE_NAME( L ), \
281  L ) \
282 
283 #
284 #define VF_TEXT(z, n, text) text
285 #
286 # define VF_SPECIALIZATION_IF_BUILTIN(L,R) \
287  BOOST_PP_IF(BOOST_PP_OR( BOOST_PP_NOT( VF_TYPE_IS_EXPR(L) ), \
288  BOOST_PP_NOT( VF_TYPE_IS_EXPR(R) ) ), \
289  BOOST_PP_IDENTITY(<VF_TYPE_TYPE(L)), \
290  BOOST_PP_EMPTY)() \
291  BOOST_PP_IF(BOOST_PP_OR( BOOST_PP_NOT( VF_TYPE_IS_EXPR(L) ), \
292  BOOST_PP_NOT( VF_TYPE_IS_EXPR(R) ) ), \
293  BOOST_PP_COMMA, \
294  BOOST_PP_EMPTY)() \
295  BOOST_PP_IF(BOOST_PP_OR( BOOST_PP_NOT( VF_TYPE_IS_EXPR(L) ), \
296  BOOST_PP_NOT( VF_TYPE_IS_EXPR(R) ) ), \
297  BOOST_PP_IDENTITY(VF_TYPE_TYPE(R)>), \
298  BOOST_PP_EMPTY)() \
299 
300 #
301 # define VF_IM_ORDER(O,L,R) \
302  BOOST_PP_IF( BOOST_PP_EQUAL( VF_OP_IMORDER(O) , 0) , \
303  0 , \
304  BOOST_PP_IF( BOOST_PP_EQUAL( VF_OP_IMORDER(O) , 1) , \
305  (VF_TYPE_TYPE(L)::imorder < VF_TYPE_TYPE(R)::imorder)*VF_TYPE_TYPE(R)::imorder \
306  + (VF_TYPE_TYPE(L)::imorder >= VF_TYPE_TYPE(R)::imorder)*VF_TYPE_TYPE(L)::imorder , \
307  VF_TYPE_TYPE(L)::imorder + VF_TYPE_TYPE(R)::imorder ) \
308  ) \
309 
310 #
311 #
312 # /* List of expression types. */
313 # define VF_EXPRL_TYPES \
314  BOOST_PP_TUPLE_TO_LIST( \
315  1, \
316  ( \
317  ( ExprL ,L, 1, 10, 1) \
318  ) \
319  ) \
320 
321 # /* List of expression types. */
322 # define VF_EXPRR_TYPES \
323  BOOST_PP_TUPLE_TO_LIST( \
324  1, \
325  ( \
326  ( ExprR ,R, 1, 10, 1) \
327  ) \
328  ) \
329 
330 #
331 # define VF_BOOST_PP_EMPTY() \
332 
333 #
334 # /* Generates code for all binary operators and integral type pairs. */
335 # define VF_BINARY_ARRAY_OP(_, OLR) \
336  VF_BINARY_ARRAY_OP_CODE OLR \
337 
338 
339 #define VF_BINARY_ARRAY_OP_CODE(O,L,R) \
340  template <BOOST_PP_IF( VF_TYPE_IS_EXPR( L ), \
341  BOOST_PP_IDENTITY(class VF_TYPE_NAME(L)), \
342  BOOST_PP_EMPTY \
343  )() \
344  BOOST_PP_IF( BOOST_PP_AND( VF_TYPE_IS_EXPR(L), \
345  VF_TYPE_IS_EXPR(R) ), \
346  BOOST_PP_COMMA, \
347  BOOST_PP_EMPTY )() \
348  BOOST_PP_IF( VF_TYPE_IS_EXPR( R ), \
349  BOOST_PP_IDENTITY(class VF_TYPE_NAME(R)), \
350  BOOST_PP_EMPTY \
351  )()> \
352  class VF_OP_NAME( O ) VF_SPECIALIZATION_IF_BUILTIN( L, R ) \
353  { \
354  public: \
355  typedef VF_OP_NAME( O )<VF_TYPE_TYPE_EXPR_CST( L ), VF_TYPE_TYPE_EXPR_CST( R )> expression_type; \
356  typedef VF_OP_NAME( O )<VF_TYPE_TYPE_EXPR_CST( L ), VF_TYPE_TYPE_EXPR_CST( R )> this_type; \
357  typedef VF_TYPE_VALUE_TYPE( L ) VF_VALUE_TYPE(L); \
358  typedef VF_TYPE_VALUE_TYPE( R ) VF_VALUE_TYPE(R); \
359  typedef VF_TYPE_TYPE( L ) L_type; \
360  typedef VF_TYPE_TYPE( R ) R_type; \
361  \
362  static const size_type context = L_type::context | R_type::context; \
363  \
364  static const uint16_type imorder = VF_IM_ORDER(O,L,R) ; \
365  static const bool imIsPoly = L_type::imIsPoly && R_type::imIsPoly; \
366  static const bool is_terminal = false; \
367  \
368  template<typename Func> \
369  struct HasTestFunction \
370  { \
371  static const bool result = L_type::template HasTestFunction<Func>::result|R_type::template HasTestFunction<Func>::result; \
372  }; \
373  \
374  template<typename Func> \
375  struct HasTrialFunction \
376  { \
377  static const bool result = L_type::template HasTrialFunction<Func>::result|R_type::template HasTrialFunction<Func>::result; \
378  }; \
379  \
380  typedef typename mpl::if_<mpl::greater<mpl::sizeof_<VF_VALUE_TYPE(L)>, \
381  mpl::sizeof_<VF_VALUE_TYPE(R)> >, \
382  mpl::identity<VF_VALUE_TYPE(L)>, \
383  mpl::identity<VF_VALUE_TYPE(R)> >::type::type value_type; \
384  \
385  VF_OP_NAME( O )( L_type const& left, R_type const& right ) \
386  : \
387  M_left(left), \
388  M_right(right) \
389  {} \
390  VF_OP_NAME( O )( VF_OP_NAME(O) const& __m ) \
391  : \
392  M_left( __m.M_left ), \
393  M_right( __m.M_right ) \
394  {;} \
395  ~VF_OP_NAME( O )() \
396  {} \
397  template<typename TheExpr> \
398  struct Lambda \
399  { \
400  typedef VF_OP_NAME( O )<typename L_type::template Lambda<TheExpr>::type,typename R_type::template Lambda<TheExpr>::type> type; \
401  }; \
402  \
403  template<typename TheExpr> \
404  typename Lambda<TheExpr>::type \
405  operator()( TheExpr const& e ) { return typename Lambda<TheExpr>::type( M_left(e), M_right(e) ); } \
406  \
407  L_type VF_TYPE_CV(L) left() const { return M_left; } \
408  R_type VF_TYPE_CV(R) right() const { return M_right; } \
409  \
410  template<typename Geo_t, typename Basis_i_t, typename Basis_j_t = Basis_i_t> \
411  struct tensor \
412  { \
413  typedef this_type expression_type; \
414  typedef typename L_type::template tensor<Geo_t, Basis_i_t, Basis_j_t> l_type; \
415  typedef typename R_type::template tensor<Geo_t, Basis_i_t, Basis_j_t> r_type; \
416  typedef typename strongest_numeric_type<typename l_type::value_type, \
417  typename r_type::value_type>::type value_type; \
418  typedef typename VF_OP_SHAPE( O )<typename l_type::shape, typename r_type::shape>::type shape; \
419  static const int shape_op = VF_OP_SHAPE( O )<typename l_type::shape, typename r_type::shape>::op; \
420  \
421  struct is_zero { \
422  static const bool value = VF_OP_SHAPE( O )<typename l_type::shape, typename r_type::shape>::template is_zero<l_type::is_zero::value, r_type::is_zero::value>::value; \
423  static const bool update_and_eval_left = VF_OP_SHAPE( O )<typename l_type::shape, typename r_type::shape>::template is_zero<l_type::is_zero::value, r_type::is_zero::value>::update_and_eval_left; \
424  static const bool update_and_eval_right = VF_OP_SHAPE( O )<typename l_type::shape, typename r_type::shape>::template is_zero<l_type::is_zero::value, r_type::is_zero::value>::update_and_eval_right; \
425  }; \
426  \
427  template<typename ExprT> \
428  tensor( ExprT const& expr, Geo_t const& geom, Basis_i_t const& fev, Basis_j_t const& feu ) \
429  : \
430  M_left( expr.left(), geom, fev, feu ), \
431  M_right( expr.right(), geom, fev, feu ) \
432  { \
433  DVLOG(2) << "Operation " BOOST_PP_STRINGIZE( VF_OP_SYMBOL( O ) ) " is_zero " << is_zero::value << " " \
434  << "update_and_eval_left " << is_zero::update_and_eval_left << " " \
435  << " update_and_eval_right " << is_zero::update_and_eval_right << " " \
436  << " left_is_zero " << l_type::is_zero::value << " " \
437  << " right_is_zero " << r_type::is_zero::value << "\n"; \
438  } \
439  template<typename ExprT> \
440  tensor( ExprT const& expr,Geo_t const& geom, Basis_i_t const& fev ) \
441  : \
442  M_left( expr.left(), geom, fev ), \
443  M_right( expr.right(), geom, fev ) \
444  {} \
445  template<typename ExprT> \
446  tensor( ExprT const& expr, Geo_t const& geom ) \
447  : \
448  M_left( expr.left(), geom ), \
449  M_right( expr.right(), geom ) \
450  { \
451  } \
452  template<typename IM> \
453  void init( IM const& im ) \
454  { \
455  M_left.init( im ); \
456  M_right.init( im ); \
457  } \
458  void update( Geo_t const& geom, Basis_i_t const& fev, Basis_j_t const& feu ) \
459  { \
460  if ( is_zero::update_and_eval_left ) \
461  M_left.update( geom, fev, feu ); \
462  if ( is_zero::update_and_eval_right ) \
463  M_right.update( geom, fev, feu ); \
464  } \
465  void update( Geo_t const& geom, Basis_i_t const& fev ) \
466  { \
467  if ( is_zero::update_and_eval_left ) \
468  M_left.update( geom, fev ); \
469  if ( is_zero::update_and_eval_right ) \
470  M_right.update( geom, fev ); \
471  } \
472  void update( Geo_t const& geom ) \
473  { \
474  if ( is_zero::update_and_eval_left ) \
475  M_left.update( geom ); \
476  if ( is_zero::update_and_eval_right ) \
477  M_right.update( geom ); \
478  } \
479  void update( Geo_t const& geom, uint16_type face ) \
480  { \
481  if ( is_zero::update_and_eval_left ) \
482  M_left.update( geom, face ); \
483  if ( is_zero::update_and_eval_right ) \
484  M_right.update( geom, face ); \
485  } \
486  \
487  value_type \
488  evalij( uint16_type i, uint16_type j ) const \
489  { \
490  return M_left.evalij(i,j) VF_OP_SYMBOL( O ) M_right.evalij(i,j); \
491  } \
492  \
493  value_type \
494  evalijq( uint16_type i, uint16_type j, uint16_type c1, uint16_type c2, uint16_type q ) const \
495  { \
496  return evalijq(i,j,c1,c2,q,mpl::int_<shape_op>() ); \
497  } \
498  template<int PatternContext> \
499  value_type \
500  evalijq( uint16_type i, uint16_type j, uint16_type c1, uint16_type c2, uint16_type q, mpl::int_<PatternContext> ) const \
501  { \
502  return evalijq(i,j,c1,c2,q,mpl::int_<PatternContext>(),mpl::int_<shape_op>() ); \
503  } \
504  \
505  value_type \
506  evalijq( uint16_type i, uint16_type j, uint16_type c1, uint16_type c2, uint16_type q, mpl::int_<0> ) const \
507  { \
508  return evalijq( i, j, c1, c2, q, mpl::bool_<is_zero::update_and_eval_left>(), mpl::bool_<is_zero::update_and_eval_right>() ); \
509  } \
510  \
511  value_type \
512  evalijq( uint16_type i, uint16_type j, uint16_type c1, uint16_type c2, uint16_type q, mpl::bool_<false>, mpl::bool_<false> ) const \
513  { \
514  return value_type( 0 ); \
515  } \
516  \
517  value_type \
518  evalijq( uint16_type i, uint16_type j, uint16_type c1, uint16_type c2, uint16_type q, mpl::bool_<true>, mpl::bool_<false> ) const \
519  { \
520  return M_left.evalijq(i, j, c1, c2, q); \
521  } \
522  \
523  value_type \
524  evalijq( uint16_type i, uint16_type j, uint16_type c1, uint16_type c2, uint16_type q, mpl::bool_<false>, mpl::bool_<true> ) const \
525  { \
526  return M_right.evalijq(i, j, c1, c2, q); \
527  } \
528  \
529  value_type \
530  evalijq( uint16_type i, uint16_type j, uint16_type c1, uint16_type c2, uint16_type q, mpl::bool_<true>, mpl::bool_<true> ) const \
531  { \
532  return M_left.evalijq(i, j, c1, c2, q) VF_OP_SYMBOL( O ) M_right.evalijq(i,j, c1, c2, q); \
533  } \
534  \
535  value_type \
536  evalijq( uint16_type i, uint16_type j, uint16_type c1, uint16_type c2, uint16_type q, mpl::int_<1> ) const \
537  { \
538  return evalijq( i, j, c1, c2, q, mpl::bool_<is_zero::value>() ); \
539  } \
540  \
541  value_type \
542  evalijq( uint16_type i, uint16_type j, uint16_type c1, uint16_type c2, uint16_type q, mpl::bool_<true> ) const \
543  { \
544  return value_type( 0 ); \
545  } \
546  \
547  value_type \
548  evalijq( uint16_type i, uint16_type j, uint16_type c1, uint16_type c2, uint16_type q, mpl::bool_<false> ) const \
549  { \
550  value_type res( value_type( 0 ) ); \
551  for(uint16_type ii = 0; ii < l_type::shape::N; ++ii ) \
552  res += M_left.evalijq(i, j, c1, ii, q ) VF_OP_SYMBOL( O ) M_right.evalijq(i, j, ii, c2, q ); \
553  return res; \
554  } \
555  template<int PatternContext> \
556  value_type \
557  evalijq__( uint16_type i, uint16_type j, uint16_type c1, uint16_type c2, uint16_type q, mpl::int_<PatternContext>, mpl::int_<0> ) const \
558  { \
559  if ( is_zero::value ) \
560  return value_type( 0 ); \
561  else if ( !is_zero::update_and_eval_left && is_zero::update_and_eval_right ) \
562  return M_right.evalijq(i,j, c1, c2, q,mpl::int_<PatternContext>()); \
563  else if ( is_zero::update_and_eval_left && !is_zero::update_and_eval_right ) \
564  return M_left.evalijq(i, j, c1, c2, q,mpl::int_<PatternContext>()); \
565  else \
566  return M_left.evalijq(i, j, c1, c2, q,mpl::int_<PatternContext>()) VF_OP_SYMBOL( O ) M_right.evalijq(i,j, c1, c2, q,mpl::int_<PatternContext>()); \
567  } \
568  template<int PatternContext> \
569  value_type \
570  evalijq( uint16_type i, uint16_type j, uint16_type c1, uint16_type c2, uint16_type q, mpl::int_<PatternContext>, mpl::int_<0> ) const \
571  { \
572  return M_left.evalijq(i, j, c1, c2, q,mpl::int_<PatternContext>()) VF_OP_SYMBOL( O ) M_right.evalijq(i,j, c1, c2, q,mpl::int_<PatternContext>()); \
573  } \
574  template<int PatternContext> \
575  value_type \
576  evalijq( uint16_type i, uint16_type j, uint16_type c1, uint16_type c2, uint16_type q, mpl::int_<PatternContext>, mpl::int_<1> ) const \
577  { \
578  value_type res( value_type( 0 ) ); \
579  for(uint16_type ii = 0; ii < l_type::shape::N; ++ii ) \
580  res += M_left.evalijq(i, j, c1, ii, q,mpl::int_<PatternContext>() ) VF_OP_SYMBOL( O ) M_right.evalijq(i, j, ii, c2, q,mpl::int_<PatternContext>() ); \
581  return res; \
582  } \
583  \
584  value_type \
585  evaliq( uint16_type i, uint16_type c1, uint16_type c2, uint16_type q ) const \
586  { \
587  return evaliq(i, c1, c2, q, mpl::int_<shape_op>() ); \
588  } \
589  \
590  value_type \
591  evaliq( uint16_type i, uint16_type c1, uint16_type c2, uint16_type q, mpl::int_<0> ) const \
592  { \
593  if ( is_zero::value ) \
594  return value_type( 0 ); \
595  else if ( !is_zero::update_and_eval_left && is_zero::update_and_eval_right ) \
596  return M_right.evaliq(i, c1, c2, q); \
597  else if ( is_zero::update_and_eval_left && !is_zero::update_and_eval_right ) \
598  return M_left.evaliq(i, c1, c2, q); \
599  else \
600  return M_left.evaliq(i, c1, c2, q) VF_OP_SYMBOL( O ) M_right.evaliq(i, c1, c2, q); \
601  } \
602  \
603  value_type \
604  evaliq( uint16_type i, uint16_type c1, uint16_type c2, uint16_type q, mpl::int_<1> ) const \
605  { \
606  if ( is_zero::value ) \
607  return value_type( 0 ); \
608  else \
609  { \
610  value_type res( value_type( 0 ) ); \
611  for(uint16_type ii = 0; ii < l_type::shape::N; ++ii ) \
612  res += M_left.evaliq(i, c1, ii, q ) VF_OP_SYMBOL( O ) M_right.evaliq(i, ii, c2, q ); \
613  return res; \
614  } \
615  } \
616  value_type \
617  evalq( uint16_type c1, uint16_type c2, uint16_type q ) const \
618  { \
619  return evalq( c1, c2, q, mpl::int_<shape_op>() ); \
620  } \
621  \
622  value_type \
623  evalq( uint16_type c1, uint16_type c2, uint16_type q, mpl::int_<0> ) const \
624  { \
625  return M_left.evalq( c1, c2, q ) VF_OP_SYMBOL( O ) M_right.evalq( c1, c2, q ); \
626  } \
627  value_type \
628  evalq( uint16_type c1, uint16_type c2, uint16_type q, mpl::int_<1> ) const \
629  { \
630  value_type res( value_type( 0 ) ); \
631  for(uint16_type ii = 0; ii < l_type::shape::N; ++ii ) \
632  res += M_left.evalq( c1, ii, q ) VF_OP_SYMBOL( O ) M_right.evalq( ii, c2, q ); \
633  return res; \
634  } \
635  l_type M_left; \
636  r_type M_right; \
637  }; /* tensor */ \
638  double \
639  evaluate() const \
640  { \
641  return M_left.evaluate() VF_OP_SYMBOL( O ) M_right.evaluate(); \
642  } \
643  double \
644  evaluate(bool p) const \
645  { \
646  return M_left.evaluate(p) VF_OP_SYMBOL( O ) M_right.evaluate(p); \
647  } \
648  \
649  std::string expressionStr() const \
650  { \
651  return std::string();/*M_left.expressionStr() + BOOST_PP_STRINGIZE( VF_OP_SYMBOL( O ) ) + M_right.expressionStr();*/ \
652  } \
653  BOOST_PP_IF(1, \
654  VF_SYMETRIC, \
655  BOOST_PP_EMPTY )() \
656  BOOST_PP_IF(BOOST_PP_AND(VF_OP_IS_ADD(O), \
657  BOOST_PP_AND(VF_TYPE_IS_EXPR(L),VF_TYPE_IS_EXPR(R))), \
658  VF_ASSEMBLE, \
659  BOOST_PP_EMPTY )() \
660  \
661  protected: \
662  VF_OP_NAME( O )() {} \
663  \
664  L_type M_left; \
665  R_type M_right; \
666  }; \
667  template <BOOST_PP_IF( VF_TYPE_IS_EXPR( L ), \
668  BOOST_PP_IDENTITY(class VF_TYPE_NAME(L)), \
669  BOOST_PP_EMPTY \
670  )() \
671  BOOST_PP_IF( BOOST_PP_AND( VF_TYPE_IS_EXPR(L), \
672  VF_TYPE_IS_EXPR(R) ), \
673  BOOST_PP_COMMA, \
674  BOOST_PP_EMPTY )() \
675  BOOST_PP_IF( VF_TYPE_IS_EXPR( R ), \
676  BOOST_PP_IDENTITY(class VF_TYPE_NAME(R)), \
677  BOOST_PP_EMPTY \
678  )()> \
679  inline \
680  Expr< VF_OP_NAME( O )< VF_TYPE_TYPE_EXPR_CST(L), VF_TYPE_TYPE_EXPR_CST(R) > > \
681  operator VF_OP_SYMBOL( O )( VF_TYPE_TYPE_EXPR(L) VF_TYPE_CV(L) v, VF_TYPE_TYPE_EXPR(R) VF_TYPE_CV(R) w ) \
682  { \
683  typedef VF_OP_NAME( O )<VF_TYPE_TYPE_EXPR_CST( L ), VF_TYPE_TYPE_EXPR_CST( R )> expr_t; \
684  return Expr<expr_t> (expr_t ( VF_TYPE_TYPE_CST(L)(v) , VF_TYPE_TYPE_CST(R)(w) )); \
685  } \
686 
687 #
688 # define VF_ASSEMBLE() \
689  template<typename Elem1, typename Elem2, typename FormType> \
690  void assemble( boost::shared_ptr<Elem1> const& __u, boost::shared_ptr<Elem2> const& __v, FormType& __f ) const \
691  { \
692  M_left.assemble( __u, __v, __f ); \
693  M_right.assemble( __u, __v, __f ); \
694  } \
695  \
696  template<typename Elem1, typename FormType> \
697  void assemble( boost::shared_ptr<Elem1> const& __v, FormType& __f ) const \
698  { \
699  M_left.assemble( __v, __f ); \
700  M_right.assemble( __v, __f ); \
701  } \
702 
703 #
704 # define VF_SYMETRIC() \
705  bool isSymetric() const \
706  { \
707  return false; \
708  } \
709 
710 #
711 
712 namespace Feel
713 {
714 namespace vf
715 {
716 BOOST_PP_LIST_FOR_EACH_PRODUCT( VF_BINARY_ARRAY_OP, 3, ( VF_APPLICATIVE_BINARY_OPS, VF_EXPRL_TYPES, VF_EXPRR_TYPES ) )
717 BOOST_PP_LIST_FOR_EACH_PRODUCT( VF_BINARY_ARRAY_OP, 3, ( VF_APPLICATIVE_BINARY_OPS, VF_EXPRL_TYPES, VF_BUILTIN_TYPES ) )
718 BOOST_PP_LIST_FOR_EACH_PRODUCT( VF_BINARY_ARRAY_OP, 3, ( VF_APPLICATIVE_BINARY_OPS, VF_BUILTIN_TYPES, VF_EXPRR_TYPES ) )
719 }
720 }
721 
723 #endif /* PP_OPERATORS_HPP */

Generated on Fri Oct 25 2013 14:24:22 for Feel++ by doxygen 1.8.4