GiNaC  1.6.2
fderivative.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 "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

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