// Things concerning curve_param's and surface_param's #ifndef _qi_param_struct_h_ #define _qi_param_struct_h_ /** RPL */ #include #include #include #include /** QI */ #include using namespace std; using namespace rpl; // Enter namespace QI namespace QI { // Template class for curve parameterizations, i.e. vectors of homogeneous // polynomials with bigint coefficients template class curve_param : public math_vector < hom_polynomial > { public: // Warning: math_vector is public virtual math_vector< T > - so get everything // directly from math_vector // Default constructor curve_param() : math_vector < hom_polynomial > (4,4) { } // Create a curve_param of size a curve_param(const rpl_size_t &a) : math_vector < hom_polynomial > (a,a) { } // Create a curve_param from a vector curve_param(const math_vector &v) : math_vector < hom_polynomial > (v.capacity(),v.capacity()) { for (rpl_size_t i = 0; i < v.capacity(); i++) this->operator[](i).assign((hom_polynomial )v[i]); } // Parameterize the line through two points curve_param(const math_vector &p1, const math_vector &p2); // Copy constructor curve_param(const curve_param &a): math_vector < hom_polynomial > (a.capacity(),a.capacity()) { this->assign(a); } // Destructor ~curve_param() { } // Copy assignment curve_param & operator = (const curve_param &a) { if (this != &a) // Beware of self-assignment this->assign(a); return *this; } // Methods // Pretty printing void print_verbose(ostream &s, const char x = 'u', const char y = 'v') const; // Evaluate a curve_param at a point math_vector eval(const T &a, const T &b) const; // Arithmetic operations // Multiply a curve_param by a polynomial void multiply(const curve_param &a, const hom_polynomial &b); // Divide a curve_param by a polynomial void divide(const curve_param &a, const hom_polynomial &b); // Divide a curve_param by a constant void divide(const curve_param &a, const T &b); // Multiply a matrix by a curve_param void multiply(const math_matrix &a, const curve_param &b); // Partial derivative of this curve param void derivative(const curve_param &a, const char v); // typedefs for iterators typedef typename math_vector >::iterator iterator; typedef typename math_vector >::const_iterator const_iterator; }; /////////////////////// Member functions for curve_param // Parameterize the line through two points template curve_param ::curve_param(const math_vector &p1, const math_vector &p2) : math_vector < hom_polynomial > (p1.capacity(),p1.capacity()) { // Polynomial 'x' hom_polynomial polx; polx.assign_x(); curve_param l1(p1); l1.multiply(l1,polx); // Polynomial 'y' hom_polynomial poly; poly.assign_y(); curve_param l2(p2); l2.multiply(l2,poly); this->add(l1, l2); } // Pretty printing of param template void curve_param ::print_verbose(ostream &s, const char x, const char y) const { s << "["; for (rpl_size_t i = 0; i < this->capacity(); i++) { this->operator[](i).print_verbose(s,x,y); if (i != this->capacity()-1) s << ", "; } s << "]"; } // Evaluate a curve_param at a point template math_vector curve_param ::eval(const T &a, const T &b) const { math_vector tmp(this->size(),this->size()); hom_polynomial t; for (size_t i = 0; i < this->size(); i++) { t = this->operator[](i); tmp[i] = t.eval(a,b); } return tmp; } // Multiply a curve_param by a polynomial template void curve_param ::multiply(const curve_param &a, const hom_polynomial &b) { BOOST_AUTO(cp, this->begin()); BOOST_AUTO(ap, a.begin()); for (rpl_size_t i = 0; i < a.capacity(); i++, cp++, ap++) QI::multiply(*cp,*ap,b); } // Divide a curve_param by a constant template void curve_param ::divide(const curve_param &a, const T &b) { // No cast is used because division by a polynomial is Euclidean BOOST_AUTO(cp, this->begin()); BOOST_AUTO(ap, a.begin()); for (rpl_size_t i = 0; i < a.capacity(); i++, cp++, ap++) QI::divide(*cp,*ap,b); } // Multiply a matrix by a curve_param template void curve_param ::multiply(const math_matrix &a, const curve_param &b) { BOOST_AUTO(cp, this->begin()); hom_polynomial tmp; // Making a copy will make things easier curve_param b_cp = b; for (size_t i = 0; i < a.get_no_of_rows(); i++, cp++) { BOOST_AUTO(bp, b_cp.begin()); for (size_t j = 0; j < a.get_no_of_columns(); j++, bp++) if (j == 0) QI::multiply(*cp,*bp,a(i,0)); else { QI::multiply(tmp,*bp,a(i,j)); QI::add(*cp,*cp,tmp); } } } // Partial derivative of this curve param template void curve_param ::derivative(const curve_param &a, const char v) { BOOST_AUTO(cp, this->begin()); BOOST_AUTO(ap, a.begin()); for (rpl_size_t i = 0; i < a.capacity(); i++, cp++, ap++ ) cp->derivative(*ap, v); } /////////////////////// Functions for curve_param // Overloading of cout template inline ostream & operator << (ostream &s, const curve_param &a) { a.print_verbose(s); return s; } // Negating a curve_param template inline curve_param operator - (const curve_param &a) { curve_param c(a.capacity()); for (rpl_size_t i = 0; i < a.capacity(); i++) c[i].negate(a[i]); return c; } // Multiply a curve_param by a polynomial template inline void multiply(curve_param &c, const curve_param &a, const hom_polynomial &b) { c.multiply(a,b); } // Multiply a curve_param by a constant template inline void multiply(curve_param &c, const curve_param &a, const T &b) { c.multiply(a,(hom_polynomial )b); } // Multiply a vector by a polynomial to give a curve_param template inline void multiply(curve_param &c, const math_vector &a, const hom_polynomial &b) { c.multiply((curve_param )a,b); } // Divide a curve_param by a polynomial template inline void divide(curve_param &c, const curve_param &a, const hom_polynomial &b) { c.divide(a,b); } // Divide a curve_param by a constant template inline void divide(curve_param &c, const curve_param &a, const T &b) { c.divide(a,b); } // Multiply a vector by a constant to give a curve_param template inline void multiply(curve_param &c, const math_vector &a, const T &b) { c.multiply((curve_param )a,(hom_polynomial )b); } // Multiply a matrix by a curve_param template inline void multiply(curve_param &c, const math_matrix &a, const curve_param &b) { c.multiply(a,b); } // Multiply two curve params template inline void multiply(hom_polynomial &c, const curve_param &a, const curve_param &b) { hom_polynomial tmp; multiply(c,a[0],b[0]); for (rpl_size_t i = 1; i < a.capacity(); i++) { multiply(tmp,a[i],b[i]); add(c,c,tmp); } } // Add two curve params template inline void add(curve_param &c, const curve_param &a, const curve_param &b) { for (rpl_size_t i = 0; i < a.capacity(); i++) QI::add(c[i],a[i],b[i]); } // Negate a curve param template inline void negate(curve_param &a, const curve_param &b) { rpl::negate(a,b); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // Template class for surface parameterizations, i.e. vectors of homogeneous // polynomials whose coefficients are homogeneous coefficients template class surface_param : public math_vector < hom_hom_polynomial > { public: // Constructors // Default surface_param(): math_vector < hom_hom_polynomial > (4,4) { } // Create a surface_param of size a surface_param(const rpl_size_t &a): math_vector < hom_hom_polynomial > (a,a) { } // Copy constructor surface_param(const surface_param &a): math_vector < hom_hom_polynomial > (a.capacity(),a.capacity()) { this->assign(a); } // Destructor ~surface_param() { } // Copy assignment surface_param & operator = (const surface_param &a) { if (this != &a) // Beware of self-assignment this->assign(a); return *this; } // Methods // Pretty printing - (x,y) are the main variables, (z,w) are for the // (polynomial) coefficients of the monomials void print_verbose(ostream &s, const char x = 'u', const char y = 'v', const char z = 's', const char w = 't') const; // Evaluate a surface_param at a point // ie, each coordinate of surface_param which is a hom_hom_polynomial // is evaluated as a homogeneous polynomial at (a,b) curve_param eval(const hom_polynomial &a, const hom_polynomial &b) const; // Arithmetic operations // Multiply a curve_param by a polynomial to give a surface_param void multiply(const curve_param &a, const hom_polynomial &b); // Multiply a matrix by a surface_param void multiply(const math_matrix &a, const surface_param &b); // Known functions friend void hom_hom_polynomial ::print_verbose(ostream &s, const char x, const char y, const char z, const char w) const; }; /////////////////////// Member functions for surface_param // Pretty printing template void surface_param ::print_verbose(ostream &s, const char x, const char y, const char z, const char w) const { s << "["; for (rpl_size_t i = 0; i < this->capacity(); i++) { this->operator[](i).print_verbose(s,x,y,z,w); if (i != this->capacity()-1) s << ", "; } s << "]"; } // Evaluate a surface_param at a point // ie, each coordinate of surface_param which is a hom_hom_polynomial // is evaluated as a homogeneous polynomial at (a,b) template curve_param surface_param ::eval(const hom_polynomial &a, const hom_polynomial &b) const { curve_param tmp(this->capacity()); hom_hom_polynomial t; for (rpl_size_t i = 0; i < this->capacity(); i++) { t = this->operator[](i); tmp[i] = t.eval(a,b); } return tmp; } // Multiply the coefficients of a curve_param by a polynomial template void surface_param ::multiply(const curve_param &a, const hom_polynomial &b) { BOOST_AUTO(cp, this->begin()); for (rpl_size_t i = 0; i < a.capacity(); i++, cp++) { if (a[i].is_zero()) (*cp).set_degree(-1); else { (*cp).set_degree(b.degree()); for (rpl_size_t j = 0; j <= b.degree(); j++) QI::multiply((*cp)[j],a[i],b[j]); } } } // Multiply a matrix by a surface_param template void surface_param ::multiply(const math_matrix &a, const surface_param &b) { BOOST_AUTO(cp, this->begin()); hom_hom_polynomial tmp; // Making a copy will make things easier surface_param b_cp = b; for (size_t i = 0; i < a.get_no_of_rows(); i++, cp++) { BOOST_AUTO(bp,b_cp.begin()); for (size_t j = 0; j < a.get_no_of_columns(); j++, bp++) if (j == 0) QI::multiply(*cp,*bp,a(i,0)); else { QI::multiply(tmp,*bp,a(i,j)); QI::add(*cp,*cp,tmp); } } } /////////////////////// Functions for surface_param // Overloading of cout template inline ostream & operator << (ostream &s, const surface_param &a) { a.print_verbose(s); return s; } // Multiply a curve_param by a polynomial to give a surface_param template inline void multiply(surface_param &c, const curve_param &a, const hom_polynomial &b) { c.multiply(a,b); } // Multiply a matrix by a surface_param template inline void multiply(surface_param &c, const math_matrix &a, const surface_param &b) { c.multiply(a,b); } // Multiply a vector by a surface_param /*template inline void multiply(surface_param &c, const math_vector &a, const surface_param &b) { c.multiply((math_matrix )a,b); }*/ // Exchange (u,v) and (s,t) in a surface param template inline surface_param exchange_uv_st(const surface_param &a) { surface_param tmp(a.capacity()); for (rpl_size_t i = 0; i < a.capacity(); i++) tmp[i] = exchange_uv_st(a[i]); return tmp; } // Multiply two surface params template inline void multiply(hom_hom_polynomial &c, const surface_param &a, const surface_param &b) { hom_hom_polynomial tmp; multiply(c,a[0],b[0]); for (size_t i = 1; i < 4; i++) { QI::multiply(tmp,a[i],b[i]); QI::add(c,c,tmp); } } // Add two surface params template inline void add(surface_param &c, const surface_param &a, const surface_param &b) { for (rpl_size_t i = 0; i < 4; i++) QI::add(c[i],a[i],b[i]); } } // end of namespace QI #endif