Dear All, In my GiNaC code I oftenly use some objects which have special properties with respect to power. For example, if values of a symbol s are assumed to be only -1, 0, or 1, then s^3=s. Another example is provided by "imaginary units" for double and dual numbers. It will be good for such objects to use such simplifying identities on the fly in power_eval() method rather then by user calls to subs() afterwards. I propose a patch to GiNaC which allows to supply such simplification rules from a user-defined classes. It requires only two new virtual methods to basic class and should not involve much overheads to the general GiNaC performance. I give an example below (which should work with the patch) for a symbol which is assumed to take only values -1 or 1, thus satisfying to s^2=1 rule. If general feeling toward this proposition will be positive I would send a more complete patch including documentation. Best wishes, Vladimir PS Somehow I was not able to use macros DEFAULT_UNARCHIVE() and DEFAULT_COMPARE() for my class, since compiler produces the error: error: expected constructor, destructor, or type conversion before 'int' What may be the reason for this? -- Vladimir V. Kisil email: kisilv@maths.leeds.ac.uk -- www: http://maths.leeds.ac.uk/~kisilv/ #include <iostream> #include <stdexcept> #include <ginac/ginac.h> using namespace std; using namespace GiNaC; class myrealsymb : public symbol { GINAC_DECLARE_REGISTERED_CLASS(myrealsymb, symbol) public: myrealsymb(const std::string & initname); virtual ex eval_power_basis(const ex & exp) const; virtual bool info(unsigned inf) const; }; GINAC_IMPLEMENT_REGISTERED_CLASS(myrealsymb,symbol) myrealsymb::myrealsymb(): symbol(){}; myrealsymb::myrealsymb(const std::string & initname) : symbol(initname) {;} ex myrealsymb::eval_power_basis(const ex & exp) const { if (is_a<numeric>(exp)) { if (ex_to<numeric>(exp).is_even()) return numeric(1); if (ex_to<numeric>(exp).is_odd()) return *this; } return power(*this,exp).hold(); } bool myrealsymb::info(unsigned inf) const { return (inf == info_flags::is_power_basis) || symbol::info(inf); } myrealsymb::myrealsymb(const archive_node &n, lst &sym_lst) : inherited(n, sym_lst) { } void myrealsymb::archive(archive_node &n) const { symbol::archive(n); } ex myrealsymb::unarchive(const archive_node &n, lst &sym_lst) { return (new myrealsymb(n, sym_lst))->symbol::setflag(status_flags::dynallocated); } int myrealsymb::compare_same_type(const basic & other) const { return symbol::compare_same_type(other); } int main(){ try { ex e=myrealsymb("s"); cout << pow(e,2) << endl; // -> 1 cout << pow(1+e,2).expand() << endl; // -> 2+2*s } catch (exception &p) { cerr << "Got problem: " << p.what() << endl; } return 0; }