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.