Hi,
here is a short example code to demonstrate the changes I plan to make
to GiNaC's function system (like discussed in November on this list).
- every function is now a C++ class derived from class function (here
still called newfunction to avoid name clashes).
- the 14 functions already present in the standard C library have a
special naming convention (here _ginac is appended to the class name)
and supporting C functions for creation.
- the definition of the functions is rather long, but will be made more
comfortable with the help of new macros like GINAC_DECLARE_FUNCTION ...
(not included here yet).
Comments?
Regards,
Jens
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <cmath>
#include <ginac/ginac.h>
namespace GiNaC {
////////////////////////////////////////////////////////////////////////////////
class newfunction : public exprseq
{
GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(newfunction, exprseq)
virtual newfunction* duplicate() const { return new newfunction(*this); }
virtual void accept(GiNaC::visitor& v) const
{
if (visitor* p = dynamic_cast<visitor*>(&v)) {
p->visit(*this);
} else {
inherited::accept(v);
}
}
protected:
virtual int compare_same_type(const basic& other) const { return exprseq::compare_same_type(other); }
virtual bool is_equal_same_type(const basic& other) const { return exprseq::compare_same_type(other); }
public:
virtual void print(const print_context& c, unsigned level = 0) const;
public:
newfunction(tinfo_t ti) { tinfo_key = ti; }
newfunction(tinfo_t ti, const ex& x1) : inherited(x1) { tinfo_key = ti; }
newfunction(tinfo_t ti, const ex& x1, const ex& x2) : inherited(x1, x2) { tinfo_key = ti; }
newfunction(tinfo_t ti, const ex& x1, const ex& x2, const ex& x3) : inherited(x1, x2, x3) { tinfo_key = ti; }
// ...
};
GINAC_IMPLEMENT_REGISTERED_CLASS(newfunction, exprseq)
newfunction::newfunction(const GiNaC::archive_node& n, GiNaC::lst& sym_lst) : inherited(n, sym_lst) { }
void newfunction::archive(GiNaC::archive_node& n) const
{
inherited::archive(n);
}
GiNaC::ex newfunction::unarchive(const GiNaC::archive_node& n, GiNaC::lst& sym_lst)
{
return (new newfunction(n, sym_lst))->setflag(status_flags::dynallocated);
}
void newfunction::print(const print_context& c, unsigned level) const
{
const std::vector<print_functor>& pdt = get_class_info().options.get_print_dispatch_table();
unsigned id = c.get_class_info().options.get_id();
if (id >= pdt.size() || !(pdt[id].is_valid())) {
if (is_a<print_tree>(c)) {
c.s << std::string(level, ' ') << class_name()
<< " @" << this
<< std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
<< ", nops=" << nops()
<< std::endl;
unsigned delta_indent = static_cast<const print_tree&>(c).delta_indent;
for (size_t i=0; i<seq.size(); ++i) {
seq[i].print(c, level + delta_indent);
}
c.s << std::string(level + delta_indent, ' ') << "=====" << std::endl;
} else if (is_a<print_latex>(c)) {
c.s << "\\mbox{" << class_name() << "}";
inherited::do_print(c,level);
} else {
c.s << class_name();
inherited::do_print(c,level);
}
} else {
pdt[id](*this, c, level);
}
}
////////////////////////////////////////////////////////////////////////////////
class polylog : public newfunction
{
// a new GINAC_DECLARE_FUNCTION macro will replace this
GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(polylog, newfunction)
// will be part of GINAC_DECLARE_FUNCTION macro
virtual polylog* duplicate() const { return new polylog(*this); }
// will be part of GINAC_DECLARE_FUNCTION macro
virtual void accept(GiNaC::visitor& v) const
{
if (visitor* p = dynamic_cast<visitor*>(&v)) {
p->visit(*this);
} else {
inherited::accept(v);
}
}
public:
polylog(const ex& x1, const ex& x2) : inherited(&polylog::tinfo_static, x1, x2) { }
protected:
void do_print_latex(const print_context& c, unsigned level) const;
public:
virtual ex eval(int level = 0) const;
};
GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(polylog, exprseq,
print_func<print_latex>(&polylog::do_print_latex))
// will be part of GINAC_IMPLEMENT_FUNCTION macro
polylog::polylog(const GiNaC::archive_node& n, GiNaC::lst& sym_lst) : inherited(n, sym_lst) { }
// will be part of GINAC_IMPLEMENT_FUNCTION macro
void polylog::archive(GiNaC::archive_node& n) const
{
inherited::archive(n);
}
// will be part of GINAC_IMPLEMENT_FUNCTION macro
GiNaC::ex polylog::unarchive(const GiNaC::archive_node& n, GiNaC::lst& sym_lst)
{
return (new polylog(n, sym_lst))->setflag(status_flags::dynallocated);
}
void polylog::do_print_latex(const print_context& c, unsigned level) const
{
c.s << "\\mbox{Li}";
inherited::do_print(c,level);
}
ex polylog::eval(int level) const
{
if (op(0).is_equal(1)) {
return zeta(op(1));
} else {
return this->hold();
}
}
////////////////////////////////////////////////////////////////////////////////
class log10_ginac : public newfunction
{
GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(log10_ginac, newfunction)
virtual log10_ginac* duplicate() const { return new log10_ginac(*this); }
virtual void accept(GiNaC::visitor& v) const
{
if (visitor* p = dynamic_cast<visitor*>(&v)) {
p->visit(*this);
} else {
inherited::accept(v);
}
}
public:
log10_ginac(const ex& x) : inherited(&log10_ginac::tinfo_static, x) { }
protected:
void do_print(const print_context& c, unsigned level) const;
void do_print_latex(const print_context& c, unsigned level) const;
public:
virtual ex eval(int level = 0) const;
};
GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(log10_ginac, newfunction,
print_func<print_dflt>(&log10_ginac::do_print).
print_func<print_latex>(&log10_ginac::do_print_latex))
log10_ginac::log10_ginac(const GiNaC::archive_node& n, GiNaC::lst& sym_lst) : inherited(n, sym_lst) { }
void log10_ginac::archive(GiNaC::archive_node& n) const
{
inherited::archive(n);
}
GiNaC::ex log10_ginac::unarchive(const GiNaC::archive_node& n, GiNaC::lst& sym_lst)
{
return (new log10_ginac(n, sym_lst))->setflag(status_flags::dynallocated);
}
void log10_ginac::do_print(const print_context& c, unsigned level) const
{
std::string classname(class_name());
c.s << classname.erase(classname.find("_ginac",0),6);
inherited::do_print(c,level);
}
void log10_ginac::do_print_latex(const print_context& c, unsigned level) const
{
c.s << "\\log";
inherited::do_print(c,level);
}
ex log10_ginac::eval(int level) const
{
if (op(0).is_equal(0)) {
return 666;
} else {
return this->hold();
}
}
template<typename T1> const GiNaC::log10_ginac log10(const T1& x) { return log10_ginac(x); }
const GiNaC::log10_ginac log10(double x) { return log10_ginac(x); }
const GiNaC::log10_ginac log10(float x) { return log10_ginac(x); }
////////////////////////////////////////////////////////////////////////////////
} // namespace GiNaC
//using namespace std;
using namespace GiNaC;
int main()
{
try {
symbol x("x");
ex r1 = polylog(x,3) + polylog(1,3) + 6*GiNaC::log10(3.0f) - log10(x);
std::cout << dflt << r1 << std::endl;
std::cout << tree << r1 << std::endl;
std::cout << latex << r1 << std::endl;
}
catch (const std::exception& e) {
std::cout << e.what() << std::endl;
}
return 0;
}