|
GiNaC
1.6.2
|
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