c++ - constexpr class with array constructor methods -


i trying write compile time class multivariate polynomials (i.e. p(x,y,z) = x^2 + xyz + yz, don't worry mathematics here):

template<int dim, int degree> class polynomial {   public:     constexpr polynomial(std::array<double,nbofcoeffs(dim,degree)> arr): coeffs(arr) {}        constexpr double eval(std::array<double,dim> x);     constexpr operator+,-,*,/ ...   private:     std::array<double,nbofcoeffs(dim,degree)> coeffs; //don't worry "nbofcoeffs" : constexpr , computes @ compile time right number of coefficients.  }  int main () {     polynomial<2,2> p({{1.,1.,1.,1.,1.,1.}}); // p(x,y) = x^2+xy+y^2+x+y+1      double x = p.eval(1.);     auto p2 = p*p; } 

so far no big problem implement this. however, note ctor can bit cumbersome : how initialize 3rd degree trivariate polynomial p(x,y,z) = xyz ? have

polynomial<3,3> p({{0.,0.,0.,0.,0.,1.,0.,0.,0.,0.}});

with position of non-zero monomial depending on store it. nice if write :

  polynomial<3,3> p("xyz");     polynomial<4,3> p("x1x2x3 + x4^2"); //more general  

the idea create sort of small dst handle string representation of polynomials.

however, if that, once string parsed, don't know how assign values elements of storing array: must done body of ctor remaining empty (because want constexpr). think of ? possible ? should change array sort of recurring structure (because in case, think really, complex)

an example of how implement luc danton's approach:

#include <cstddef> #include <iostream>  namespace polynomials {     // it's possible store exponent data member instead     template < std::size_t t_id, std::size_t t_exponent = 1 >     struct monomial     {         static constexpr std::size_t id = t_id;         static constexpr std::size_t exponent = t_exponent;          // it's not possible store coefficient         // non-type template parameter (floating-point..)         double coefficient;          explicit constexpr monomial(double p_coefficient = 1.0)             : coefficient{ p_coefficient }         {}          void print() const         {             std::cout << coefficient << "x" << t_id << "^" << t_exponent;         }     };      // create monomial objects (like std::placeholders::_1)     constexpr monomial<0> x;     constexpr monomial<1> y;     constexpr monomial<2> z;      constexpr monomial<4> x0;     constexpr monomial<5> x1;     // ... can use macros produce lot of them..      // multiply arithmetic type (double, int, ..) monomial     template < typename t_arithmetic,                std::size_t t_id, std::size_t t_exponent0 >     constexpr auto operator*(t_arithmetic c, monomial < t_id, t_exponent0 > m0)     -> monomial < t_id, t_exponent0 >     {         return monomial < t_id, t_exponent0 >{c * m0.coefficient};     }     // other way 'round     template < typename t_arithmetic,                std::size_t t_id, std::size_t t_exponent0 >     constexpr auto operator*(monomial < t_id, t_exponent0 > m0, t_arithmetic c)     -> monomial < t_id, t_exponent0 >     {         return c * m0;     }      // multiply 2 monomials same id     template < std::size_t t_id,                std::size_t t_exponent0, std::size_t t_exponent1 >     constexpr auto operator*(monomial < t_id, t_exponent0 > m0,                              monomial < t_id, t_exponent1 > m1)     -> monomial < t_id, t_exponent0 + t_exponent1 >     {         return monomial<t_id, t_exponent0 + t_exponent1>                 {m0.coefficient * m1.coefficient};     }       // storage type multiple different monomials     template < typename... t_monomials >     struct polynomial     {         void print() const         {}     };         template < typename t_monomial, typename... tt_monomials >         struct polynomial < t_monomial, tt_monomials... >             : public polynomial < tt_monomials... >         {             using base = polynomial < tt_monomials... >;              t_monomial m;             constexpr polynomial(t_monomial p, tt_monomials... pp)                 : base(pp...)                 , m{p}             {}              void print() const             {                 m.print();                 std::cout << "*";                 base::print();             }         };      // multiply 2 monomials polynomial     template < std::size_t t_id0, std::size_t t_id1,                std::size_t t_exponent0, std::size_t t_exponent1 >     constexpr auto operator*( monomial < t_id0, t_exponent0 > m0,                               monomial < t_id1, t_exponent1 > m1)     -> polynomial < monomial<t_id0, t_exponent0>,                     monomial<t_id1, t_exponent1> >     {         return {m0, m1};     }      // still (and more complicated):     // - multiply 2 polynomials     // - multiply polynomial , monomial     // - addition, subtraction, division (?) etc. } 

usage example:

int main() {     using namespace polynomials;      auto p0 = 1.25*x*x;     p0.print();     std::cout << std::endl;      auto p1 = p0 * 5*y;     p1.print();     std::cout << std::endl; } 

Comments

Popular posts from this blog

SPSS keyboard combination alters encoding -

Add new record to the table by click on the button in Microsoft Access -

javascript - jQuery .height() return 0 when visible but non-0 when hidden -