Re: Symbolic manipulation
On May 22, 9:53 pm, Jon Harrop <j...@ffconsultancy.com> wrote:
Can anyone improve this C++ program so that it can compete with the other
languages:
http://www.codecodex.com/wiki/index.php?title=Derivative
Here is one. It does not leaks, is exception safe
and prints prettier result.
#include <string>
#include <iostream>
#include <ostream>
using namespace std;
template <class T>
class Ref{
public:
explicit Ref(T* ref):ref_(ref),count_(new int(1)){}
Ref(const Ref& in)
:ref_(in.ref_),count_(in.count_)
{
Add();
}
Ref&operator=(const Ref& in)
{
if(&in!=this)
{
Release();
count_ = in.count_;
ref_ = in.ref_;
Add();
}
return *this;
}
T* operator ->()const{ return ref_; }
T& operator *()const{ return *ref_; }
~Ref(){ Release(); }
void Release()
{
--*count_;
if(*count_==0)
{
delete ref_;
delete count_;
}
}
void Add(){ ++*count_; }
private:
T* ref_;
int* count_;
};
class Op{
public:
// could be any shared ptr
typedef const Ref<const Op> Ptr_t;
virtual string eval()const=0;
virtual Ptr_t d(const string&)const=0;
virtual ~Op(){}
};
class BinaryOp:public Op{
protected:
BinaryOp(Ptr_t lhs,Ptr_t rhs):left_(lhs),right_(rhs){}
static string smul(const string&lhs,const string&rhs)
{
if(lhs == "0" || rhs == "0")return "0";
else if(lhs == "1")return rhs;
else if(rhs == "1")return lhs;
else return string ("(") + lhs+"*"+rhs + ")";
}
static string sadd(const string& lhs,const string& rhs)
{
if(lhs == "0")return rhs;
else if(rhs == "0")return lhs;
else return string ("(")+lhs+"+"+rhs+")";
}
Ptr_t left_,right_;
};
class Add:public BinaryOp{
public:
Add(Ptr_t lhs,Ptr_t rhs):BinaryOp(lhs,rhs){}
string eval()const
{
return sadd(left_->eval(),right_->eval());
}
Ptr_t d(const string& x)const
{
return Ptr_t(new Add(left_->d(x),right_->d(x)));
}
};
class Mul:public BinaryOp{
public:
Mul(Ptr_t lhs,Ptr_t rhs):BinaryOp(lhs,rhs){}
string eval()const
{
return smul(left_->eval(),right_->eval());
}
Ptr_t d(const string& x)const
{
Ptr_t left(new Mul(left_,right_->d(x)));
Ptr_t right(new Mul(left_->d(x), right_));
return Ptr_t(new Add(left,right));
}
};
class Var:public Op,private string{
public:
Var(const string& x = ""):string(x){}
string eval()const{ return *this; }
Ptr_t d(const string& x)const
{
return Ptr_t(new Var(x==*this?"1":"0"));
}
};
typedef Op::Ptr_t Ptr_t;
Ptr_t operator + (Ptr_t lhs,Ptr_t rhs)
{
return Ptr_t(new Add(lhs,rhs));
}
Ptr_t operator * (Ptr_t lhs,Ptr_t rhs)
{
return Ptr_t(new Mul(lhs,rhs));
}
int main()
{
Ptr_t x(new Var("x")),
a(new Var("a")),
b(new Var("b")),
c(new Var("c"));
Ptr_t expr = a * x * x + b * x + c;
cout <<expr->eval()<<' '<<expr->d("x")->eval()<<'\n';
return 0;
}
Greetings, Branimir.