|
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 "constant.h" 00024 #include "numeric.h" 00025 #include "ex.h" 00026 #include "archive.h" 00027 #include "utils.h" 00028 #include "inifcns.h" 00029 00030 #include <iostream> 00031 #include <stdexcept> 00032 #include <string> 00033 00034 namespace GiNaC { 00035 00036 GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(constant, basic, 00037 print_func<print_context>(&constant::do_print). 00038 print_func<print_latex>(&constant::do_print_latex). 00039 print_func<print_tree>(&constant::do_print_tree). 00040 print_func<print_python_repr>(&constant::do_print_python_repr)) 00041 00042 00043 // default constructor 00045 00046 // public 00047 00048 constant::constant() : ef(0), serial(next_serial++), domain(domain::complex) 00049 { 00050 setflag(status_flags::evaluated | status_flags::expanded); 00051 } 00052 00054 // other constructors 00056 00057 // public 00058 00059 constant::constant(const std::string & initname, evalffunctype efun, const std::string & texname, unsigned dm) 00060 : name(initname), ef(efun), serial(next_serial++), domain(dm) 00061 { 00062 if (texname.empty()) 00063 TeX_name = "\\mathrm{" + name + "}"; 00064 else 00065 TeX_name = texname; 00066 setflag(status_flags::evaluated | status_flags::expanded); 00067 } 00068 00069 constant::constant(const std::string & initname, const numeric & initnumber, const std::string & texname, unsigned dm) 00070 : name(initname), ef(0), number(initnumber), serial(next_serial++), domain(dm) 00071 { 00072 if (texname.empty()) 00073 TeX_name = "\\mathrm{" + name + "}"; 00074 else 00075 TeX_name = texname; 00076 setflag(status_flags::evaluated | status_flags::expanded); 00077 } 00078 00080 // archiving 00082 00083 void constant::read_archive(const archive_node &n, lst &sym_lst) 00084 { 00085 // Find constant by name (!! this is bad: 'twould be better if there 00086 // was a list of all global constants that we could search) 00087 std::string s; 00088 if (n.find_string("name", s)) { 00089 if (s == Pi.name) 00090 *this = Pi; 00091 else if (s == Catalan.name) 00092 *this = Catalan; 00093 else if (s == Euler.name) 00094 *this = Euler; 00095 else 00096 throw (std::runtime_error("unknown constant '" + s + "' in archive")); 00097 } else 00098 throw (std::runtime_error("unnamed constant in archive")); 00099 } 00100 GINAC_BIND_UNARCHIVER(constant); 00101 00102 void constant::archive(archive_node &n) const 00103 { 00104 inherited::archive(n); 00105 n.add_string("name", name); 00106 } 00107 00109 // functions overriding virtual functions from base classes 00111 00112 // public 00113 00114 void constant::do_print(const print_context & c, unsigned level) const 00115 { 00116 c.s << name; 00117 } 00118 00119 void constant::do_print_tree(const print_tree & c, unsigned level) const 00120 { 00121 c.s << std::string(level, ' ') << name << " (" << class_name() << ")" << " @" << this 00122 << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec 00123 << std::endl; 00124 } 00125 00126 void constant::do_print_latex(const print_latex & c, unsigned level) const 00127 { 00128 c.s << TeX_name; 00129 } 00130 00131 void constant::do_print_python_repr(const print_python_repr & c, unsigned level) const 00132 { 00133 c.s << class_name() << "('" << name << "'"; 00134 if (TeX_name != "\\mathrm{" + name + "}") 00135 c.s << ",TeX_name='" << TeX_name << "'"; 00136 c.s << ')'; 00137 } 00138 00139 bool constant::info(unsigned inf) const 00140 { 00141 if (inf == info_flags::polynomial) 00142 return true; 00143 if (inf == info_flags::real) 00144 return domain==domain::real || domain==domain::positive ; 00145 if (inf==info_flags::positive || inf==info_flags::nonnegative) 00146 return domain == domain::positive; 00147 else 00148 return inherited::info(inf); 00149 } 00150 00151 ex constant::evalf(int level) const 00152 { 00153 if (ef!=0) { 00154 return ef(); 00155 } else { 00156 return number.evalf(); 00157 } 00158 return *this; 00159 } 00160 00161 bool constant::is_polynomial(const ex & var) const 00162 { 00163 return true; 00164 } 00165 00166 ex constant::conjugate() const 00167 { 00168 if ( domain==domain::real || domain==domain::positive ) 00169 return *this; 00170 return conjugate_function(*this).hold(); 00171 } 00172 00173 ex constant::real_part() const 00174 { 00175 if ( domain==domain::real || domain==domain::positive ) 00176 return *this; 00177 return real_part_function(*this).hold(); 00178 } 00179 00180 ex constant::imag_part() const 00181 { 00182 if ( domain==domain::real || domain==domain::positive ) 00183 return 0; 00184 return imag_part_function(*this).hold(); 00185 } 00186 00187 // protected 00188 00192 ex constant::derivative(const symbol & s) const 00193 { 00194 return _ex0; 00195 } 00196 00197 int constant::compare_same_type(const basic & other) const 00198 { 00199 GINAC_ASSERT(is_exactly_a<constant>(other)); 00200 const constant &o = static_cast<const constant &>(other); 00201 00202 if (serial == o.serial) 00203 return 0; 00204 else 00205 return serial < o.serial ? -1 : 1; 00206 } 00207 00208 bool constant::is_equal_same_type(const basic & other) const 00209 { 00210 GINAC_ASSERT(is_exactly_a<constant>(other)); 00211 const constant &o = static_cast<const constant &>(other); 00212 00213 return serial == o.serial; 00214 } 00215 00216 unsigned constant::calchash() const 00217 { 00218 const void* typeid_this = (const void*)typeid(*this).name(); 00219 hashvalue = golden_ratio_hash((p_int)typeid_this ^ serial); 00220 00221 setflag(status_flags::hash_calculated); 00222 00223 return hashvalue; 00224 } 00225 00227 // new virtual functions which can be overridden by derived classes 00229 00230 // none 00231 00233 // non-virtual functions in this class 00235 00236 // none 00237 00239 // static member variables 00241 00242 unsigned constant::next_serial = 0; 00243 00245 // global constants 00247 00249 const constant Pi("Pi", PiEvalf, "\\pi", domain::positive); 00250 00253 const constant Euler("Euler", EulerEvalf, "\\gamma_E", domain::positive); 00254 00256 const constant Catalan("Catalan", CatalanEvalf, "G", domain::positive); 00257 00258 } // namespace GiNaC