00001 #ifndef VIENNAMATH_BINARY_OPERATORS_MANIPULATION_HPP
00002 #define VIENNAMATH_BINARY_OPERATORS_MANIPULATION_HPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <string>
00021 #include <vector>
00022 #include <math.h>
00023 #include "viennamath/forwards.h"
00024 #include "viennamath/compiletime/binary_op_tags.hpp"
00025 #include "viennamath/runtime/binary_expr.hpp"
00026 #include "viennamath/runtime/unary_expr.hpp"
00027
00032 namespace viennamath
00033 {
00034
00035
00036
00037
00038
00040 template <typename InterfaceType, typename NumericT>
00041 InterfaceType * diff_impl(const InterfaceType * lhs, op_plus<NumericT>, const InterfaceType * rhs, const InterfaceType * diff_var)
00042 {
00043 return new rt_binary_expr<InterfaceType>( lhs->diff(diff_var),
00044 new op_binary<op_plus<NumericT>, InterfaceType>(),
00045 rhs->diff(diff_var) );
00046 }
00047
00049 template <typename InterfaceType, typename NumericT>
00050 InterfaceType * simplify_impl(const InterfaceType * lhs, op_plus<NumericT>, const InterfaceType * rhs)
00051 {
00052 if (lhs->is_constant())
00053 {
00054 NumericT val = lhs->unwrap();
00055 if (val == 0.0)
00056 return rhs->simplify();
00057
00058 return new rt_binary_expr<InterfaceType>(new rt_constant<NumericT, InterfaceType>(val),
00059 new op_binary<op_plus<NumericT>, InterfaceType>(),
00060 rhs->simplify());
00061 }
00062 else if (rhs->is_constant())
00063 {
00064 NumericT val = rhs->unwrap();
00065 if (val == 0.0)
00066 return lhs->simplify();
00067
00068 return new rt_binary_expr<InterfaceType>(lhs->simplify(),
00069 new op_binary<op_plus<NumericT>, InterfaceType>(),
00070 new rt_constant<NumericT, InterfaceType>(val));
00071 }
00072
00073 return new rt_binary_expr<InterfaceType>(lhs->simplify(),
00074 new op_binary<op_plus<NumericT>, InterfaceType>(),
00075 rhs->simplify());
00076 }
00077
00079 template <typename InterfaceType, typename NumericT>
00080 bool can_simplify_impl(const InterfaceType * lhs, op_plus<NumericT>, const InterfaceType * rhs)
00081 {
00082 if (lhs->is_constant())
00083 {
00084 if (lhs->unwrap() == 0.0)
00085 {
00086
00087 return true;
00088 }
00089 }
00090 if (rhs->is_constant())
00091 {
00092 if (rhs->unwrap() == 0.0)
00093 {
00094
00095 return true;
00096 }
00097 }
00098 return lhs->can_simplify() || rhs->can_simplify();
00099 }
00100
00101
00102
00103
00104
00105
00106
00108 template <typename InterfaceType, typename NumericT>
00109 InterfaceType * diff_impl(const InterfaceType * lhs, op_minus<NumericT>, const InterfaceType * rhs, const InterfaceType * diff_var)
00110 {
00111 return new rt_binary_expr<InterfaceType>( lhs->diff(diff_var),
00112 new op_binary<op_minus<NumericT>, InterfaceType>(),
00113 rhs->diff(diff_var) );
00114 }
00115
00117 template <typename InterfaceType, typename NumericT>
00118 InterfaceType * simplify_impl(const InterfaceType * lhs, op_minus<NumericT>, const InterfaceType * rhs)
00119 {
00120 if (lhs->is_constant())
00121 {
00122 NumericT val = lhs->unwrap();
00123 if (val == 0.0)
00124 {
00125 return new rt_binary_expr<InterfaceType>(new rt_constant<NumericT, InterfaceType>(-1),
00126 new op_binary<op_mult<NumericT>, InterfaceType>(),
00127 rhs->simplify());
00128 }
00129
00130 return new rt_binary_expr<InterfaceType>(new rt_constant<NumericT, InterfaceType>(val),
00131 new op_binary<op_minus<NumericT>, InterfaceType>(),
00132 rhs->simplify());
00133 }
00134 else if (rhs->is_constant())
00135 {
00136 NumericT val = rhs->unwrap();
00137 if (val == 0.0)
00138 return lhs->simplify();
00139
00140 return new rt_binary_expr<InterfaceType>(lhs->simplify(),
00141 new op_binary<op_minus<NumericT>, InterfaceType>(),
00142 new rt_constant<NumericT, InterfaceType>(val));
00143 }
00144
00145 return new rt_binary_expr<InterfaceType>(lhs->simplify(),
00146 new op_binary<op_minus<NumericT>, InterfaceType>(),
00147 rhs->simplify());
00148 }
00149
00151 template <typename InterfaceType, typename NumericT>
00152 bool can_simplify_impl(const InterfaceType * lhs, op_minus<NumericT>, const InterfaceType * rhs)
00153 {
00154 if (lhs->is_constant())
00155 {
00156 if (lhs->unwrap() == 0.0)
00157 {
00158
00159 return true;
00160 }
00161 }
00162
00163 if (rhs->is_constant())
00164 {
00165 if (rhs->unwrap() == 0.0)
00166 {
00167
00168 return true;
00169 }
00170 }
00171
00172 return lhs->can_simplify() || rhs->can_simplify();
00173 }
00174
00175
00176
00177
00178
00179
00180
00182 template <typename InterfaceType, typename NumericT>
00183 InterfaceType * diff_impl(const InterfaceType * lhs, op_mult<NumericT>, const InterfaceType * rhs, const InterfaceType * diff_var)
00184 {
00185 return new rt_binary_expr<InterfaceType>( new rt_binary_expr<InterfaceType>(lhs->diff(diff_var),
00186 new op_binary<op_mult<NumericT>, InterfaceType>(),
00187 rhs->clone()),
00188 new op_binary<op_plus<NumericT>, InterfaceType>(),
00189 new rt_binary_expr<InterfaceType>(lhs->clone(),
00190 new op_binary<op_mult<NumericT>, InterfaceType>(),
00191 rhs->diff(diff_var) )
00192 );
00193 }
00194
00196 template <typename InterfaceType, typename NumericT>
00197 InterfaceType * simplify_impl(const InterfaceType * lhs, op_mult<NumericT>, const InterfaceType * rhs)
00198 {
00199 if (lhs->is_constant())
00200 {
00201 NumericT val = lhs->unwrap();
00202 if (val == 0.0)
00203 return new rt_constant<NumericT, InterfaceType>(0.0);
00204 if (val == 1.0)
00205 return rhs->simplify();
00206
00207 return new rt_binary_expr<InterfaceType>(new rt_constant<NumericT, InterfaceType>(val),
00208 new op_binary<op_mult<NumericT>, InterfaceType>(),
00209 rhs->simplify());
00210 }
00211 else if (rhs->is_constant())
00212 {
00213 NumericT val = rhs->unwrap();
00214 if (val == 0.0)
00215 return new rt_constant<NumericT, InterfaceType>(0.0);
00216 if (val == 1.0)
00217 return lhs->simplify();
00218
00219 return new rt_binary_expr<InterfaceType>(lhs->simplify(),
00220 new op_binary<op_mult<NumericT>, InterfaceType>(),
00221 new rt_constant<NumericT, InterfaceType>(val));
00222 }
00223
00224 rt_vector_expr<InterfaceType> const * lhs_vec = dynamic_cast<rt_vector_expr<InterfaceType> const *>(lhs);
00225 rt_vector_expr<InterfaceType> const * rhs_vec = dynamic_cast<rt_vector_expr<InterfaceType> const *>(rhs);
00226
00227 if (lhs_vec != NULL && rhs_vec != NULL)
00228 return (*lhs_vec * *rhs_vec).get()->clone();
00229
00230 return new rt_binary_expr<InterfaceType>(lhs->simplify(),
00231 new op_binary<op_mult<NumericT>, InterfaceType>(),
00232 rhs->simplify());
00233 }
00234
00236 template <typename InterfaceType, typename NumericT>
00237 bool can_simplify_impl(const InterfaceType * lhs, op_mult<NumericT>, const InterfaceType * rhs)
00238 {
00239 if (lhs->is_constant())
00240 {
00241 NumericT val = lhs->unwrap();
00242 if (val == 0.0)
00243 {
00244
00245 return true;
00246 }
00247 if (val == 1.0)
00248 {
00249
00250 return true;
00251 }
00252 }
00253 if (rhs->is_constant())
00254 {
00255 NumericT val = rhs->unwrap();
00256 if (val == 0.0)
00257 {
00258
00259 return true;
00260 }
00261 if (val == 1.0)
00262 {
00263
00264 return true;
00265 }
00266 }
00267
00268 rt_vector_expr<InterfaceType> const * lhs_vec = dynamic_cast<rt_vector_expr<InterfaceType> const *>(lhs);
00269 rt_vector_expr<InterfaceType> const * rhs_vec = dynamic_cast<rt_vector_expr<InterfaceType> const *>(rhs);
00270
00271 if (lhs_vec != NULL && rhs_vec != NULL)
00272 return true;
00273
00274 return lhs->can_simplify() || rhs->can_simplify();
00275 }
00276
00277
00278
00279
00280
00281
00282
00284 template <typename InterfaceType, typename NumericT>
00285 InterfaceType * diff_impl(const InterfaceType * lhs, op_div<NumericT>, const InterfaceType * rhs, const InterfaceType * diff_var)
00286 {
00287 return new rt_binary_expr<InterfaceType>( new rt_binary_expr<InterfaceType>( new rt_binary_expr<InterfaceType>(lhs->diff(diff_var),
00288 new op_binary<op_mult<NumericT>, InterfaceType>(),
00289 rhs->clone()),
00290 new op_binary<op_minus<NumericT>, InterfaceType>(),
00291 new rt_binary_expr<InterfaceType>(lhs->clone(),
00292 new op_binary<op_mult<NumericT>, InterfaceType>(),
00293 rhs->diff(diff_var))
00294 ),
00295 new op_binary<op_div<NumericT>, InterfaceType>(),
00296 new rt_binary_expr<InterfaceType>(rhs->clone(),
00297 new op_binary<op_mult<NumericT>, InterfaceType>(),
00298 rhs->clone())
00299 );
00300 }
00301
00303 template <typename InterfaceType, typename NumericT>
00304 InterfaceType * simplify_impl(const InterfaceType * lhs, op_div<NumericT>, const InterfaceType * rhs)
00305 {
00306 if (lhs->is_constant())
00307 {
00308 NumericT val = lhs->unwrap();
00309 if (val == 0.0)
00310 return new rt_constant<NumericT, InterfaceType>(0.0);
00311
00312 return new rt_binary_expr<InterfaceType>(new rt_constant<NumericT, InterfaceType>(val),
00313 new op_binary<op_div<NumericT>, InterfaceType>(),
00314 rhs->simplify());
00315 }
00316 else if (rhs->is_constant())
00317 {
00318 NumericT val = rhs->unwrap();
00319 if (val == 1.0)
00320 return lhs->simplify();
00321
00322 return new rt_binary_expr<InterfaceType>(lhs->simplify(),
00323 new op_binary<op_div<NumericT>, InterfaceType>(),
00324 new rt_constant<NumericT, InterfaceType>(val));
00325 }
00326
00327 return new rt_binary_expr<InterfaceType>(lhs->simplify(),
00328 new op_binary<op_div<NumericT>, InterfaceType>(),
00329 rhs->simplify());
00330 }
00331
00333 template <typename InterfaceType, typename NumericT>
00334 bool can_simplify_impl(const InterfaceType * lhs, op_div<NumericT>, const InterfaceType * rhs)
00335 {
00336 if (lhs->is_constant())
00337 {
00338 if (lhs->unwrap() == 0.0)
00339 {
00340
00341 return true;
00342 }
00343 }
00344 if (rhs->is_constant())
00345 {
00346 if (rhs->unwrap() == 1.0)
00347 {
00348
00349 return true;
00350 }
00351 }
00352 return lhs->can_simplify() || rhs->can_simplify();
00353 }
00354
00355
00356
00357 }
00358
00359 #endif