|
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 "fderivative.h" 00024 #include "operators.h" 00025 #include "archive.h" 00026 #include "utils.h" 00027 00028 #include <iostream> 00029 00030 namespace GiNaC { 00031 00032 GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(fderivative, function, 00033 print_func<print_context>(&fderivative::do_print). 00034 print_func<print_csrc>(&fderivative::do_print_csrc). 00035 print_func<print_tree>(&fderivative::do_print_tree)) 00036 00037 00038 // default constructor 00040 00041 fderivative::fderivative() 00042 { 00043 } 00044 00046 // other constructors 00048 00049 fderivative::fderivative(unsigned ser, unsigned param, const exvector & args) : function(ser, args) 00050 { 00051 parameter_set.insert(param); 00052 } 00053 00054 fderivative::fderivative(unsigned ser, const paramset & params, const exvector & args) : function(ser, args), parameter_set(params) 00055 { 00056 } 00057 00058 fderivative::fderivative(unsigned ser, const paramset & params, std::auto_ptr<exvector> vp) : function(ser, vp), parameter_set(params) 00059 { 00060 } 00061 00063 // archiving 00065 00066 void fderivative::read_archive(const archive_node& n, lst& sym_lst) 00067 { 00068 inherited::read_archive(n, sym_lst); 00069 unsigned i = 0; 00070 while (true) { 00071 unsigned u; 00072 if (n.find_unsigned("param", u, i)) 00073 parameter_set.insert(u); 00074 else 00075 break; 00076 ++i; 00077 } 00078 } 00079 GINAC_BIND_UNARCHIVER(fderivative); 00080 00081 void fderivative::archive(archive_node &n) const 00082 { 00083 inherited::archive(n); 00084 paramset::const_iterator i = parameter_set.begin(), end = parameter_set.end(); 00085 while (i != end) { 00086 n.add_unsigned("param", *i); 00087 ++i; 00088 } 00089 } 00090 00091 00093 // functions overriding virtual functions from base classes 00095 00096 void fderivative::print(const print_context & c, unsigned level) const 00097 { 00098 // class function overrides print(), but we don't want that 00099 basic::print(c, level); 00100 } 00101 00102 void fderivative::do_print(const print_context & c, unsigned level) const 00103 { 00104 c.s << "D["; 00105 paramset::const_iterator i = parameter_set.begin(), end = parameter_set.end(); 00106 --end; 00107 while (i != end) { 00108 c.s << *i++ << ","; 00109 } 00110 c.s << *i << "](" << registered_functions()[serial].name << ")"; 00111 printseq(c, '(', ',', ')', exprseq::precedence(), function::precedence()); 00112 } 00113 00114 void fderivative::do_print_csrc(const print_csrc & c, unsigned level) const 00115 { 00116 c.s << "D_"; 00117 paramset::const_iterator i = parameter_set.begin(), end = parameter_set.end(); 00118 --end; 00119 while (i != end) 00120 c.s << *i++ << "_"; 00121 c.s << *i << "_" << registered_functions()[serial].name; 00122 printseq(c, '(', ',', ')', exprseq::precedence(), function::precedence()); 00123 } 00124 00125 void fderivative::do_print_tree(const print_tree & c, unsigned level) const 00126 { 00127 c.s << std::string(level, ' ') << class_name() << " " 00128 << registered_functions()[serial].name << " @" << this 00129 << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec 00130 << ", nops=" << nops() 00131 << ", params="; 00132 paramset::const_iterator i = parameter_set.begin(), end = parameter_set.end(); 00133 --end; 00134 while (i != end) 00135 c.s << *i++ << ","; 00136 c.s << *i << std::endl; 00137 for (size_t i=0; i<seq.size(); ++i) 00138 seq[i].print(c, level + c.delta_indent); 00139 c.s << std::string(level + c.delta_indent, ' ') << "=====" << std::endl; 00140 } 00141 00142 ex fderivative::eval(int level) const 00143 { 00144 if (level > 1) { 00145 // first evaluate children, then we will end up here again 00146 return fderivative(serial, parameter_set, evalchildren(level)); 00147 } 00148 00149 // No parameters specified? Then return the function itself 00150 if (parameter_set.empty()) 00151 return function(serial, seq); 00152 00153 // If the function in question actually has a derivative, return it 00154 if (registered_functions()[serial].has_derivative() && parameter_set.size() == 1) 00155 return pderivative(*(parameter_set.begin())); 00156 00157 return this->hold(); 00158 } 00159 00162 ex fderivative::evalf(int level) const 00163 { 00164 return basic::evalf(level); 00165 } 00166 00169 ex fderivative::series(const relational & r, int order, unsigned options) const 00170 { 00171 return basic::series(r, order, options); 00172 } 00173 00174 ex fderivative::thiscontainer(const exvector & v) const 00175 { 00176 return fderivative(serial, parameter_set, v); 00177 } 00178 00179 ex fderivative::thiscontainer(std::auto_ptr<exvector> vp) const 00180 { 00181 return fderivative(serial, parameter_set, vp); 00182 } 00183 00186 ex fderivative::derivative(const symbol & s) const 00187 { 00188 ex result; 00189 for (size_t i=0; i<seq.size(); i++) { 00190 ex arg_diff = seq[i].diff(s); 00191 if (!arg_diff.is_zero()) { 00192 paramset ps = parameter_set; 00193 ps.insert(i); 00194 result += arg_diff * fderivative(serial, ps, seq); 00195 } 00196 } 00197 return result; 00198 } 00199 00200 int fderivative::compare_same_type(const basic & other) const 00201 { 00202 GINAC_ASSERT(is_a<fderivative>(other)); 00203 const fderivative & o = static_cast<const fderivative &>(other); 00204 00205 if (parameter_set != o.parameter_set) 00206 return parameter_set < o.parameter_set ? -1 : 1; 00207 else 00208 return inherited::compare_same_type(o); 00209 } 00210 00211 bool fderivative::is_equal_same_type(const basic & other) const 00212 { 00213 GINAC_ASSERT(is_a<fderivative>(other)); 00214 const fderivative & o = static_cast<const fderivative &>(other); 00215 00216 if (parameter_set != o.parameter_set) 00217 return false; 00218 else 00219 return inherited::is_equal_same_type(o); 00220 } 00221 00222 bool fderivative::match_same_type(const basic & other) const 00223 { 00224 GINAC_ASSERT(is_a<fderivative>(other)); 00225 const fderivative & o = static_cast<const fderivative &>(other); 00226 00227 return parameter_set == o.parameter_set && inherited::match_same_type(other); 00228 } 00229 00230 } // namespace GiNaC