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

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

Go to the documentation of this file.
00001 #ifndef VIENNAMATH_MANIPULATION_LATEX_HPP
00002 #define VIENNAMATH_MANIPULATION_LATEX_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 <map>
00021 
00022 #include "viennamath/forwards.h"
00023 #include "viennamath/runtime/unary_expr.hpp"
00024 #include "viennamath/compiletime/unary_op_tags.hpp"
00025 
00030 namespace viennamath
00031 {
00032   //
00033   // LaTeX processing
00034   //
00035   template <typename InterfaceType = default_interface_type>
00036   class rt_latex_translator;
00037   
00038   template <typename InterfaceType = default_interface_type>
00039   class rt_latex_binary_expr_processor;
00040 
00041   template <typename InterfaceType = default_interface_type>
00042   class rt_latex_unary_expr_processor;
00043 
00044   template <typename InterfaceType = default_interface_type>
00045   class rt_latex_constant_processor;
00046 
00047   template <typename InterfaceType = default_interface_type>
00048   class rt_latex_variable_processor;
00049 
00050   template <typename InterfaceType = default_interface_type>
00051   class rt_latex_function_symbol_processor;
00052 
00053   
00054   
00059   template <typename InterfaceType = default_interface_type>
00060   class rt_latex_processor_interface
00061   {
00062     public: 
00069       virtual std::string process(InterfaceType const * e,
00070                                   bool use_parenthesis,
00071                                   rt_latex_translator<InterfaceType> const & trans) const = 0;
00072          
00078       virtual bool customize(InterfaceType const * e, std::string const & str) { return false; }
00079   };
00080   
00081   
00086   template <typename InterfaceType>
00087   class rt_latex_translator
00088   {
00089       typedef typename InterfaceType::numeric_type                           NumericType;
00090     
00091       typedef viennamath::rt_binary_expr<InterfaceType>                      BinaryExpr;
00092       typedef viennamath::rt_unary_expr<InterfaceType>                       UnaryExpr;
00093       typedef viennamath::rt_constant<default_numeric_type, InterfaceType>   Constant;
00094       typedef viennamath::rt_variable<InterfaceType>                         Variable;
00095       typedef viennamath::rt_function_symbol<InterfaceType>                  FuncSymbol;
00096       typedef viennamath::rt_equation<InterfaceType>                         Equation;
00097       typedef viennamath::rt_interval<InterfaceType>                         Interval;
00098       
00099       typedef rt_latex_processor_interface<InterfaceType>                    ProcessorInterface;
00100       typedef std::vector< ProcessorInterface *>                             ProcessorArray;
00101     
00102     public:
00103       
00104       rt_latex_translator()
00105       {
00106         processors_.push_back(new rt_latex_binary_expr_processor<InterfaceType>());
00107         processors_.push_back(new rt_latex_unary_expr_processor<InterfaceType>());
00108         processors_.push_back(new rt_latex_constant_processor<InterfaceType>());
00109         processors_.push_back(new rt_latex_variable_processor<InterfaceType>());
00110         processors_.push_back(new rt_latex_function_symbol_processor<InterfaceType>());
00111       }
00112       
00113       ~rt_latex_translator()
00114       {
00115         for (typename ProcessorArray::iterator it = processors_.begin();
00116                                                it != processors_.end();
00117                                              ++it)
00118         {
00119           delete *it;
00120         }
00121       }
00122 
00123       //
00124       // Generic runtime expression. Unwrap it and then scan through types
00125       //
00126       std::string operator()(viennamath::rt_expr<InterfaceType> const & e,
00127                              bool use_parenthesis = false) const
00128       {
00129         return process_impl(e.get(), use_parenthesis);
00130       }
00131       
00132       std::string operator()(BinaryExpr const & e, bool use_parenthesis = false) const { return process_impl(&e, use_parenthesis); }
00133       std::string operator()(UnaryExpr  const & e, bool use_parenthesis = false) const { return process_impl(&e, use_parenthesis); }
00134 
00135       template <typename ScalarType>
00136       std::string operator()(viennamath::rt_constant<ScalarType, InterfaceType> const & e, bool use_parenthesis = false) const { return process_impl(e, use_parenthesis); }
00137       std::string operator()(Variable   const & e, bool use_parenthesis = false) const { return process_impl(&e, use_parenthesis); }
00138       std::string operator()(FuncSymbol const & e, bool use_parenthesis = false) const { return process_impl(&e, use_parenthesis); }
00139       std::string operator()(Equation   const & e, bool use_parenthesis = false) const
00140       {
00141         std::stringstream ss;
00142         ss << operator()(e.lhs()) << " = " << operator()(e.rhs());
00143         return ss.str();        
00144       }
00145       std::string operator()(Interval   const & e, bool use_parenthesis = false) const 
00146       {
00147         std::stringstream ss;
00148         ss << " [ " << operator()(e.lower()) << "; " << operator()(e.upper()) << " ] ";
00149         return ss.str();        
00150       }
00151       
00157       template <typename ExpressionType>
00158       void customize(ExpressionType const & e, std::string output)
00159       {
00160         bool found = false;
00161         for (typename ProcessorArray::const_iterator it = processors_.begin();
00162                                                      it != processors_.end();
00163                                                    ++it)
00164         {
00165           found |= (*it)->customize(&e, output);
00166         }       
00167         
00168         if (!found)
00169           std::cerr << "Warning: Cannot customize LaTeX translator for " << e << " (no suitable processor found)" << std::endl;
00170         //variable_strings_[x.id()] = output;
00171       }
00172       
00174       void add_processor(ProcessorInterface * proc_ptr)
00175       {
00176         processors_.push_back(proc_ptr);
00177       }
00178 
00179     private:
00180       
00181       std::string process_impl(InterfaceType const * ptr,
00182                                bool use_parenthesis = false) const
00183       {
00184         std::string ret;
00185         
00186         for (typename ProcessorArray::const_iterator it = processors_.begin();
00187                                                      it != processors_.end();
00188                                                    ++it)
00189         {
00190           ret = (*it)->process(ptr, use_parenthesis, *this);
00191           if (ret.size() > 0)
00192             return ret;
00193         }       
00194         
00195         std::cerr << "ViennaMath: Warning: Unknown type in latex translator: " << ptr << std::endl;
00196         //throw "Unknown type!";
00197         return " \\chi_{\\mathrm{unknown}} ";
00198       }
00199       
00200     ProcessorArray processors_;
00201   };
00202   
00204   typedef rt_latex_translator<>      latex_translator;
00205 
00206   
00207   
00208   //
00209   // Binary expression
00210   //
00215   template <typename InterfaceType>
00216   class rt_latex_binary_expr_processor : public rt_latex_processor_interface<InterfaceType>
00217   {
00218       typedef typename InterfaceType::numeric_type           NumericType;
00219       typedef viennamath::rt_binary_expr<InterfaceType>      BinaryExpr;
00220     
00221     public:
00222       
00223       std::string process(InterfaceType const * ptr, bool use_parenthesis, rt_latex_translator<InterfaceType> const & translator) const 
00224       {
00225         if (dynamic_cast< const BinaryExpr * >(ptr) != NULL)
00226         {
00227           const BinaryExpr * temp = dynamic_cast< const BinaryExpr * >(ptr);
00228           return process_impl(*temp, use_parenthesis, translator);
00229         }
00230         
00231         return "";
00232       }
00233        
00234     private:
00235 
00236       std::string process_impl(BinaryExpr const & e, bool use_parenthesis, rt_latex_translator<InterfaceType> const & translator) const 
00237       {
00238         std::stringstream ss;
00239         viennamath::rt_expr<InterfaceType> lhs(e.lhs()->clone());
00240         viennamath::rt_expr<InterfaceType> rhs(e.rhs()->clone());
00241         
00242         if (dynamic_cast< const op_binary<op_div<NumericType>, InterfaceType> * >(e.op()) != NULL)  //division -> \frac{}{}
00243         {
00244           if (use_parenthesis)
00245             ss << " \\left( ";
00246           ss << " \\frac{" << translator(lhs) << "}{" << translator(rhs) << "} ";
00247           if (use_parenthesis)
00248             ss << " \\right) ";
00249         }
00250         else
00251         {
00252           bool is_op_mult = false;
00253           if (dynamic_cast< const op_binary<op_mult<NumericType>, InterfaceType> * >(e.op()) != NULL)
00254             is_op_mult = true;
00255 
00256           bool is_op_minus = false;
00257           if (dynamic_cast< const op_binary<op_minus<NumericType>, InterfaceType> * >(e.op()) != NULL)
00258             is_op_minus = true;
00259           
00260           if (use_parenthesis)
00261             ss << "(";
00262           ss << translator(lhs, is_op_mult);
00263           if (is_op_mult)
00264             ss << " \\cdot ";
00265           else
00266             ss << " " << e.op()->str() << " ";
00267           ss << translator(rhs, is_op_mult || is_op_minus);
00268           if (use_parenthesis)
00269             ss << ")";
00270         }
00271         
00272         return ss.str();
00273       }      
00274       
00275   }; 
00276   
00277 
00278   
00279   //
00280   // Unary expression
00281   //
00286   template <typename InterfaceType>
00287   class rt_latex_unary_expr_processor : public rt_latex_processor_interface<InterfaceType>
00288   {
00289       typedef typename InterfaceType::numeric_type           NumericType;
00290       typedef viennamath::rt_unary_expr<InterfaceType>       UnaryExpr;
00291     
00292     public:
00293       
00294       std::string process(InterfaceType const * ptr, bool use_parenthesis, rt_latex_translator<InterfaceType> const & translator) const 
00295       {
00296         if (dynamic_cast< const UnaryExpr * >(ptr) != NULL)
00297         {
00298           const UnaryExpr * temp = dynamic_cast< const UnaryExpr * >(ptr);
00299           return process_impl(*temp, use_parenthesis, translator);
00300         }
00301         
00302         return "";
00303       }
00304        
00305     private:
00306 
00307       std::string process_impl(UnaryExpr const & e, bool use_parenthesis, rt_latex_translator<InterfaceType> const & translator) const 
00308       {
00309         typedef op_unary<op_id<NumericType>,    InterfaceType>    OpId;
00310         typedef op_unary<op_exp<NumericType>,   InterfaceType>    OpExp;
00311         typedef op_unary<op_sin<NumericType>,   InterfaceType>    OpSin;
00312         typedef op_unary<op_cos<NumericType>,   InterfaceType>    OpCos;
00313         typedef op_unary<op_tan<NumericType>,   InterfaceType>    OpTan;
00314         typedef op_unary<op_fabs<NumericType>,  InterfaceType>    OpFabs;
00315         typedef op_unary<op_sqrt<NumericType>,  InterfaceType>    OpSqrt;
00316         typedef op_unary<op_log<NumericType>,   InterfaceType>    OpLog;
00317         typedef op_unary<op_log10<NumericType>, InterfaceType>    OpLog10;
00318         
00319         // symbolic stuff:
00320         typedef op_unary<op_gradient<NumericType>, InterfaceType>              OpGradient;
00321         typedef op_unary<op_divergence<NumericType>, InterfaceType>            OpDivergence;
00322         typedef op_unary<op_partial_deriv<NumericType>, InterfaceType>         OpPartialDeriv;
00323         typedef op_unary<op_rt_integral<InterfaceType>, InterfaceType>         OpRuntimeIntegration;
00324         typedef op_unary<op_rt_symbolic_integral<InterfaceType>, InterfaceType>         OpSymbolicIntegration;
00325         
00326         std::stringstream ss;
00327         viennamath::rt_expr<InterfaceType> lhs(e.lhs()->clone());
00328         
00329         if (dynamic_cast< const OpId * >(e.op()) != NULL)
00330           ss << translator(lhs, use_parenthesis);
00331         else if (dynamic_cast< const OpExp * >(e.op()) != NULL)
00332           ss << " \\exp " << translator(lhs, true) << " ";          
00333         else if (dynamic_cast< const OpSin * >(e.op()) != NULL)
00334           ss << " \\sin " << translator(lhs, true) << " ";          
00335         else if (dynamic_cast< const OpCos * >(e.op()) != NULL)
00336           ss << " \\cos " << translator(lhs, true) << " ";          
00337         else if (dynamic_cast< const OpTan * >(e.op()) != NULL)
00338           ss << " \\tan " << translator(lhs, true) << " ";          
00339         else if (dynamic_cast< const OpFabs * >(e.op()) != NULL)
00340           ss << " \\left|" << translator(lhs) << "\\right| ";          
00341         else if (dynamic_cast< const OpSqrt * >(e.op()) != NULL)
00342           ss << " \\sqrt{" << translator(lhs) << "} ";          
00343         else if (dynamic_cast< const OpLog * >(e.op()) != NULL)
00344           ss << " \\ln " << translator(lhs, true) << " ";          
00345         else if (dynamic_cast< const OpLog10 * >(e.op()) != NULL)
00346           ss << " \\log " << translator(lhs, true) << " ";     
00347         
00348         else if (dynamic_cast< const OpGradient * >(e.op()) != NULL)
00349           ss << " \\nabla " << translator(lhs, true) << " ";     
00350         else if (dynamic_cast< const OpDivergence * >(e.op()) != NULL)
00351           ss << " \\nabla \\cdot " << translator(lhs, true) << " ";     
00352         else if (dynamic_cast< const OpPartialDeriv * >(e.op()) != NULL)
00353         {
00354           const OpPartialDeriv * tmp = dynamic_cast< const OpPartialDeriv * >(e.op());
00355           viennamath::rt_variable<InterfaceType> var(tmp->op().id());
00356           ss << " \\frac{\\partial " << translator(lhs, true) << "}{\\partial " << translator(var) << "} ";
00357         }
00358         else if (dynamic_cast< const OpRuntimeIntegration * >(e.op()) != NULL)
00359         {
00360           const OpRuntimeIntegration * op_integral = dynamic_cast< const OpRuntimeIntegration * >(e.op());
00361           
00362           ss << " \\int_{ " << translator(op_integral->op().interval()) << " } ";
00363           ss << translator(lhs) << " ";
00364           ss << " \\: \\mathrm{d} " << translator(op_integral->op().variable()) << " ";
00365         }
00366         else if (dynamic_cast< const OpSymbolicIntegration * >(e.op()) != NULL)
00367         {
00368           const OpSymbolicIntegration * op_integral = dynamic_cast< const OpSymbolicIntegration * >(e.op());
00369           // integral:
00370           ss << " \\int_{\\Omega_{" << op_integral->op().interval().id() << "}} ";
00371           ss << translator(lhs) << " ";
00372           ss << " \\: \\mathrm{d} \\Omega ";
00373         }
00374         else
00375         {
00376           std::cout << "Operator not supported: " << e.op()->str() << std::endl;
00377           throw "Not supported!";
00378         }
00379         
00380         return ss.str();
00381       }
00382       
00383   }; 
00384   
00385   
00386   //
00387   // Constant
00388   //
00393   template <typename InterfaceType>
00394   class rt_latex_constant_processor : public rt_latex_processor_interface<InterfaceType>
00395   {
00396       typedef typename InterfaceType::numeric_type           NumericType;
00397       typedef viennamath::rt_constant<default_numeric_type, InterfaceType>   Constant;
00398     
00399     public:
00400       
00401       std::string process(InterfaceType const * ptr, bool use_parenthesis, rt_latex_translator<InterfaceType> const & translator) const 
00402       {
00403         if (dynamic_cast< const Constant * >(ptr) != NULL)
00404         {
00405           const Constant * temp = dynamic_cast< const Constant * >(ptr);
00406           return process_impl(*temp, use_parenthesis, translator);
00407         }
00408         
00409         return "";
00410       }
00411        
00412     private:
00413 
00414       std::string process_impl(Constant const & e, bool use_parenthesis, rt_latex_translator<InterfaceType> const & translator) const 
00415       {
00416         std::stringstream ss;
00417         ss << " " << static_cast<NumericType>(e) << " ";
00418         return ss.str();        
00419       }      
00420       
00421   }; 
00422   
00423 
00424   //
00425   // Variable
00426   //
00431   template <typename InterfaceType>
00432   class rt_latex_variable_processor : public rt_latex_processor_interface<InterfaceType>
00433   {
00434       typedef typename InterfaceType::numeric_type           NumericType;
00435       typedef viennamath::rt_variable<InterfaceType>                         Variable;
00436     
00437     public:
00438       
00439       std::string process(InterfaceType const * ptr, bool use_parenthesis, rt_latex_translator<InterfaceType> const & translator) const 
00440       {
00441         if (dynamic_cast< const Variable * >(ptr) != NULL)
00442         {
00443           const Variable * temp = dynamic_cast< const Variable * >(ptr);
00444           return process_impl(*temp, use_parenthesis, translator);
00445         }
00446         
00447         return "";
00448       }
00449        
00450       bool customize(InterfaceType const * ptr, std::string const & str)
00451       {
00452         if (dynamic_cast< const Variable * >(ptr) != NULL)
00453         {
00454           const Variable * temp = dynamic_cast< const Variable * >(ptr);
00455           variable_strings_[temp->id()] = str;
00456           return true;
00457         }
00458         return false;
00459       }
00460       
00461     private:
00462 
00463       std::string process_impl(Variable const & e, bool use_parenthesis, rt_latex_translator<InterfaceType> const & translator) const 
00464       {
00465         std::stringstream ss;
00466 
00467         std::map<id_type, std::string>::const_iterator it = variable_strings_.find(e.id());
00468         if (it != variable_strings_.end())
00469           ss << it->second;
00470         else
00471           ss << " x_{" << e.id() << "} ";
00472         
00473         return ss.str();        
00474       }      
00475       
00476       std::map<id_type, std::string>                            variable_strings_;
00477   }; 
00478 
00479   //
00480   // Function Symbol
00481   //
00486   template <typename InterfaceType>
00487   class rt_latex_function_symbol_processor : public rt_latex_processor_interface<InterfaceType>
00488   {
00489       typedef typename InterfaceType::numeric_type              NumericType;
00490       typedef viennamath::rt_function_symbol<InterfaceType>     FuncSymbol;
00491       typedef std::pair<id_type, id_type>           KeyType;
00492     
00493     public:
00494       
00495       std::string process(InterfaceType const * ptr, bool use_parenthesis, rt_latex_translator<InterfaceType> const & translator) const 
00496       {
00497         if (dynamic_cast< const FuncSymbol * >(ptr) != NULL)
00498         {
00499           const FuncSymbol * temp = dynamic_cast< const FuncSymbol * >(ptr);
00500           return process_impl(*temp, use_parenthesis, translator);
00501         }
00502         
00503         return "";
00504       }
00505        
00506       bool customize(InterfaceType const * ptr, std::string const & str)
00507       {
00508         if (dynamic_cast< const FuncSymbol * >(ptr) != NULL)
00509         {
00510           const FuncSymbol * temp = dynamic_cast< const FuncSymbol * >(ptr);
00511           KeyType key(temp->id(), temp->tag_id());
00512           function_symbol_strings_[key] = str;
00513           return true;
00514         }
00515         return false;
00516       }
00517       
00518     private:
00519 
00520       std::string process_impl(FuncSymbol const & e, bool use_parenthesis, rt_latex_translator<InterfaceType> const & translator) const 
00521       {
00522         std::stringstream ss;
00523         
00524         KeyType func_symb_id(e.id(), e.tag_id());
00525         std::map<KeyType, std::string>::const_iterator it = function_symbol_strings_.find(func_symb_id);
00526         if (it != function_symbol_strings_.end())
00527         {
00528           ss << it->second;
00529         }
00530         else
00531         {
00532           if (e.tag_id() == test_tag<>::tag_id())
00533             ss << " v_{" << e.id() << "} ";
00534           else
00535             ss << " u_{" << e.id() << "} ";
00536         }
00537         
00538         return ss.str();        
00539       }
00540       
00541       std::map<KeyType, std::string>  function_symbol_strings_;
00542     
00543   }; 
00544   
00545   
00546 
00547 }
00548 
00549 #endif

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