These are chat archives for symengine/symengine

12th
Nov 2015
Ondřej Čertík
@certik
Nov 12 2015 15:12
@rwst as @isuruf said, you have to create a wrapper, and if you subclass the wrapper from EnableRCPFromThis, then you can use our RCP. The Basic class is already subclassed from EnableRCPFromThis, so you can subclass from Basic as well.
Ralf Stephan
@rwst
Nov 12 2015 15:46
@certik You mean like this (inheritance vs containment)?
using piranha_poly = piranha::polynomial<piranha::rational,piranha::              monomial<short>>;

class rcp_enabled_pt : piranha_poly, EnableRCPFromThis<rcp_enabled_pt> 
{  
...
Ondřej Čertík
@certik
Nov 12 2015 17:56

@rwst not quite. What I had in mind is this:

class Polynomial: public Basic {
public:
    piranha_poly & get_piranha_polynomial() {
        return *p_;
    }
private:
    std::unique_ptr<piranha_poly> p_;
};

Then you can use this inside SymEngine expressions, and internally it dispatches everything to Piranha. There are multiple ways to make the above code safer (e.g. I really need to finish certik/trilinos#1, which will provide safe but fast Ptr access), since the above can segfault if you retain the reference to piranha_poly and the Polynomial goes out of scope. But that's besides the point here.

Probably the polynomial should be a constant polynomial, since symengine expression is constant, so perhaps it should be:

    const piranha_poly & get_piranha_polynomial() {
        return *p_;
    }

And the idea is that if somebody gives you this Polynomial, then you can use get_piranha_polynomial to get an access to the underlying Piranha type, and then write a very fast algorithm with it using Piranha only. Then once you get the result, you just wrap it up in another Polynomial and return to the user. That way we get both the speed, but can also use it with the rest of symengine.

Ondřej Čertík
@certik
Nov 12 2015 18:03
Specifically what you don't want to do is to let's say create a matrix of these Polynomial classes and then when using Gaussian elimination, create, destroy and reference count all the temporary Polynomial instances. That would be wasteful. We will support this out of the box, since Polynomial will be a subclass of Basic, so you can stick it into a matrix and call our Gaussian elimination on it. But it will be slow. Much faster implementation should have a specialized Matrix type, which operates on the Piranha type directly, and then only wraps the result back to the user. And with get_piranha_polynomial(), we can implement this specialized faster version later.
So that's what I had in mind. Perhaps there is a better design. @rwst let me know.

When thinking about it, it should probably be just this:

class Polynomial: public Basic {
public:
    const piranha_poly & get_piranha_polynomial() {
        return p_;
    }
private:
    piranha_poly p_;
};

Which will be a lot faster, since there is no heap allocation/deallocation in std::unique_ptr. But not safe, but my other work in progress improvement Viewable (certik/trilinos#2) will be as fast (=stack allocated in Release mode), but 100% safe in Debug mode.

@bluescarni do you think that's a good design?
Francesco Biscani
@bluescarni
Nov 12 2015 20:36
@certik looks good to me, I was about to ask about the need for unique_ptr but you addressed that already :)
I must say that I have never run in practice into cases in which I need to be particularly careful about the lifetime of references, but I am used to work almost exclusively with value semantics, so I probably have a bias there
Ralf Stephan
@rwst
Nov 12 2015 21:05
@certik @bluescarni But if I make the wrapper contain a Piranha polynomial (instead of deriving from it) I need to duplicate the whole interface of polynomial in that class. Not sure if I want that.