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

/export/development/ViennaMath/viennamath/runtime/unary_expr.hpp

Go to the documentation of this file.
00001 #ifndef VIENNAMATH_RUNTIME_UNARY_EXPRESSION_HPP
00002 #define VIENNAMATH_RUNTIME_UNARY_EXPRESSION_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 <iostream>
00021 #include <ostream>
00022 #include <sstream>
00023 #include <memory>
00024 #include "viennamath/forwards.h"
00025 #include "viennamath/compiletime/unary_op_tags.hpp"
00026 #include "viennamath/compiletime/ct_unary_expr.hpp"
00027 #include "viennamath/runtime/constant.hpp"
00028 #include "viennamath/runtime/op_interface.hpp"
00029 #include "viennamath/runtime/expression_interface.hpp"
00030 
00035 namespace viennamath
00036 {
00037   
00038   //A run time expression
00043   template <typename InterfaceType /* see forwards.h for default argument */>
00044   class rt_unary_expr : public InterfaceType
00045   {
00046     typedef op_interface<InterfaceType>                    op_interface_type;
00047     typedef op_unary<op_id<typename InterfaceType::numeric_type>, InterfaceType>  op_unary_id_type;
00048     
00049       typedef rt_unary_expr<InterfaceType>                    self_type;
00050     
00051     public:
00052       typedef typename InterfaceType::numeric_type         numeric_type;
00053       
00054       rt_unary_expr() {}
00055 
00056       explicit rt_unary_expr(InterfaceType * lhs,
00057                           op_interface_type * op) : expr_(lhs),
00058                                                     op_(op) {}
00059                                                   
00060       explicit rt_unary_expr(InterfaceType * lhs) : expr_(lhs), 
00061                                                  op_(new op_unary_id_type()) {}
00062                     
00063       template <typename LHS, typename OP, typename RHS>
00064       explicit rt_unary_expr(ct_unary_expr<LHS, OP> const & other) : op_(new OP())
00065       {
00066         //std::cout << "Constructing from expression " << other << std::endl;
00067         expr_ = std::auto_ptr<InterfaceType>(other.lhs().clone());
00068       }
00069 
00070       explicit rt_unary_expr(rt_variable<InterfaceType> const & other) : expr_(other.clone()),
00071                                                                    op_(new op_unary_id_type())  {}
00072 
00073       template <typename T>
00074       explicit rt_unary_expr(rt_constant<T, InterfaceType> const & other) : expr_(other.clone()),
00075                                                                       op_(new op_unary_id_type()) {}
00076 
00077       template <long value>
00078       explicit rt_unary_expr(ct_constant<value> const & other) : expr_(other.clone()),
00079                                                               op_(new op_unary_id_type()) {}
00080 
00081       //Copy CTOR:
00082       rt_unary_expr(rt_unary_expr const & other) : expr_(other.expr_->clone()), 
00083                                              op_(other.op_->clone()) {};
00084 
00085       //assignments:                           
00086       template <typename LHS, typename OP>
00087       rt_unary_expr & operator=(ct_unary_expr<LHS, OP> const & other) 
00088       {
00089         expr_ = std::auto_ptr<InterfaceType>(other.lhs().clone());
00090         op_ = std::auto_ptr<op_interface_type>(new OP());
00091         return *this;
00092       }
00093 
00094       rt_unary_expr & operator=(rt_unary_expr const & other) 
00095       {
00096         expr_ = std::auto_ptr<InterfaceType>(other.lhs_->clone());
00097         op_  = std::auto_ptr<op_interface_type>(other.op_->clone());
00098         return *this;
00099       }
00100 
00101       template <typename ScalarType>
00102       rt_unary_expr & operator=(rt_constant<ScalarType> const & other)
00103       {
00104         expr_ = std::auto_ptr<InterfaceType>(other.clone());
00105         op_  = std::auto_ptr<op_interface_type>(new op_unary_id_type());
00106         return *this;
00107       }
00108 
00109       template <long value>
00110       rt_unary_expr & operator=(ct_constant<value> const & other)
00111       {
00112         return *this = value;
00113       }
00114 
00115       rt_unary_expr & operator=(numeric_type value)
00116       {
00117         expr_ = std::auto_ptr<InterfaceType>(new rt_constant<numeric_type>(value));
00118         op_  = std::auto_ptr<op_interface_type>(new op_unary_id_type());
00119         return *this;
00120       }
00121 
00123       const InterfaceType     * lhs() const { return expr_.get(); }
00124       
00126       const op_interface_type * op()  const { return op_.get(); }
00127       
00129       
00130       //operator() is a convenience layer:
00132       numeric_type operator()(numeric_type val) const
00133       {
00134         return this->eval(val);
00135       }
00136 
00138       template <typename ScalarType>
00139       numeric_type operator()(rt_constant<ScalarType> val) const
00140       {
00141         return this->eval(static_cast<numeric_type>(val));
00142       }
00143       
00145       template <long value>
00146       numeric_type operator()(ct_constant<value> val) const
00147       {
00148         return this->eval(value);
00149       }
00150 
00152       template <typename VectorType>
00153       numeric_type operator()(VectorType const & v) const
00154       {
00155         std::vector<double> stl_v(v.size());
00156         for (std::size_t i=0; i<v.size(); ++i)
00157           stl_v[i] = v[i];
00158         
00159         return this->eval(stl_v);
00160       }
00161 
00163       numeric_type operator()(std::vector<numeric_type> const & stl_v) const
00164       {
00165         return this->eval(stl_v);
00166       }
00167 
00169       template <typename T0>
00170       numeric_type operator()(viennamath::ct_vector_1<T0> const & v) const
00171       {
00172         std::vector<double> stl_v(1);
00173         stl_v[0] = v[ct_index<0>()];
00174         return this->eval(stl_v);
00175       }
00176 
00178       template <typename T0, typename T1>
00179       numeric_type operator()(viennamath::ct_vector_2<T0, T1> const & v) const
00180       {
00181         std::vector<double> stl_v(2);
00182         stl_v[0] = v[ct_index<0>()];
00183         stl_v[1] = v[ct_index<1>()];
00184         return this->eval(stl_v);
00185       }
00186       
00188       template <typename T0, typename T1, typename T2>
00189       numeric_type operator()(viennamath::ct_vector_3<T0, T1, T2> const & v) const
00190       {
00191         std::vector<double> stl_v(3);
00192         stl_v[0] = v[ct_index<0>()];
00193         stl_v[1] = v[ct_index<1>()];
00194         stl_v[2] = v[ct_index<2>()];
00195         return this->eval(stl_v);
00196       }
00197       
00198       //virtual functions for evaluations
00200       numeric_type eval(std::vector<double> const & v) const
00201       {
00202         return op_->apply(expr_.get()->eval(v));
00203       }
00204 
00206       numeric_type eval(numeric_type val) const
00207       {
00208         return op_->apply(expr_.get()->eval(val));
00209       }
00210 
00212       
00214       InterfaceType * simplify() const
00215       {
00216         if (expr_->is_constant())
00217         {
00218           if (op_->can_simplify())
00219             return new rt_constant<numeric_type, InterfaceType>( op_->apply(expr_->unwrap()) );
00220           else
00221             return new rt_unary_expr(new rt_constant<numeric_type, InterfaceType>(expr_->unwrap()),
00222                                      op_->clone());
00223         }
00224 
00225         //TODO: Unwrap op_id()
00226         
00227         return new rt_unary_expr(expr_->simplify(), op_->clone());
00228       }
00229       
00231       bool can_simplify() const
00232       {
00233         if (expr_->can_simplify())
00234         {
00235           //std::cout << "optimizable(): true in unary_expr" << std::endl;
00236           return true;
00237         }
00238         return false;
00239       }
00240       
00241     
00243 
00244       InterfaceType * clone() const { return new rt_unary_expr(expr_->clone(), op_->clone()); }
00245       
00247       std::string deep_str() const
00248       {
00249         std::stringstream ss;
00250         ss << op_->str();
00251         ss << "(";
00252         ss << expr_->deep_str();
00253         ss << ")";
00254         return ss.str();        
00255       }
00256       
00258       std::string shallow_str() const
00259       {
00260         return std::string("unary_expr");
00261       }
00262       
00264       numeric_type unwrap() const
00265       {
00266         //if (op_->is_unary())
00267         //  return lhs_->unwrap();
00268         return op_->apply(expr_->unwrap());
00269       }
00270       
00272       InterfaceType * substitute(const InterfaceType * e,
00273                                  const InterfaceType * repl) const
00274       {
00275         if (deep_equal(e))
00276           return repl->clone();
00277         
00278         return new rt_unary_expr(expr_->substitute(e, repl),
00279                               op_->clone());
00280       };
00281 
00283       InterfaceType * substitute(std::vector<const InterfaceType *> const &  e,
00284                                  std::vector<const InterfaceType *> const &  repl) const
00285       {
00286         for (std::size_t i=0; i<e.size(); ++i)
00287           if (deep_equal(e[i]))
00288             return repl[i]->clone();
00289         
00290         return new rt_unary_expr(expr_->substitute(e, repl),
00291                               op_->clone());
00292       };
00293       
00295       bool deep_equal(const InterfaceType * other) const
00296       {
00297         if (dynamic_cast<const rt_unary_expr *>(other) != NULL)
00298         {
00299            const rt_unary_expr * temp = dynamic_cast<const rt_unary_expr *>(other);
00300            
00301            return expr_->deep_equal(temp->expr_.get())
00302                   && op_->equal(temp->op_.get());
00303         }
00304         return false;
00305       }
00306 
00308       bool shallow_equal(const InterfaceType * other) const
00309       {
00310         return dynamic_cast< const self_type * >(other) != NULL;
00311       }
00312       
00314       InterfaceType * diff(const InterfaceType * diff_var) const
00315       {
00316         return op_->diff(expr_.get(), diff_var);
00317       }
00318       
00320       InterfaceType * recursive_manipulation(rt_manipulation_wrapper<InterfaceType> const & fw) const
00321       {
00322         if (fw.modifies(this))
00323           return fw(this);
00324 
00325         return new rt_unary_expr(expr_->recursive_manipulation(fw),
00326                               op_->clone() ); 
00327       }
00328 
00330       void recursive_traversal(rt_traversal_wrapper<InterfaceType> const & fw) const
00331       {
00332         fw(this);
00333         expr_->recursive_traversal(fw);
00334       }
00335       
00336     private:
00337       std::auto_ptr<InterfaceType>      expr_;
00338       std::auto_ptr<op_interface_type>  op_;
00339   };
00340   
00342   template <typename InterfaceType>
00343   std::ostream& operator<<(std::ostream & stream, rt_unary_expr<InterfaceType> const & e)
00344   {
00345     stream << "unary" 
00346            << e.deep_str()
00347            << "";
00348     return stream;
00349   }
00350   
00351   
00352 }
00353 
00354 #endif

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