GiNaC  1.6.2
symbol.cpp
Go to the documentation of this file.
00001 
00005 /*
00006  *  GiNaC Copyright (C) 1999-2011 Johannes Gutenberg University Mainz, Germany
00007  *
00008  *  This program is free software; you can redistribute it and/or modify
00009  *  it under the terms of the GNU General Public License as published by
00010  *  the Free Software Foundation; either version 2 of the License, or
00011  *  (at your option) any later version.
00012  *
00013  *  This program is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *  GNU General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU General Public License
00019  *  along with this program; if not, write to the Free Software
00020  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  */
00022 
00023 #include "symbol.h"
00024 #include "lst.h"
00025 #include "archive.h"
00026 #include "tostring.h"
00027 #include "utils.h"
00028 #include "hash_seed.h"
00029 #include "inifcns.h"
00030 
00031 #include <map>
00032 #include <stdexcept>
00033 #include <string>
00034 
00035 namespace GiNaC {
00036 
00037 GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(symbol, basic,
00038   print_func<print_context>(&symbol::do_print).
00039   print_func<print_latex>(&symbol::do_print_latex).
00040   print_func<print_tree>(&symbol::do_print_tree).
00041   print_func<print_python_repr>(&symbol::do_print_python_repr))
00042 
00043 
00044 // default constructor
00046 
00047 // symbol
00048 
00049 symbol::symbol() : serial(next_serial++), name(""), TeX_name("")
00050 {
00051     setflag(status_flags::evaluated | status_flags::expanded);
00052 }
00053 
00054 // realsymbol
00055 
00056 realsymbol::realsymbol() : symbol() { }
00057 
00058 // possymbol
00059 
00060 possymbol::possymbol() : realsymbol() { }
00061 
00063 // other constructors
00065 
00066 // public
00067 
00068 // symbol
00069 
00070 symbol::symbol(const std::string & initname) : serial(next_serial++),
00071     name(initname), TeX_name("")
00072 {
00073     setflag(status_flags::evaluated | status_flags::expanded);
00074 }
00075 
00076 symbol::symbol(const std::string & initname, const std::string & texname) :
00077     serial(next_serial++), name(initname), TeX_name(texname)
00078 {
00079     setflag(status_flags::evaluated | status_flags::expanded);
00080 }
00081 
00082 // realsymbol
00083     
00084 realsymbol::realsymbol(const std::string & initname) : symbol(initname) { }
00085 
00086 realsymbol::realsymbol(const std::string & initname, const std::string & texname)
00087     : symbol(initname, texname) { }
00088 
00089 // possymbol
00090     
00091 possymbol::possymbol(const std::string & initname) : realsymbol(initname) { }
00092 
00093 possymbol::possymbol(const std::string & initname, const std::string & texname) 
00094     : realsymbol(initname, texname) { }
00095 
00097 // archiving
00099 
00101 void symbol::read_archive(const archive_node &n, lst &sym_lst)
00102 {
00103     inherited::read_archive(n, sym_lst);
00104     serial = next_serial++;
00105     std::string tmp_name;
00106     n.find_string("name", tmp_name);
00107 
00108     // If symbol is in sym_lst, return the existing symbol
00109     for (lst::const_iterator it = sym_lst.begin(); it != sym_lst.end(); ++it) {
00110         if (is_a<symbol>(*it) && (ex_to<symbol>(*it).name == tmp_name)) {
00111             *this = ex_to<symbol>(*it);
00112             // XXX: This method is responsible for reading realsymbol
00113             // and possymbol objects too. But
00114             // basic::operator=(const basic& other)
00115             // resets status_flags::evaluated if other and *this are
00116             // of different types. Usually this is a good idea, but
00117             // doing this for symbols is wrong (for one, nothing is
00118             // going to set status_flags::evaluated, evaluation will
00119             // loop forever). Therefore we need to restore flags.
00120             setflag(status_flags::evaluated | status_flags::expanded);
00121             return;
00122         }
00123     }
00124     name = tmp_name;
00125     if (!n.find_string("TeXname", TeX_name))
00126         TeX_name = std::string("");
00127     setflag(status_flags::evaluated | status_flags::expanded);
00128 
00129     setflag(status_flags::dynallocated);
00130     sym_lst.append(*this);
00131 }
00132 
00134 void symbol::archive(archive_node &n) const
00135 {
00136     inherited::archive(n);
00137     // XXX: we should not archive anonymous symbols.
00138     if (!name.empty())
00139         n.add_string("name", name);
00140     if (!TeX_name.empty())
00141         n.add_string("TeX_name", TeX_name);
00142 }
00143 
00145 // functions overriding virtual functions from base classes
00147 
00149 static const std::string& get_default_TeX_name(const std::string& name);
00150 
00151 // public
00152 
00153 std::string symbol::get_name() const
00154 {
00155     if (name.empty()) {
00156         std::ostringstream s;
00157         s << "symbol" << serial;
00158         name = s.str();
00159     }
00160     return name;
00161 }
00162 
00163 // protected
00164 
00165 void symbol::do_print(const print_context & c, unsigned level) const
00166 {
00167     c.s << get_name();
00168 }
00169 
00170 void symbol::do_print_latex(const print_latex & c, unsigned level) const
00171 {
00172     if (!TeX_name.empty())
00173         c.s << TeX_name;
00174     else if (!name.empty())
00175         c.s << get_default_TeX_name(name);
00176     else
00177         c.s << "symbol" << serial;
00178 }
00179 
00180 void symbol::do_print_tree(const print_tree & c, unsigned level) const
00181 {
00182     c.s << std::string(level, ' ') << name << " (" << class_name() << ")" << " @" << this
00183         << ", serial=" << serial
00184         << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
00185         << ", domain=" << get_domain()
00186         << std::endl;
00187 }
00188 
00189 void symbol::do_print_python_repr(const print_python_repr & c, unsigned level) const
00190 {
00191     c.s << class_name() << "('";
00192     if (!name.empty())
00193         c.s << name;
00194     else
00195         c.s << "symbol" << serial;
00196     if (!TeX_name.empty())
00197         c.s << "','" << TeX_name;
00198     c.s << "')";
00199 }
00200 
00201 bool symbol::info(unsigned inf) const
00202 {
00203     switch (inf) {
00204         case info_flags::symbol:
00205         case info_flags::polynomial:
00206         case info_flags::integer_polynomial: 
00207         case info_flags::cinteger_polynomial: 
00208         case info_flags::rational_polynomial: 
00209         case info_flags::crational_polynomial: 
00210         case info_flags::rational_function: 
00211         case info_flags::expanded:
00212             return true;
00213         case info_flags::real:
00214             return get_domain() == domain::real || get_domain() == domain::positive;
00215         case info_flags::positive:
00216         case info_flags::nonnegative:
00217             return get_domain() == domain::positive;
00218         case info_flags::has_indices:
00219             return false;
00220     }
00221     return inherited::info(inf);
00222 }
00223 
00224 ex symbol::conjugate() const
00225 {
00226     return conjugate_function(*this).hold();
00227 }
00228 
00229 ex symbol::real_part() const
00230 {
00231     return real_part_function(*this).hold();
00232 }
00233 
00234 ex symbol::imag_part() const
00235 {
00236     return imag_part_function(*this).hold();
00237 }
00238 
00239 bool symbol::is_polynomial(const ex & var) const
00240 {
00241     return true;
00242 }
00243 
00244 // protected
00245 
00250 ex symbol::derivative(const symbol & s) const
00251 {
00252     if (compare_same_type(s))
00253         return _ex0;
00254     else
00255         return _ex1;
00256 }
00257 
00258 int symbol::compare_same_type(const basic & other) const
00259 {
00260     GINAC_ASSERT(is_a<symbol>(other));
00261     const symbol *o = static_cast<const symbol *>(&other);
00262     if (serial==o->serial) return 0;
00263     return serial < o->serial ? -1 : 1;
00264 }
00265 
00266 bool symbol::is_equal_same_type(const basic & other) const
00267 {
00268     GINAC_ASSERT(is_a<symbol>(other));
00269     const symbol *o = static_cast<const symbol *>(&other);
00270     return serial==o->serial;
00271 }
00272 
00273 unsigned symbol::calchash() const
00274 {
00275     unsigned seed = make_hash_seed(typeid(*this));
00276     hashvalue = golden_ratio_hash(seed ^ serial);
00277     setflag(status_flags::hash_calculated);
00278     return hashvalue;
00279 }
00280 
00282 // virtual functions which can be overridden by derived classes
00284 
00285 // none
00286 
00288 // non-virtual functions in this class
00290 
00292 static const std::string& get_default_TeX_name(const std::string& name)
00293 {
00294     static std::map<std::string, std::string> standard_names;
00295     static bool names_initialized = false;
00296     if (!names_initialized) {
00297         standard_names["alpha"] = std::string("\\alpha");
00298         standard_names["beta"] = std::string("\\beta");;
00299         standard_names["gamma"] = std::string("\\gamma");;
00300         standard_names["delta"] = std::string("\\delta");;
00301         standard_names["epsilon"] = std::string("\\epsilon");
00302         standard_names["varepsilon"] = std::string("\\varepsilon");
00303         standard_names["zeta"] = std::string("\\zeta");
00304         standard_names["eta" ] = std::string("\\eta" );
00305         standard_names["theta"] = std::string("\\theta");
00306         standard_names["vartheta"] = std::string("\\vartheta");
00307         standard_names["iota"] = std::string("\\iota");
00308         standard_names["kappa"] = std::string("\\kappa");
00309         standard_names["lambda"] = std::string("\\lambda");
00310         standard_names["mu"] = std::string("\\mu");
00311         standard_names["nu"] = std::string("\\nu");
00312         standard_names["xi"] = std::string("\\xi");
00313         standard_names["omicron"] = std::string("\\omicron");
00314         standard_names["pi"] = std::string("\\pi");
00315         standard_names["varpi"] = std::string("\\varpi");
00316         standard_names["rho"] = std::string("\\rho");
00317         standard_names["varrho"] = std::string("\\varrho");
00318         standard_names["sigma"] = std::string("\\sigma");
00319         standard_names["varsigma"] = std::string("\\varsigma");
00320         standard_names["tau"] = std::string("\\tau");
00321         standard_names["upsilon"] = std::string("\\upsilon");
00322         standard_names["phi"] = std::string("\\phi");
00323         standard_names["varphi"] = std::string("\\varphi");
00324         standard_names["chi"] = std::string("\\chi");
00325         standard_names["psi"] = std::string("\\psi");
00326         standard_names["omega"] = std::string("\\omega");
00327         standard_names["Gamma"] = std::string("\\Gamma");
00328         standard_names["Delta"] = std::string("\\Delta");
00329         standard_names["Theta"] = std::string("\\Theta");
00330         standard_names["Lambda"] = std::string("\\Lambda");
00331         standard_names["Xi"] = std::string("\\Xi");
00332         standard_names["Pi"] = std::string("\\Pi");
00333         standard_names["Sigma"] = std::string("\\Sigma");
00334         standard_names["Upsilon"] = std::string("\\Upsilon");
00335         standard_names["Phi"] = std::string("\\Phi");
00336         standard_names["Psi"] = std::string("\\Psi");
00337         standard_names["Omega"] = std::string("\\Omega");
00338         names_initialized = true;
00339     }
00340     std::map<std::string, std::string>::const_iterator it = standard_names.find(name);
00341     if (it != standard_names.end())
00342         return it->second;
00343     else
00344         return name;
00345 }
00346 
00347 GINAC_BIND_UNARCHIVER(symbol);
00348 GINAC_BIND_UNARCHIVER(realsymbol);
00349 GINAC_BIND_UNARCHIVER(possymbol);
00350 
00352 // static member variables
00354 
00355 // private
00356 
00357 unsigned symbol::next_serial = 0;
00358 
00359 } // namespace GiNaC

This page is part of the GiNaC developer's reference. It was generated automatically by doxygen. For an introduction, see the tutorial.