• Main Page
  • Namespaces
  • Data Structures
  • Files
  • File List

/export/development/ViennaMath/viennamath/manipulation/simplify.hpp

Go to the documentation of this file.
00001 #ifndef VIENNAMATH_MANIPULATION_SIMPLIFY_HPP
00002 #define VIENNAMATH_MANIPULATION_SIMPLIFY_HPP
00003 
00004 /* =======================================================================
00005    Copyright (c) 2012, Institute for Microelectronics,
00006                        Institute for Analysis and Scientific Computing,
00007                        TU Wien.
00008                              -----------------
00009                ViennaMath - Symbolic and Numerical Math in C++
00010                              -----------------
00011 
00012    Author:     Karl Rupp                          rupp@iue.tuwien.ac.at
00013 
00014    License:    MIT (X11), see file LICENSE in the ViennaMath base directory
00015 ======================================================================= */
00016 
00017 
00018 
00019 
00020 #include "viennamath/forwards.h"
00021 #include "viennamath/runtime/functor_wrapper.hpp"
00022 #include <assert.h>
00023 
00028 namespace viennamath
00029 {
00030   
00031   //
00032   //   Section 1: Compile time optimization
00033   //
00034   
00035   namespace result_of
00036   {
00037     
00038     
00039     namespace detail
00040     {
00041     
00042       // general handling:
00043       template <typename ExpressionType>
00044       struct simplify_impl
00045       {
00046         //default: no optimization available, thus don't manipulate anything
00047         enum { value = 0 };
00048         typedef ExpressionType        type;
00049       };
00050       
00051       template <typename LHS, typename OP, typename RHS>
00052       struct simplify_impl< ct_binary_expr<LHS, OP, RHS> >
00053       {
00054         //default: no optimization available, thus don't manipulate anything
00055         enum { value = simplify_impl<LHS>::value + simplify_impl<RHS>::value };
00056         typedef ct_binary_expr<typename simplify_impl<LHS>::type,
00057                               OP,
00058                               typename simplify_impl<RHS>::type
00059                               >        type;
00060       };
00061       
00062       
00064       
00065       // something plus 0 is something
00066       template <typename LHS, typename NumericT>
00067       struct simplify_impl < ct_binary_expr<LHS, op_plus<NumericT>, ct_constant<0> > >
00068       {
00069         enum { value = 1 };
00070         typedef LHS          type;
00071       };
00072       
00073       // 0 plus something is something
00074       template <typename NumericT, typename RHS>
00075       struct simplify_impl < ct_binary_expr<ct_constant<0>, op_plus<NumericT>, RHS> >
00076       {
00077         enum { value = 1 };
00078         typedef RHS          type;
00079       };
00080 
00081       // 0 plus 0 is 0 (resolve ambiguity)
00082       template <typename NumericT>
00083       struct simplify_impl < ct_binary_expr<ct_constant<0>, op_plus<NumericT>, ct_constant<0> > >
00084       {
00085         enum { value = 1 };
00086         typedef ct_constant<0>          type;
00087       };
00088       
00089       
00090       
00091       
00093       
00094       // something minus 0 is something
00095       template <typename LHS, typename NumericT>
00096       struct simplify_impl < ct_binary_expr<LHS, op_minus<NumericT>, ct_constant<0> > >
00097       {
00098         enum { value = 1 };
00099         typedef LHS          type;
00100       };
00101       
00102 
00103       template <typename LHS1, typename NumericT, typename RHS2>
00104       struct simplify_impl < ct_binary_expr<LHS1,
00105                                             op_plus<NumericT>,
00106                                             ct_binary_expr<ct_constant<0>,
00107                                                           op_minus<NumericT>,
00108                                                           RHS2 >
00109                                             > >
00110       {
00111         enum { value = 1 };
00112         typedef ct_binary_expr<LHS1,
00113                               op_minus<NumericT>,
00114                               RHS2>                   type;
00115       };
00116       
00117       template <typename LHS1, typename NumericT, typename RHS2>
00118       struct simplify_impl < ct_binary_expr<LHS1,
00119                                             op_minus<NumericT>,
00120                                             ct_binary_expr<ct_constant<0>,
00121                                                           op_minus<NumericT>,
00122                                                           RHS2 >
00123                                             > >
00124       {
00125         enum { value = 1 };
00126         typedef ct_binary_expr<LHS1,
00127                               op_plus<NumericT>,
00128                               RHS2>                   type;
00129       };
00130 
00131       template <typename RHS1, typename NumericT, typename RHS2>
00132       struct simplify_impl < ct_binary_expr<ct_binary_expr< ct_constant<0>,
00133                                                             op_minus<NumericT>,
00134                                                             RHS1 >,
00135                                             op_plus<NumericT>,
00136                                             RHS2
00137                                             > >
00138       {
00139         enum { value = 1 };
00140         typedef ct_binary_expr<RHS2,
00141                               op_minus<NumericT>,
00142                               RHS1>                   type;
00143       };
00144       
00145       template <typename RHS1, typename NumericT, typename RHS2>
00146       struct simplify_impl < ct_binary_expr<ct_binary_expr< ct_constant<0>,
00147                                                             op_minus<NumericT>,
00148                                                             RHS1 >,
00149                                             op_minus<NumericT>,
00150                                             RHS2
00151                                             > >
00152       {
00153         enum { value = 1 };
00154         typedef ct_binary_expr< ct_constant<-1>,
00155                                 op_mult<NumericT>,
00156                                 ct_binary_expr<RHS1,
00157                                               op_plus<NumericT>,
00158                                               RHS2>
00159                               >                 type;
00160       };
00161       
00162       // resolve ambituity for plus:
00163       template <typename RHS1, typename NumericT, typename RHS2>
00164       struct simplify_impl < ct_binary_expr<ct_binary_expr< ct_constant<0>,
00165                                                             op_minus<NumericT>,
00166                                                             RHS1 >,
00167                                             op_plus<NumericT>,
00168                                             ct_binary_expr< ct_constant<0>,
00169                                                             op_minus<NumericT>,
00170                                                             RHS2 >                                          
00171                                             > >
00172       {
00173         enum { value = 1 };
00174         typedef ct_binary_expr< ct_constant<-1>,
00175                                 op_mult<NumericT>,
00176                                 ct_binary_expr<RHS1,
00177                                               op_plus<NumericT>,
00178                                               RHS2>
00179                               >                 type;
00180       };
00181 
00182       // resolve ambituity for minus:
00183       template <typename RHS1, typename NumericT, typename RHS2>
00184       struct simplify_impl < ct_binary_expr<ct_binary_expr< ct_constant<0>,
00185                                                             op_minus<NumericT>,
00186                                                             RHS1 >,
00187                                             op_minus<NumericT>,
00188                                             ct_binary_expr< ct_constant<0>,
00189                                                             op_minus<NumericT>,
00190                                                             RHS2 >                                          
00191                                             > >
00192       {
00193         enum { value = 1 };
00194         typedef ct_binary_expr<RHS2,
00195                               op_minus<NumericT>,
00196                               RHS1>                   type;
00197       };
00198       
00199       
00200       
00202       
00203       // something times 0 is 0
00204       template <typename LHS, typename NumericT>
00205       struct simplify_impl < ct_binary_expr<LHS, op_mult<NumericT>, ct_constant<0> > >
00206       {
00207         enum { value = 1 };
00208         typedef ct_constant<0>          type;
00209       };
00210       
00211       // 0 times something is 0
00212       template <typename NumericT, typename RHS>
00213       struct simplify_impl < ct_binary_expr<ct_constant<0>, op_mult<NumericT>, RHS> >
00214       {
00215         enum { value = 1 };
00216         typedef ct_constant<0>          type;
00217       };
00218 
00219       // 0 times 0 is 0 (resolve ambiguity)
00220       template <typename NumericT>
00221       struct simplify_impl < ct_binary_expr<ct_constant<0>, op_mult<NumericT>, ct_constant<0> > >
00222       {
00223         enum { value = 1 };
00224         typedef ct_constant<0>          type;
00225       };
00226       
00227       
00229       
00230       // something times 1 is something
00231       template <typename LHS, typename NumericT>
00232       struct simplify_impl < ct_binary_expr<LHS, op_mult<NumericT>, ct_constant<1> > >
00233       {
00234         enum { value = 1 };
00235         typedef LHS          type;
00236       };
00237       
00238       // 1 times something is something
00239       template <typename NumericT, typename RHS>
00240       struct simplify_impl < ct_binary_expr<ct_constant<1>, op_mult<NumericT>, RHS> >
00241       {
00242         enum { value = 1 };
00243         typedef RHS          type;
00244       };
00245       
00246       // 1 times 1 is 1 (resolve ambiguity)
00247       template <typename NumericT>
00248       struct simplify_impl < ct_binary_expr<ct_constant<1>, op_mult<NumericT>, ct_constant<1> > >
00249       {
00250         enum { value = 1 };
00251         typedef ct_constant<1>          type;
00252       };
00253       
00254       // resolve amgibuity for 0 * 1:
00255       template <typename NumericT>
00256       struct simplify_impl < ct_binary_expr<ct_constant<1>, op_mult<NumericT>, ct_constant<0> > >
00257       {
00258         enum { value = 1 };
00259         typedef ct_constant<0>          type;
00260       };
00261 
00262       template <typename NumericT>
00263       struct simplify_impl < ct_binary_expr<ct_constant<0>, op_mult<NumericT>, ct_constant<1> > >
00264       {
00265         enum { value = 1 };
00266         typedef ct_constant<0>          type;
00267       };
00268       
00269       
00271       
00272       // 0 divided by something is 0
00273       template <typename NumericT, typename RHS>
00274       struct simplify_impl < ct_binary_expr<ct_constant<0>, op_div<NumericT>, RHS> >
00275       {
00276         enum { value = 1 };
00277         typedef ct_constant<0>          type;
00278       };
00279 
00280       // something divided by 0 is a compile time error :-)
00281       template <typename LHS, typename NumericT>
00282       struct simplify_impl < ct_binary_expr<LHS, op_div<NumericT>, ct_constant<0> > >
00283       {
00284         enum { value = 1 };
00285         typedef typename ct_binary_expr<LHS, op_div<NumericT>, ct_constant<0> >::ERROR_ENCOUNTERED_DIVISION_BY_ZERO          type;
00286       };
00287       
00288       
00289       // 0 divided by 0 is a compile time error :-)
00290       template <typename NumericT>
00291       struct simplify_impl < ct_binary_expr<ct_constant<0>, op_div<NumericT>, ct_constant<0> > >
00292       {
00293         enum { value = 1 };
00294         typedef typename ct_binary_expr<ct_constant<0>, op_div<NumericT>, ct_constant<0> >::ERROR_ENCOUNTERED_DIVISION_BY_ZERO          type;
00295       };
00296       
00297       
00299       
00300       // something divided by 1 is 1
00301       template <typename LHS, typename NumericT>
00302       struct simplify_impl < ct_binary_expr<LHS, op_div<NumericT>, ct_constant<1> > >
00303       {
00304         enum { value = 1 };
00305         typedef LHS          type;
00306       };
00307       
00309       
00310       template <typename LHS, typename NumericT, typename RHS>
00311       struct simplify_impl < ct_binary_expr<LHS,
00312                                             op_mult<NumericT>,
00313                                             ct_binary_expr<ct_constant<1>, op_div<NumericT>, RHS>
00314                                           > >
00315       {
00316         enum { value = 1 };
00317         typedef ct_binary_expr<LHS,
00318                               op_div<NumericT>,
00319                               RHS>                             type;
00320       };
00321 
00322       template <typename RHS1, typename NumericT, typename RHS2>
00323       struct simplify_impl < ct_binary_expr<ct_binary_expr<ct_constant<1>, op_div<NumericT>, RHS1>,
00324                                             op_mult<NumericT>,
00325                                             RHS2
00326                                           > >
00327       {
00328         enum { value = 1 };
00329         typedef ct_binary_expr<RHS2,
00330                               op_div<NumericT>,
00331                               RHS1>                             type;
00332       };
00333 
00334       //resolve ambiguity in above two cases:
00335       template <typename RHS1, typename NumericT, typename RHS2>
00336       struct simplify_impl < ct_binary_expr<ct_binary_expr<ct_constant<1>, op_div<NumericT>, RHS1>,
00337                                             op_mult<NumericT>,
00338                                             ct_binary_expr<ct_constant<1>, op_div<NumericT>, RHS2>
00339                                           > >
00340       {
00341         enum { value = 1 };
00342         typedef ct_binary_expr<ct_constant<1>,
00343                               op_div<NumericT>,
00344                               ct_binary_expr<RHS1, op_mult<NumericT>, RHS2> 
00345                               >                             type;
00346       };
00347       
00348       
00349       
00351       
00353       
00354       // A + B:
00355       template <long numerator_1, long denominator_1, typename NumericT,
00356                 long numerator_2, long denominator_2>
00357       struct simplify_impl< ct_binary_expr<ct_binary_expr<ct_constant<numerator_1>,
00358                                                           op_div<NumericT>,
00359                                                           ct_constant<denominator_1> >,
00360                                           op_plus<NumericT>,
00361                                           ct_binary_expr<ct_constant<numerator_2>,
00362                                                           op_div<NumericT>,
00363                                                           ct_constant<denominator_2> >
00364                                           >
00365                           >
00366       {
00367         enum { value = 1,
00368               numerator = numerator_1 * denominator_2 + numerator_2 * denominator_1,
00369               denominator = denominator_1 * denominator_2 };
00370         
00371         
00372         typedef ct_binary_expr< ct_constant< numerator / result_of::gcd<numerator, denominator>::value >,
00373                                 op_div<NumericT>,
00374                                 ct_constant<denominator / result_of::gcd<numerator, denominator>::value > >        type;
00375       };
00376 
00377       template <long value_1, typename NumericT,
00378                 long numerator_2, long denominator_2>
00379       struct simplify_impl< ct_binary_expr<ct_constant<value_1>,
00380                                           op_plus<NumericT>,
00381                                           ct_binary_expr<ct_constant<numerator_2>,
00382                                                           op_div<NumericT>,
00383                                                           ct_constant<denominator_2> >
00384                                           >
00385                           >
00386       {
00387         enum { value = 1,
00388               numerator = value_1 * denominator_2 + numerator_2,
00389               denominator = denominator_2 };
00390               
00391         typedef ct_binary_expr< ct_constant< numerator / result_of::gcd<numerator, denominator>::value >,
00392                                 op_div<NumericT>,
00393                                 ct_constant<denominator / result_of::gcd<numerator, denominator>::value > >        type;
00394       };
00395 
00396       template <long numerator_1, long denominator_1, typename NumericT,
00397                 long value_2>
00398       struct simplify_impl< ct_binary_expr<ct_binary_expr<ct_constant<numerator_1>,
00399                                                           op_div<NumericT>,
00400                                                           ct_constant<denominator_1> >,
00401                                           op_plus<NumericT>,
00402                                           ct_constant<value_2>
00403                                           >
00404                           >
00405       {
00406         enum { value = 1,
00407               numerator = numerator_1 + value_2 * denominator_1,
00408               denominator = denominator_1 };
00409               
00410         typedef ct_binary_expr< ct_constant< numerator / result_of::gcd<numerator, denominator>::value >,
00411                                 op_div<NumericT>,
00412                                 ct_constant<denominator / result_of::gcd<numerator, denominator>::value > >        type;
00413       };
00414       
00415       
00416       
00417       // A - B:
00418       template <long numerator_1, long denominator_1, typename NumericT,
00419                 long numerator_2, long denominator_2>
00420       struct simplify_impl< ct_binary_expr<ct_binary_expr<ct_constant<numerator_1>,
00421                                                           op_div<NumericT>,
00422                                                           ct_constant<denominator_1> >,
00423                                           op_minus<NumericT>,
00424                                           ct_binary_expr<ct_constant<numerator_2>,
00425                                                           op_div<NumericT>,
00426                                                           ct_constant<denominator_2> >
00427                                           > >
00428       {
00429         enum { value = 1,
00430               numerator = numerator_1 * denominator_2 - numerator_2 * denominator_1,
00431               denominator = denominator_1 * denominator_2 };
00432               
00433         typedef ct_binary_expr< ct_constant< numerator / result_of::gcd<numerator, denominator>::value >,
00434                                 op_div<NumericT>,
00435                                 ct_constant<denominator / result_of::gcd<numerator, denominator>::value > >        type;
00436       };
00437       
00438       template <long value_1, typename NumericT,
00439                 long numerator_2, long denominator_2>
00440       struct simplify_impl< ct_binary_expr<ct_constant<value_1>,
00441                                           op_minus<NumericT>,
00442                                           ct_binary_expr<ct_constant<numerator_2>,
00443                                                           op_div<NumericT>,
00444                                                           ct_constant<denominator_2> >
00445                                           > >
00446       {
00447         enum { value = 1,
00448               numerator = value_1 * denominator_2 - numerator_2,
00449               denominator = denominator_2 };
00450               
00451         typedef ct_binary_expr< ct_constant< numerator / result_of::gcd<numerator, denominator>::value >,
00452                                 op_div<NumericT>,
00453                                 ct_constant<denominator / result_of::gcd<numerator, denominator>::value > >        type;
00454       };
00455 
00456       template <long numerator_1, long denominator_1, typename NumericT,
00457                 long value_2>
00458       struct simplify_impl< ct_binary_expr<ct_binary_expr<ct_constant<numerator_1>,
00459                                                           op_div<NumericT>,
00460                                                           ct_constant<denominator_1> >,
00461                                           op_minus<NumericT>,
00462                                           ct_constant<value_2>
00463                                           > >
00464       {
00465         enum { value = 1,
00466               numerator = numerator_1 - value_2 * denominator_1,
00467               denominator = denominator_1 };
00468               
00469         typedef ct_binary_expr< ct_constant< numerator / result_of::gcd<numerator, denominator>::value >,
00470                                 op_div<NumericT>,
00471                                 ct_constant<denominator / result_of::gcd<numerator, denominator>::value > >        type;
00472       };
00473       
00474       // resolve ambiguity with elimination of zero
00475       template <long numerator_1, long denominator_1, typename NumericT>
00476       struct simplify_impl< ct_binary_expr<ct_binary_expr<ct_constant<numerator_1>,
00477                                                           op_div<NumericT>,
00478                                                           ct_constant<denominator_1> >,
00479                                           op_minus<NumericT>,
00480                                           ct_constant<0>
00481                                           > >
00482       {
00483         enum { value = 1,
00484               numerator = numerator_1,
00485               denominator = denominator_1 };
00486               
00487         typedef ct_binary_expr< ct_constant< numerator / result_of::gcd<numerator, denominator>::value >,
00488                                 op_div<NumericT>,
00489                                 ct_constant<denominator / result_of::gcd<numerator, denominator>::value > >        type;
00490       };
00491       
00492       
00493       // A * B:
00494       template <long numerator_1, long denominator_1, typename NumericT,
00495                 long numerator_2, long denominator_2>
00496       struct simplify_impl< ct_binary_expr<ct_binary_expr<ct_constant<numerator_1>,
00497                                                           op_div<NumericT>,
00498                                                           ct_constant<denominator_1> >,
00499                                           op_mult<NumericT>,
00500                                           ct_binary_expr<ct_constant<numerator_2>,
00501                                                           op_div<NumericT>,
00502                                                           ct_constant<denominator_2> >
00503                                           >  >
00504       {
00505         enum { value = 1,
00506               numerator = numerator_1 * numerator_2,
00507               denominator = denominator_1 * denominator_2 };
00508               
00509         typedef ct_binary_expr< ct_constant< numerator / result_of::gcd<numerator, denominator>::value >,
00510                                 op_div<NumericT>,
00511                                 ct_constant<denominator / result_of::gcd<numerator, denominator>::value > >        type;
00512       };
00513       
00514       template <long value_1, typename NumericT,
00515                 long numerator_2, long denominator_2>
00516       struct simplify_impl< ct_binary_expr<ct_constant<value_1>,
00517                                           op_mult<NumericT>,
00518                                           ct_binary_expr<ct_constant<numerator_2>,
00519                                                           op_div<NumericT>,
00520                                                           ct_constant<denominator_2> >
00521                                           > >
00522       {
00523         enum { value = 1,
00524               numerator = value_1 * numerator_2,
00525               denominator = denominator_2 };
00526               
00527         typedef ct_binary_expr< ct_constant< numerator / result_of::gcd<numerator, denominator>::value >,
00528                                 op_div<NumericT>,
00529                                 ct_constant<denominator / result_of::gcd<numerator, denominator>::value > >        type;
00530       };
00531 
00532       template <long numerator_1, long denominator_1, typename NumericT,
00533                 long value_2>
00534       struct simplify_impl< ct_binary_expr<ct_binary_expr<ct_constant<numerator_1>,
00535                                                           op_div<NumericT>,
00536                                                           ct_constant<denominator_1> >,
00537                                           op_mult<NumericT>,
00538                                           ct_constant<value_2>
00539                                           >  >
00540       {
00541         enum { value = 1,
00542               numerator = numerator_1 * value_2,
00543               denominator = denominator_1 };
00544               
00545         typedef ct_binary_expr< ct_constant< numerator / result_of::gcd<numerator, denominator>::value >,
00546                                 op_div<NumericT>,
00547                                 ct_constant<denominator / result_of::gcd<numerator, denominator>::value > >        type;
00548       };
00549       
00550       // A / B:
00551       template <long numerator_1, long denominator_1, typename NumericT,
00552                 long numerator_2, long denominator_2>
00553       struct simplify_impl< ct_binary_expr<ct_binary_expr<ct_constant<numerator_1>,
00554                                                           op_div<NumericT>,
00555                                                           ct_constant<denominator_1> >,
00556                                           op_div<NumericT>,
00557                                           ct_binary_expr<ct_constant<numerator_2>,
00558                                                           op_div<NumericT>,
00559                                                           ct_constant<denominator_2> >
00560                                           >  >
00561       {
00562         enum { value = 1,
00563               numerator = numerator_1 * denominator_2,
00564               denominator = denominator_1 * numerator_2 };
00565               
00566         typedef ct_binary_expr< ct_constant< numerator / result_of::gcd<numerator, denominator>::value >,
00567                                 op_div<NumericT>,
00568                                 ct_constant<denominator / result_of::gcd<numerator, denominator>::value > >        type;
00569       };
00570       
00571       template <long value_1, typename NumericT,
00572                 long numerator_2, long denominator_2>
00573       struct simplify_impl< ct_binary_expr<ct_constant<value_1>,
00574                                           op_div<NumericT>,
00575                                           ct_binary_expr<ct_constant<numerator_2>,
00576                                                           op_div<NumericT>,
00577                                                           ct_constant<denominator_2> >
00578                                           >  >
00579       {
00580         enum { value = 1,
00581               numerator = value_1 * denominator_2,
00582               denominator = numerator_2 };
00583               
00584         typedef ct_binary_expr< ct_constant< numerator / result_of::gcd<numerator, denominator>::value >,
00585                                 op_div<NumericT>,
00586                                 ct_constant<denominator / result_of::gcd<numerator, denominator>::value > >        type;
00587       };
00588 
00589       template <long numerator_1, typename NumericT, long denominator_1,
00590                 long value_2>
00591       struct simplify_impl< ct_binary_expr<ct_binary_expr<ct_constant<numerator_1>,
00592                                                           op_div<NumericT>,
00593                                                           ct_constant<denominator_1> >,
00594                                           op_div<NumericT>,
00595                                           ct_constant<value_2>
00596                                           >  >
00597       {
00598         enum { value = 1,
00599               numerator = numerator_1,
00600               denominator = denominator_1 * value_2 };
00601               
00602         typedef ct_binary_expr< ct_constant< numerator / result_of::gcd<numerator, denominator>::value >,
00603                                 op_div<NumericT>,
00604                                 ct_constant<denominator / result_of::gcd<numerator, denominator>::value > >        type;
00605       };
00606       
00607       //primitive expressions
00608       template <long value_1, typename NumericT, long value_2>
00609       struct simplify_impl< ct_binary_expr<ct_constant<value_1>,
00610                                           op_plus<NumericT>,
00611                                           ct_constant<value_2>
00612                                           >  >
00613       {
00614         enum { value = 1 };
00615         typedef ct_constant<value_1 + value_2>   type;
00616       };
00617 
00618       template <long value_1, typename NumericT>
00619       struct simplify_impl< ct_binary_expr<ct_constant<value_1>,
00620                                           op_plus<NumericT>,
00621                                           ct_constant<0>
00622                                           >  >
00623       {
00624         enum { value = 1 };
00625         typedef ct_constant<value_1>   type;
00626       };
00627 
00628       template <typename NumericT, long value_2>
00629       struct simplify_impl< ct_binary_expr<ct_constant<0>,
00630                                           op_plus<NumericT>,
00631                                           ct_constant<value_2>
00632                                           >  >
00633       {
00634         enum { value = 1 };
00635         typedef ct_constant<value_2>   type;
00636       };
00637       
00638       template <long value_1, typename NumericT, long value_2>
00639       struct simplify_impl< ct_binary_expr<ct_constant<value_1>,
00640                                           op_minus<NumericT>,
00641                                           ct_constant<value_2>
00642                                           >  >
00643       {
00644         enum { value = 1 };
00645         typedef ct_constant<value_1 - value_2>   type;
00646       };
00647 
00648       //resolve ambiguity:
00649       template <typename NumericT>
00650       struct simplify_impl< ct_binary_expr<ct_constant<1>,
00651                                           op_minus<NumericT>,
00652                                           ct_constant<0>
00653                                           >  >
00654       {
00655         enum { value = 1 };
00656         typedef ct_constant<1>   type;
00657       };
00658 
00659       template <typename NumericT>
00660       struct simplify_impl< ct_binary_expr<ct_constant<-1>,
00661                                           op_minus<NumericT>,
00662                                           ct_constant<0>
00663                                           >  >
00664       {
00665         enum { value = 1 };
00666         typedef ct_constant<-1>   type;
00667       };
00668       
00669       
00671       
00672       template <long value_1, typename NumericT, long value_2>
00673       struct simplify_impl< ct_binary_expr<ct_constant<value_1>,
00674                                           op_mult<NumericT>,
00675                                           ct_constant<value_2>
00676                                           > >
00677       {
00678         enum { value = 1 };
00679         typedef ct_constant<value_1 * value_2>   type;
00680       };
00681 
00682       //resolve ambiguity
00683       template <typename NumericT, long value_2>
00684       struct simplify_impl< ct_binary_expr<ct_constant<1>,
00685                                           op_mult<NumericT>,
00686                                           ct_constant<value_2>
00687                                           > >
00688       {
00689         enum { value = 1 };
00690         typedef ct_constant<value_2>   type;
00691       };
00692 
00693       template <long value_1, typename NumericT>
00694       struct simplify_impl< ct_binary_expr<ct_constant<value_1>,
00695                                           op_mult<NumericT>,
00696                                           ct_constant<1>
00697                                           > >
00698       {
00699         enum { value = 1 };
00700         typedef ct_constant<value_1>   type;
00701       };
00702       
00703       template <long value_1, typename NumericT>
00704       struct simplify_impl< ct_binary_expr<ct_constant<value_1>,
00705                                           op_mult<NumericT>,
00706                                           ct_constant<0>
00707                                           > >
00708       {
00709         enum { value = 1 };
00710         typedef ct_constant<0>   type;
00711       };
00712       
00713       template <typename NumericT, long value_2>
00714       struct simplify_impl< ct_binary_expr<ct_constant<0>,
00715                                           op_mult<NumericT>,
00716                                           ct_constant<value_2>
00717                                           > >
00718       {
00719         enum { value = 1 };
00720         typedef ct_constant<0>   type;
00721       };  
00722         
00723       
00724       // a / b
00725       
00726       
00727       template <long value_1, typename NumericT, long value_2>
00728       struct simplify_impl< ct_binary_expr<ct_constant<value_1>,
00729                                           op_div<NumericT>,
00730                                           ct_constant<value_2>
00731                                           > >
00732       {
00733         enum { value = 0 };  //Note: this is not a change that needs to trigger an optimization, thus keep it at 0.
00734         typedef ct_binary_expr<ct_constant<value_1 / result_of::gcd<value_1, value_2>::value >,
00735                               op_div<NumericT>,
00736                               ct_constant<value_2 / result_of::gcd<value_1, value_2>::value >
00737                               >                  type;
00738       };
00739 
00740       template <typename NumericT, long value_2>
00741       struct simplify_impl< ct_binary_expr<ct_constant<0>,
00742                                           op_div<NumericT>,
00743                                           ct_constant<value_2>
00744                                           > >
00745       {
00746         enum { value = 1 };
00747         typedef ct_constant<0>                   type;
00748       };
00749 
00750       template <typename NumericT>
00751       struct simplify_impl< ct_binary_expr<ct_constant<0>,
00752                                           op_div<NumericT>,
00753                                           ct_constant<1>
00754                                           > >
00755       {
00756         enum { value = 1 };
00757         typedef ct_constant<0>                   type;
00758       };
00759 
00760       template <long value_1, typename NumericT>
00761       struct simplify_impl< ct_binary_expr<ct_constant<value_1>,
00762                                           op_div<NumericT>,
00763                                           ct_constant<1>
00764                                           > >
00765       {
00766         enum { value = 1 };
00767         typedef ct_constant<value_1>            type;
00768       };
00769       
00770       
00771       template <long value_1, typename NumericT>
00772       struct simplify_impl< ct_binary_expr<ct_constant<value_1>,
00773                                           op_div<NumericT>,
00774                                           ct_constant<-1>
00775                                           > >
00776       {
00777         enum { value = 1 };
00778         typedef ct_constant<-value_1>            type;
00779       };
00780       
00781       
00782     } //namespace detail      
00783     
00785     
00786     //
00787     // interfacing metafunction: loops over simplification routines until no more optimization is possible
00788     //
00796     template <typename ExpressionType,
00797               bool optimization_possible = (detail::simplify_impl<ExpressionType>::value != 0)
00798              >
00799     struct simplify {}; //provides SFINAE for the compile time interface function simplify()
00800     
00801     // binary expression
00803     template <typename LHS, typename OP, typename RHS>
00804     struct simplify < ct_binary_expr<LHS, OP, RHS>, true >
00805     {
00806       typedef typename detail::simplify_impl< ct_binary_expr<LHS, OP, RHS> >::type    simplified_type;
00807       typedef typename simplify<simplified_type>::type       type;
00808       //typedef simplifyd_type          type;
00809     };
00810 
00812     template <typename LHS, typename OP, typename RHS>
00813     struct simplify < ct_binary_expr<LHS, OP, RHS>, false >
00814     {
00815       typedef ct_binary_expr<LHS, OP, RHS>          type;
00816     };
00817 
00818     // unary expression
00820     template <typename LHS, typename OP>
00821     struct simplify < ct_unary_expr<LHS, OP>, true >
00822     {
00823       typedef typename detail::simplify_impl< ct_unary_expr<LHS, OP> >::type    simplified_type;
00824       typedef typename simplify<simplified_type>::type       type;
00825     };
00826 
00828     template <typename LHS, typename OP>
00829     struct simplify < ct_unary_expr<LHS, OP>, false >
00830     {
00831       typedef ct_unary_expr<LHS, OP>       type;
00832     };
00833 
00834     // constant
00836     template <long value>
00837     struct simplify < ct_constant<value>, true >
00838     {
00839       typedef typename detail::simplify_impl< ct_constant<value> >::type    simplified_type;
00840       typedef typename simplify<simplified_type>::type       type;
00841     };
00842 
00844     template <long value>
00845     struct simplify < ct_constant<value>, false >
00846     {
00847       typedef ct_constant<value>       type;
00848     };
00849 
00850     // function symbol
00852     template <typename TAG>
00853     struct simplify < ct_function_symbol<TAG>, true >
00854     {
00855       typedef typename detail::simplify_impl< ct_function_symbol<TAG> >::type    simplified_type;
00856       typedef typename simplify<simplified_type>::type       type;
00857     };
00858 
00860     template <typename TAG>
00861     struct simplify < ct_function_symbol<TAG>, false >
00862     {
00863       typedef ct_function_symbol<TAG>       type;
00864     };
00865 
00866     // variable
00868     template <id_type id>
00869     struct simplify < ct_variable<id>, true >
00870     {
00871       typedef typename detail::simplify_impl< ct_variable<id> >::type    simplified_type;
00872       typedef typename simplify<simplified_type>::type       type;
00873     };
00874     
00876     template <id_type id>
00877     struct simplify < ct_variable<id>, false >
00878     {
00879       typedef ct_variable<id>       type;
00880     };
00881     
00882   } //namespace result_of
00883   
00884   
00886   template <typename ExpressionType>
00887   typename result_of::simplify<ExpressionType>::type
00888   simplify(ExpressionType const & e)
00889   {
00890     return typename result_of::simplify<ExpressionType>::type();
00891   } 
00892   
00893 
00894 
00895 
00896 
00897   //
00898   //   Section 2: Run time simplification
00899   //
00900   
00901   
00902   
00903   //public interface:
00905   template <typename InterfaceType>
00906   void inplace_simplify(rt_expr<InterfaceType> & e)
00907   {
00908     while (e.get()->can_simplify())
00909       e = e.get()->simplify();
00910   }
00911 
00913   template <typename InterfaceType>
00914   void inplace_simplify(rt_unary_expr<InterfaceType> & e)
00915   {
00916     while (e->can_simplify())
00917       e = e->simplify();
00918   }
00919 
00921   template <typename InterfaceType>
00922   void inplace_simplify(rt_binary_expr<InterfaceType> & e)
00923   {
00924     while (e->can_simplify())
00925       e = e->simplify();
00926   }
00927 
00929   template <typename T>
00930   void inplace_simplify(T & e)
00931   {
00932     //do nothing, since primitive types cannot be simplified
00933   }
00934   
00935   
00936 
00938   template <typename InterfaceType>
00939   rt_expr<InterfaceType> simplify(rt_expr<InterfaceType> const & e)
00940   {
00941     rt_expr<InterfaceType> ret(e);
00942     inplace_simplify(ret);
00943     return ret;
00944   }
00945 
00947   template <typename InterfaceType>
00948   rt_expr<InterfaceType> simplify(rt_unary_expr<InterfaceType> const & e)
00949   {
00950     rt_expr<InterfaceType> ret(e);
00951     inplace_simplify(ret);
00952     return ret;
00953   }
00954 
00956   template <typename InterfaceType>
00957   rt_expr<InterfaceType> simplify(rt_binary_expr<InterfaceType> const & e)
00958   {
00959     rt_expr<InterfaceType> ret(e);
00960     inplace_simplify(ret);
00961     return ret;
00962   }
00963 
00965   template <typename T>
00966   T simplify(T const & e)
00967   {
00968     //do nothing, since primitive types cannot be simplified
00969     return e;
00970   }
00971 
00972 }
00973 
00974 #endif

Generated on Wed Feb 29 2012 21:50:43 for ViennaMath by  doxygen 1.7.1