00001 #ifndef VIENNAMATH_RUNTIME_FUNCTION_SYMBOL_HPP 00002 #define VIENNAMATH_RUNTIME_FUNCTION_SYMBOL_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 <ostream> 00021 #include <sstream> 00022 #include "viennamath/forwards.h" 00023 #include "viennamath/expression.hpp" 00024 #include "viennamath/compiletime/ct_function_symbol.hpp" 00025 #include "viennamath/runtime/expression_interface.hpp" 00026 00031 namespace viennamath 00032 { 00033 00038 template <typename InterfaceType> 00039 class rt_function_symbol : public InterfaceType 00040 { 00041 typedef rt_function_symbol<InterfaceType> self_type; 00042 public: 00043 typedef typename InterfaceType::numeric_type numeric_type; 00044 typedef InterfaceType interface_type; 00045 00051 template <typename Tag> 00052 rt_function_symbol(id_type i, Tag const & t) : id_(i), tag_id_(Tag::tag_id()) {} 00053 00059 rt_function_symbol(id_type i, id_type t = 0) : id_(i), tag_id_(t) {} 00060 00061 rt_function_symbol() : id_(0), tag_id_(unknown_tag<>::tag_id()) {} 00062 00063 id_type id() const { return id_; } 00064 id_type tag_id() const { return tag_id_; } 00065 00066 // 00067 // interface requirements: 00068 // 00069 00071 InterfaceType * clone() const { return new self_type(id_, tag_id_); } 00072 00074 numeric_type eval(std::vector<double> const & v) const { throw expression_not_evaluable_exception("Cannot evaluate rt_function_symbol!"); return 0; } 00076 numeric_type eval(numeric_type v) const { throw expression_not_evaluable_exception("Cannot evaluate rt_function_symbol!"); return 0; } 00077 00079 std::string deep_str() const 00080 { 00081 std::stringstream ss; 00082 ss << "function_symbol<"; 00083 if (tag_id_ == unknown_tag<>::tag_id()) 00084 ss << "unknown(" << id_ << ")>"; 00085 else if (tag_id_ == test_tag<>::tag_id()) 00086 ss << "test(" << id_ << ")>"; 00087 else 00088 ss << "invalid>"; 00089 00090 return ss.str(); 00091 } 00092 00094 numeric_type unwrap() const { throw expression_not_unwrappable_exception("Cannot evaluate rt_function_symbol to a number!"); } 00095 00097 InterfaceType * substitute(const InterfaceType * e, 00098 const InterfaceType * repl) const 00099 { 00100 if (deep_equal(e)) 00101 return repl->clone(); 00102 00103 return clone(); 00104 }; 00105 00107 InterfaceType * substitute(std::vector<const InterfaceType *> const & e, 00108 std::vector<const InterfaceType *> const & repl) const 00109 { 00110 //std::cout << "Comparing variable<" << id << "> with " << e->str() << ", result: "; 00111 for (std::size_t i=0; i<e.size(); ++i) 00112 if (deep_equal(e[i])) 00113 return repl[i]->clone(); 00114 00115 //std::cout << "FALSE" << std::endl; 00116 return clone(); 00117 }; 00118 00120 bool deep_equal(const InterfaceType * other) const 00121 { 00122 const self_type * ptr = dynamic_cast< const self_type *>(other); 00123 if (ptr != NULL) 00124 return (ptr->id() == id_ && ptr->tag_id_ == tag_id_); 00125 00126 return false; 00127 } 00128 00130 bool shallow_equal(const InterfaceType * other) const 00131 { 00132 return dynamic_cast< const self_type * >(other) != NULL; 00133 } 00134 00136 InterfaceType * diff(const InterfaceType * diff_var) const 00137 { 00138 //this code should not be reached, because rt_function_symbol is symbolically differentiated at a higher level 00139 throw expression_not_differentiable_exception("Cannot differentiate rt_function_symbol!"); 00140 return NULL; 00141 } 00142 00143 private: 00145 id_type id_; 00147 id_type tag_id_; 00148 }; 00149 00150 00151 00152 template <typename InterfaceType> 00153 std::ostream& operator<<(std::ostream & stream, rt_function_symbol<InterfaceType> const & v) 00154 { 00155 stream << v.deep_str(); 00156 return stream; 00157 } 00158 00159 00160 00161 } 00162 00163 #endif