00001 #ifndef VIENNAMATH_MANIPULATION_INTEGRATE_HPP
00002 #define VIENNAMATH_MANIPULATION_INTEGRATE_HPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "viennamath/forwards.h"
00021 #include "viennamath/compiletime/ct_interval.hpp"
00022 #include "viennamath/manipulation/expand.hpp"
00023 #include "viennamath/manipulation/simplify.hpp"
00024 #include "viennamath/manipulation/substitute.hpp"
00025
00030 namespace viennamath
00031 {
00032
00034
00035
00036 namespace result_of
00037 {
00039 template <typename VariableType, typename ExpressionType>
00040 struct polynomial_degree
00041 {
00042 enum { value = 0 };
00043 };
00044
00046 template <typename VariableType>
00047 struct polynomial_degree <VariableType, VariableType>
00048 {
00049 enum { value = 1 };
00050 };
00051
00053 template <typename VariableType,
00054 typename LHS, typename NumericT, typename RHS>
00055 struct polynomial_degree <VariableType, ct_binary_expr<LHS, op_plus<NumericT>, RHS> >
00056 {
00057 typedef typename ct_binary_expr<LHS, op_plus<NumericT>, RHS>::ERROR_CANNOT_DEDUCE_POLYNOMIAL_DEGREE_FROM_SUM error_type;
00058 };
00059
00061 template <typename VariableType,
00062 typename LHS, typename NumericT, typename RHS>
00063 struct polynomial_degree <VariableType, ct_binary_expr<LHS, op_minus<NumericT>, RHS> >
00064 {
00065 typedef typename ct_binary_expr<LHS, op_plus<NumericT>, RHS>::ERROR_CANNOT_DEDUCE_POLYNOMIAL_DEGREE_FROM_SUM error_type;
00066 };
00067
00069 template <typename VariableType,
00070 typename LHS, typename NumericT, typename RHS>
00071 struct polynomial_degree <VariableType, ct_binary_expr<LHS, op_mult<NumericT>, RHS> >
00072 {
00073 enum { value = polynomial_degree<VariableType, LHS>::value + polynomial_degree<VariableType, RHS>::value };
00074 };
00075
00077 template <typename VariableType,
00078 typename LHS, typename NumericT, typename RHS>
00079 struct polynomial_degree <VariableType, ct_binary_expr<LHS, op_div<NumericT>, RHS> >
00080 {
00081 enum { value = polynomial_degree<VariableType, LHS>::value - polynomial_degree<VariableType, RHS>::value };
00082 };
00083
00084
00085
00087 template <typename T, long exponent>
00088 struct pow
00089 {
00090
00091 typedef ct_binary_expr< typename pow<T, exponent / 2>::type,
00092 op_mult<default_numeric_type>,
00093 typename pow<T, exponent - exponent / 2>::type> type;
00094 };
00095
00097 template <typename T>
00098 struct pow <T, 0>
00099 {
00100 typedef ct_constant<1> type;
00101 };
00102
00104 template <typename T>
00105 struct pow <T, 1>
00106 {
00107 typedef T type;
00108 };
00109
00111 template <typename T>
00112 struct pow <T, 2>
00113 {
00114 typedef ct_binary_expr<T, op_mult<default_numeric_type>, T> type;
00115 };
00116
00117
00118
00119
00121 template <typename VariableType,
00122 long exponent>
00123 struct integrate_monomial
00124 {
00125 typedef ct_binary_expr< typename pow<VariableType, exponent + 1>::type,
00126 op_div<default_numeric_type>,
00127 ct_constant<exponent + 1>
00128 > type;
00129 };
00130
00132 template <typename VariableType>
00133 struct integrate_monomial < VariableType, 0>
00134 {
00135 typedef VariableType type;
00136 };
00137
00138
00140
00150 template <typename LowerBound, typename UpperBound,
00151 typename IntegrandType,
00152 typename VariableType>
00153 struct integrate {};
00154
00155
00156 namespace detail
00157 {
00159 template <typename LowerBound, typename UpperBound,
00160 typename IntegrandType,
00161 typename VariableType>
00162 struct integrate_impl {};
00163
00164
00165
00166 template <typename LowerBound, typename UpperBound,
00167 typename LHS, typename NumericT, typename RHS,
00168 typename VariableType>
00169 struct integrate_impl <LowerBound, UpperBound,
00170 ct_binary_expr<LHS, op_plus<NumericT>, RHS>,
00171 VariableType
00172 >
00173 {
00174 typedef ct_binary_expr< typename integrate_impl<LowerBound, UpperBound, LHS, VariableType>::type,
00175 op_plus<NumericT>,
00176 typename integrate_impl<LowerBound, UpperBound, RHS, VariableType>::type
00177 > integrated_type;
00178
00179 typedef typename viennamath::result_of::simplify<integrated_type>::type type;
00180 };
00181
00182 template <typename LowerBound, typename UpperBound,
00183 typename LHS, typename NumericT, typename RHS,
00184 typename VariableType>
00185 struct integrate_impl <LowerBound, UpperBound,
00186 ct_binary_expr<LHS, op_minus<NumericT>, RHS>,
00187 VariableType
00188 >
00189 {
00190 typedef ct_binary_expr< typename integrate_impl<LowerBound, UpperBound, LHS, VariableType>::type,
00191 op_minus<NumericT>,
00192 typename integrate_impl<LowerBound, UpperBound, RHS, VariableType>::type
00193 > integrated_type;
00194
00195 typedef typename viennamath::result_of::simplify<integrated_type>::type type;
00196 };
00197
00198
00199 template <typename LowerBound, typename UpperBound,
00200 typename LHS, typename NumericT, typename RHS,
00201 typename VariableType>
00202 struct integrate_impl <LowerBound, UpperBound,
00203 ct_binary_expr<LHS, op_mult<NumericT>, RHS>,
00204 VariableType
00205 >
00206 {
00207
00208 typedef typename viennamath::result_of::substitute< VariableType,
00209 ct_constant<1>,
00210 ct_binary_expr<LHS, op_mult<NumericT>, RHS> >::type coefficient_type;
00211
00212 typedef typename viennamath::result_of::simplify<coefficient_type>::type simplified_coefficient_type;
00213
00214 enum { exponent = polynomial_degree<VariableType,
00215 ct_binary_expr<LHS, op_mult<NumericT>, RHS>
00216 >::value };
00217
00218 typedef ct_binary_expr< typename integrate_monomial<UpperBound, exponent>::type,
00219 op_mult<NumericT>,
00220 simplified_coefficient_type
00221 > upper_contribution;
00222
00223 typedef ct_binary_expr< typename integrate_monomial<LowerBound, exponent>::type,
00224 op_mult<NumericT>,
00225 simplified_coefficient_type
00226 > lower_contribution;
00227
00228 typedef ct_binary_expr< typename simplify<upper_contribution>::type,
00229 op_minus<NumericT>,
00230 typename simplify<lower_contribution>::type
00231 > integrated_type;
00232
00233 typedef typename viennamath::result_of::simplify<integrated_type>::type type;
00234 };
00235
00236 template <typename LowerBound, typename UpperBound,
00237 typename LHS, typename NumericT, typename RHS,
00238 typename VariableType>
00239 struct integrate_impl <LowerBound, UpperBound,
00240 ct_binary_expr<LHS, op_div<NumericT>, RHS>,
00241 VariableType
00242 >
00243 {
00244
00245 typedef ct_binary_expr< typename integrate_impl<LowerBound, UpperBound,
00246 LHS,
00247 VariableType>::type,
00248 op_div<NumericT>,
00249 RHS> integrated_type;
00250
00251 typedef typename viennamath::result_of::simplify<integrated_type>::type type;
00252 };
00253
00254 template <typename LowerBound, typename UpperBound,
00255 typename LHS, typename OP,
00256 typename VariableType>
00257 struct integrate_impl <LowerBound, UpperBound,
00258 ct_unary_expr<LHS, OP>,
00259 VariableType
00260 >
00261 {
00262 typedef typename ct_unary_expr<LHS, OP>::ERROR_INTEGRATION_OF_UNARY_EXPRESSION_NOT_SUPPORTED type;
00263 };
00264
00265 template <typename LowerBound, typename UpperBound,
00266 long value,
00267 typename VariableType>
00268 struct integrate_impl <LowerBound, UpperBound,
00269 ct_constant<value>,
00270 VariableType
00271 >
00272 {
00273 typedef ct_binary_expr<UpperBound,
00274 op_minus<default_numeric_type>,
00275 LowerBound
00276 > interval_length;
00277
00278 typedef ct_binary_expr< ct_constant<value>,
00279 op_mult<default_numeric_type>,
00280 interval_length
00281 > integrated_type;
00282
00283 typedef typename viennamath::result_of::simplify<integrated_type>::type type;
00284 };
00285
00286 template <typename LowerBound, typename UpperBound,
00287 typename TAG,
00288 typename VariableType>
00289 struct integrate_impl <LowerBound, UpperBound,
00290 ct_function_symbol<TAG>,
00291 VariableType
00292 >
00293 {
00294 typedef typename ct_function_symbol<TAG>::ERROR_INTEGRATION_OF_FUNCTION_SYMBOL_NOT_SUPPORTED type;
00295 };
00296
00297 template <typename LowerBound, typename UpperBound,
00298 id_type id,
00299 typename VariableType>
00300 struct integrate_impl <LowerBound, UpperBound,
00301 ct_variable<id>,
00302 VariableType
00303 >
00304 {
00305 typedef ct_binary_expr< ct_binary_expr<UpperBound,
00306 op_mult<default_numeric_type>,
00307 UpperBound
00308 >,
00309 op_div<default_numeric_type>,
00310 ct_constant<2>
00311 > upper_contribution;
00312
00313 typedef ct_binary_expr< ct_binary_expr<LowerBound,
00314 op_mult<default_numeric_type>,
00315 LowerBound
00316 >,
00317 op_div<default_numeric_type>,
00318 ct_constant<2>
00319 > lower_contribution;
00320
00321 typedef ct_binary_expr<upper_contribution,
00322 op_minus<default_numeric_type>,
00323 lower_contribution> integrated_type;
00324
00325 typedef typename viennamath::result_of::simplify<integrated_type>::type type;
00326 };
00327
00328 }
00329
00330
00331
00332
00334 template <typename LowerBound, typename UpperBound,
00335 typename LHS, typename OP, typename RHS,
00336 typename VariableType>
00337 struct integrate <LowerBound, UpperBound,
00338 ct_binary_expr<LHS, OP, RHS>,
00339 VariableType
00340 >
00341 {
00342
00343 typedef ct_binary_expr<LHS, OP, RHS> IntegrandType;
00344 typedef typename viennamath::result_of::expand<IntegrandType>::type expanded_integrand;
00345 typedef typename viennamath::result_of::simplify<expanded_integrand>::type simplified_integrand;
00346
00347 typedef typename detail::integrate_impl<LowerBound, UpperBound,
00348 simplified_integrand,
00349 VariableType>::type type;
00350
00351 };
00352
00354 template <typename LowerBound, typename UpperBound,
00355 typename LHS, typename OP,
00356 typename VariableType>
00357 struct integrate <LowerBound, UpperBound,
00358 ct_unary_expr<LHS, OP>,
00359 VariableType
00360 >
00361 {
00362 typedef typename ct_unary_expr<LHS, OP>::ERROR_INTEGRATION_OF_UNARY_EXPRESSION_NOT_SUPPORTED type;
00363 };
00364
00366 template <typename LowerBound, typename UpperBound,
00367 long value,
00368 typename VariableType>
00369 struct integrate <LowerBound, UpperBound,
00370 ct_constant<value>,
00371 VariableType
00372 >
00373 {
00374 typedef typename detail::integrate_impl<LowerBound, UpperBound, ct_constant<value>, VariableType >::type type;
00375 };
00376
00378 template <typename LowerBound, typename UpperBound,
00379 typename TAG,
00380 typename VariableType>
00381 struct integrate <LowerBound, UpperBound,
00382 ct_function_symbol<TAG>,
00383 VariableType
00384 >
00385 {
00386 typedef typename ct_function_symbol<TAG>::ERROR_INTEGRATION_OF_FUNCTION_SYMBOL_NOT_SUPPORTED type;
00387 };
00388
00390 template <typename LowerBound, typename UpperBound,
00391 id_type id,
00392 typename VariableType>
00393 struct integrate <LowerBound, UpperBound,
00394 ct_variable<id>,
00395 VariableType
00396 >
00397 {
00398 typedef typename detail::integrate_impl<LowerBound, UpperBound, ct_variable<id>, VariableType >::type type;
00399 };
00400
00401
00402 }
00403
00410 template <typename LowerBound, typename UpperBound,
00411 typename IntegrandType,
00412 typename VariableType>
00413 typename result_of::integrate<LowerBound, UpperBound,
00414 IntegrandType,
00415 VariableType>::type
00416 integrate( ct_interval<LowerBound, UpperBound> const & interv,
00417 IntegrandType const & integrand,
00418 VariableType const & var)
00419 {
00420 return typename result_of::integrate<LowerBound, UpperBound,
00421 IntegrandType,
00422 VariableType>::type();
00423 }
00424
00425
00427
00428
00429
00430 }
00431
00432 #endif