Home | Doxygen Documentation | Tutorials | Developer Tools (restricted)

basics/vectorsMatrices.hh
Go to the documentation of this file.
00001 /* vectors and matrices for 2D and 3D
00002 */
00003 
00004 #ifndef vectMatr_hh
00005 #define vectMatr_hh
00006 
00007 #include <iostream>
00008 #include <cmath>
00009 #include <cstring>
00010 
00011 #include "functionCompiler.hh"
00012 #include "exceptions.hh"
00013 #include "typedefs.hh"
00014 #include "vectorsMatricesForward.hh"
00015 #include "debug.hh"
00016 
00017 // debugging Mapping
00018 #define MappingAppll_D 0
00019 #define MappingAppl_D 0
00020 
00021 namespace concepts {
00022 
00024   template<typename F, typename G>
00025     void memorycpy(F *dest, const G *src, size_t n) {
00026       for (size_t i = 0; i < n; ++i) *dest++ = *src++;
00027     }
00028 
00029   // ***************************************************************** Point **
00030 
00039   template<class F, int dim>
00040     class Point {
00041       public:
00045         Point() { F* d = data_; for(uint i = dim; i--;) *d++ = 0; }
00047         template<class G>
00048           Point(const Point<G, dim>& p) {
00049             memorycpy(data_, (const G*)p, dim);
00050           }
00052         template<int dim2>
00053           Point(const Point<F, dim2>& p) {
00054             if (dim2<dim) {
00055               F* d = data_+dim2; for(uint i = dim-dim2; i--;) *d++ = 0;
00056             }
00057             memorycpy(data_, (const F*)p, ((dim < dim2) ? dim : dim2));
00058           }
00062         Point(F x) { F* d = data_; for(uint i = dim; i--;) *d++ = x; }
00064         Point(const F e0, const F e1, const F e2 = 0) {
00065           data_[0] = e0;
00066           if (dim > 1)
00067             data_[1] = e1;
00068           if (dim > 2)
00069             data_[2] = e2;
00070         }
00072         Point(const uchar *pgm, const Real x, const Real y, const Real z = 0.0);
00073 
00075         template<int dim2>
00076           Point<F, dim>& operator=(const Point<F, dim2>& b) {
00077             if (this != &b)
00078               memorycpy(data_, b.data_, ((dim < dim2) ? dim : dim2));
00079             return *this;
00080           }
00081 
00083         const F& operator[](const int i) const {
00084           conceptsAssert(i < dim, concepts::Assertion());
00085           return data_[i]; }
00087           F& operator[](const int i) {
00088             conceptsAssert(i < dim, concepts::Assertion());
00089             return data_[i]; }
00090 
00092             operator F*() { return data_; }
00094             operator const F*() const { return data_; }
00095 
00097             Point<F, dim>& operator+=(const Point<F, dim>& p) {
00098               F* d = data_; const F* dp = p.data_;
00099               for(uint i = dim; i--;) *d++ += *dp++;
00100               return *this;
00101             }
00103             Point<F, dim> operator+ (const Point<F, dim>& p) const {
00104               Point<F, dim> res(*this);
00105               return res += p;
00106             }
00108             Point<F, dim>& operator-=(const Point<F, dim>& p) {
00109               F* d = data_; const F* dp = p.data_;
00110               for(uint i = dim; i--;) *d++ -= *dp++;
00111               return *this;
00112             }
00114             Point<F, dim> operator- (const Point<F, dim>& p) const {
00115               Point<F, dim> res(*this);
00116               return res -= p;
00117             }
00118 
00120             F operator*(const Point<F, dim>& b) const;
00121             F operator*(const UnitNd<dim>& b) const;
00123             F dot(const Point<F, dim>& b) const {
00124               return *this * b;
00125             }
00126 
00128             template<class G>
00129               Point<F, dim>& operator*=(const G n) {
00130                 F* d = data_; 
00131                 for(uint i = dim; i--;) *d++ *= n;
00132                 return *this;
00133               }
00134             template<class G>
00135               Point<F, dim>& operator/=(const G n) {
00136                 F* d = data_; for(uint i = dim; i--;) *d++ /= n;
00137                 return *this;
00138               }
00140             template<class G>
00141             Point<typename Combtype<F,G>::type, dim> operator*(const G n) const {
00142               Point<typename Combtype<F,G>::type, dim> res(*this);
00143               return res *= n;
00144             }
00146             Point<F, dim>& scale(const Point<F, dim>& n) {
00147               F* d = data_; const F* e = n.data_;
00148               for(uint i = dim; i--;) *d++ *= *e++;
00149               return *this;
00150             }
00151 
00153             F cross(const Point<F, dim>& b) const {
00154               return data_[0]*b[1] - data_[1]*b[0];
00155             }
00157             Point<F, dim> operator^(const Point<F, dim>& b) const;
00158 
00160             Real l2() const { return std::sqrt(l2_2()); }
00162             Real l2_2() const;
00164             Real linfty() const;
00165 
00167             void lincomb(const Point<F, dim>& a, const Point<F, dim>& b,
00168                 const F ca = 1.0, const F cb = 1.0);
00169 
00171             void max(const Point<F, dim>& a, const Point<F, dim>& b);
00172 
00174             void min(const Point<F, dim>& a, const Point<F, dim>& b);
00175 
00179             Point<F, dim>& ortho(const Point<F, dim>& a);
00181             Point<F, dim>& ortho();
00183             Point<F, dim> ortho() const;
00184 
00185             std::ostream& info(std::ostream& os) const;
00186       private:
00187             F data_[dim];
00188     };
00189 
00190   template<class F, int dim>
00191     std::ostream& operator<<(std::ostream& os, const Point<F, dim>& p) {
00192       return p.info(os);
00193     }
00194 
00195   // set the real type of a vector to the real type of the components
00196   template<typename F, int dim>
00197   struct Realtype<Point<F,dim> > {
00198     typedef typename Realtype<F>::type type;
00199   };
00200 
00201   // set the data type of a vector to the data type of the components
00202   template<typename F, int dim>
00203   struct Datatype<Point<F,dim> > {
00204     //typedef typename Datatype<F>::type type;
00205     typedef F type;
00206   };
00207 
00208   template <class F, int dim>
00209   inline bool operator==(const Point<F,dim>& x, const Point<F,dim>& y)
00210   {
00211     const F* d = (const F*)x; const F* e = (const F*)y;
00212     for (uint i = dim; i--;)
00213       if (*d++ != *e++) return false;
00214     return true;
00215   }
00216 
00217   template <class F, int dim>
00218   inline Point<typename Combtype<F,Real>::type,dim> operator*(const Real x, const Point<F,dim>& y)
00219   {
00220     return y * x;
00221   }
00222 
00223   template <class F, int dim>
00224   inline Point<typename Combtype<F,Cmplx>::type,dim> operator*(const Cmplx x, const Point<F,dim>& y)
00225   {
00226     return y * x;
00227   }
00228 
00229   template<int dim>
00230   Cmplx operator*(const Point<Cmplx, dim>& a, const Point<Real, dim>& b) {
00231     Cmplx res = 0.0;
00232     const Cmplx* d = (const Cmplx*)a; const Real* db = (const Real*)b;
00233     for(uint i = 2; i--;) 
00234       res += (*d++) * *db++;
00235     return res;
00236   }
00237 
00238   template<int dim>
00239   Cmplx operator*(const Point<Real, dim>& a, const Point<Cmplx, dim>& b) {
00240     Cmplx res = 0.0;
00241     const Real* d = (const Real*)a; const Cmplx* db = (const Cmplx*)b;
00242     for(uint i = dim; i--;) 
00243       res += (*d++) * conj(*db++);
00244     return res;
00245   }
00246 
00247   // ********************************************************** GeneralPoint **
00248 
00257   template<class F, uint dim>
00258   struct GeneralPoint {
00259     typedef typename concepts::Point<F,dim> Type;
00260   };
00261   
00262   template<class F>
00263   struct GeneralPoint<F,1> {
00264     typedef F Type;
00265   };
00266 
00267 
00268   // **************************************************************** UnitNd **
00269 
00274   template <int dim>
00275     class UnitNd : public Point<Real, dim> {
00276       Real len_;
00277 
00278       public:
00280       UnitNd() : Point<Real, dim>() {len_ = 0.0;}
00282       inline UnitNd(const Point<Real, dim>& u);
00284       inline UnitNd(Real x, Real y, Real z);
00285 
00287       Real length() const {return len_;}
00288     };
00289 
00290   template <int dim>
00291     inline UnitNd<dim>::UnitNd(const Point<Real, dim>& u)
00292     : Point<Real, dim>(u) {
00293       len_ = this->l2();  *this *= (1.0 / len_);
00294     }
00295 
00296   template <int dim>
00297     inline UnitNd<dim>::UnitNd(Real x, Real y, Real z)
00298     : Point<Real, dim>(x, y, z) {
00299       len_ = this->l2();  *this *= (1.0 / len_);
00300     }
00301 
00302   // *************************************************************** Mapping **
00303 
00311   template<class F, int dim>
00312   class Mapping {
00313   public:
00317     Mapping() {}
00319     Mapping(const Mapping<F, dim>& m) {
00320       memorycpy(data_, m.data_, dim*dim);
00321     }
00322 
00326     template <class H>
00327     Mapping(const Mapping<H, dim>& m) {
00328       for(int i=0; i < dim*dim; ++i)
00329         data_[i] = m.data_[i];
00330     }
00331 
00332     // FIXME: this is not really nice
00333     friend class Mapping<Cmplx, dim>;
00334     friend class Mapping<Real, dim>;
00335 
00337     Mapping(const F e0, const F e1,
00338             const F e2, const F e3);
00343     Mapping(const Point<F, dim> first, const Point<F, dim> second);
00345     Mapping(const F e0, const F e1, const F e2,
00346             const F e3, const F e4, const F e5,
00347             const F e6, const F e7, const F e8);
00351     Mapping(const Point<F, dim> first,
00352             const Point<F, dim> second,
00353             const Point<F, dim> third);
00355     Mapping(const F e0, const F e1, const F e2,
00356             const F e3, const F e4, const F e5,
00357             const F e6, const F e7, const F e8, 
00358             const F e9, const F e10, const F e11, 
00359             const F e12, const F e13, const F e14, 
00360             const F e15, const F e16, const F e17, 
00361             const F e18, const F e19, const F e20, 
00362             const F e21, const F e22, const F e23, 
00363             const F e24, const F e25, const F e26, 
00364             const F e27, const F e28, const F e29, 
00365             const F e30, const F e31, const F e32, 
00366             const F e33, const F e34, const F e35);
00367 
00371     Mapping(const UnitNd<dim>& n);
00372 
00374     const F& operator()(uint i, uint j) const {
00375       conceptsAssert(i < dim, Assertion());
00376       conceptsAssert(j < dim, Assertion());
00377       DEBUGL(MappingAppll_D, '(' << i << ", " << j << ") is " << data_[i*dim+j]
00378              << " at " << &(data_[i*dim+j]));
00379       return data_[i*dim+j];
00380     }
00381 
00383     F& operator()(uint i, uint j) {
00384       conceptsAssert(i < dim, Assertion());
00385       conceptsAssert(j < dim, Assertion());
00386       DEBUGL(MappingAppll_D, '(' << i << ", " << j << ") is " << data_[i*dim+j]
00387              << " at " << &(data_[i*dim+j]));
00388       return data_[i*dim+j];
00389     }
00390 
00391 
00395     Mapping(F x) { F* d = data_; for(uint i = dim*dim; i--;) *d++ = x; }
00396 
00398     template<class H>
00399     Point<typename Combtype<F,H>::type, dim> operator*(const Point<H, dim>& p) const;
00400 
00401     template<class H>
00402     Point<H, dim> mapPoint(const Point<H, dim>& b) const {
00403       return this->operator*(b);
00404     }
00405 
00407     template<class G>
00408     Mapping<typename Combtype<F,G>::type, dim> 
00409     operator*(const Mapping<G, dim>& m) const;
00411     Mapping<F, dim>& operator*=(const F n);
00413     Mapping<F, dim>& operator*=(const Mapping<F, dim>& m);
00417     template<class G>
00418     Mapping<typename Combtype<F,G>::type, dim> operator*(const G n) const;
00419 
00421     Mapping<F, dim>& operator+=(const Mapping<F, dim>& M);
00423     Mapping<F, dim>& scaleRows(const Point<F, dim>& s);
00425     Mapping<F, dim>& scaleCols(const Point<F, dim>& s);
00427     F determinant() const;
00429     Mapping<F, dim> inverse() const;
00433     Mapping<F, dim> adjugate() const;
00435     Mapping<F, dim> transpose() const;
00437     Mapping<F, dim> prodTranspose() const;
00439     Point<F, dim> column(const uint i) const;
00440 
00445       template<class H, class J, int dimy, int dimx>
00446       void operator()(const Point<H, dimy>& y, Point<J, dimx>& x) const;
00447 
00449       void zeros() { F* d = data_;
00450         for (uint i = 0; i < dim*dim; ++i) *d++ = 0; }
00451       
00455       template <class H>
00456       void mapTranspose(const Point<H, dim>& y, Point<H, dim>& x) const;
00457       
00459       void rank1Product(const Point<F, dim> x,
00460                         const Point<F, dim> y);
00461       
00462       std::ostream& info(std::ostream& os) const;
00463     private:
00464       F data_[dim*dim];
00465     };
00466 
00467   template<class F, int dim>
00468   template<class H>
00469   Point<typename Combtype<F,H>::type, dim> Mapping<F, dim>::operator*(const Point<H, dim>& p) const
00470   {
00471     Point<typename Combtype<F,H>::type, dim> res;
00472     this->operator()(p, res);
00473     return res;
00474   }
00475 
00476   template<class F, int dim>
00477   template<class H, class J, int dimy, int dimx>
00478   void Mapping<F, dim>::operator()(const Point<H, dimy>& y,
00479                                    Point<J, dimx>& x) const
00480   {
00481     DEBUGL(MappingAppl_D, *this << " * " << y << " -> " << x);
00482     if (dimx == dimy && (void*)&x == (void*)&y) {
00483       
00484       J*       dx = (J*)x;
00485       const F* d  = data_;
00486       const H* yp = (const H*)y;
00487       H yy[dimy];
00488       for (int k = 0; k < dimy; k++)  yy[k] = yp[k];
00489       const H* dy = yy;
00490       for(int i = 0; i < (dim < dimx ? dim : dimx); ++dx, ++i) {
00491         dy = yy;
00492         *dx = 0;
00493         for(int j = 0; j < (dim < dimy ? dim : dimy); ++j) {
00494           *dx += d[j] * (*dy++);
00495         }
00496         d += dim;
00497       }
00498       if (dim < dimx) {
00499         for(int j = dim; j < (dimx < dimy ? dimx : dimy); ++j)
00500           *dx++ = *dy++;
00501         for(int k = 0; k < dimx - (dim < dimy ? dimy : dim); ++k)
00502           *dx++ = 0;
00503       }
00504       
00505     } // if (dimx == dimy && &x == &y)
00506     else {
00507       DEBUGL(MappingAppl_D, "x != y");
00508       J*       dx = (J*)x;
00509       const F* d  = data_;
00510       const H* dy = (const H*)y;
00511       for(int i = 0; i < (dim < dimx ? dim : dimx); ++dx, ++i) {
00512         dy = (const H*)y;
00513         *dx = 0;
00514         for(int j = 0; j < (dim < dimy ? dim : dimy); ++j) {
00515           *dx += d[j] * (*dy++);
00516         }
00517         DEBUGL(MappingAppl_D, "x = " << x);
00518         d += dim;
00519       }
00520       if (dim < dimx) {
00521         for(int j = dim; j < (dimx < dimy ? dimx : dimy); ++j)
00522           *dx++ = *dy++;
00523         for(int k = 0; k < dimx - (dim < dimy ? dimy : dim); ++k)
00524           *dx++ = 0;
00525       }
00526       
00527     } // else (dimx == dimy && &x == &y)
00528   }
00529   
00530   template<class F, int dim>
00531     template<class H>
00532     inline void Mapping<F, dim>::mapTranspose(const Point<H, dim>& y,
00533         Point<H, dim>& x) const 
00534     {
00535       H* dr = (H*)x;
00536       for(uint i = 0; i < dim; i++, dr++) {
00537         const H* dp = (const H*)y;
00538         const F* dm = data_ + i;
00539         *dr = 0;
00540         for(uint j = dim; j--; ++dp) {
00541           *dr += (*dm) * (*dp);
00542           dm += dim;
00543         }
00544       }
00545     }
00546 
00547   template<class F, int dim>
00548   std::ostream& operator<<(std::ostream& os, const Mapping<F, dim>& m) {
00549     return m.info(os);
00550   }
00551 
00552   // set the real type of a matrix to the real type of the components
00553   template<typename F, int dim>
00554   struct Realtype<Mapping<F,dim> > {
00555     typedef typename Realtype<F>::type type;
00556   };
00557 
00558   // set the data type of a matrix to the data type of the components
00559   template<typename F, int dim>
00560   struct Datatype<Mapping<F,dim> > {
00561     typedef typename Datatype<F>::type type;
00562   };
00563 
00564   // ******************************************************** GeneralMapping **
00565 
00574   template<class F, uint dim>
00575   struct GeneralMapping {
00576     typedef typename concepts::Mapping<F,dim> Type;
00577   };
00578   
00579   template<class F>
00580   struct GeneralMapping<F,1> {
00581     typedef F Type;
00582   };
00583 
00584   // **************************************************************** number **
00585 
00586   template<>
00587   template<class F, int dim>
00588   struct number<Point<F,dim> > {
00589     static inline std::string name() {
00590       return number<F>::name() + char('0'+dim) + 'd';
00591     }
00592   };
00593 
00594   template<>
00595   template<class F, int dim>
00596   struct number<Mapping<F,dim> > {
00597     static inline std::string name() {
00598       return "Map" + number<F>::name() + char('0'+dim) + 'd';
00599     }
00600   };
00601 
00602 } // namespace concepts
00603 
00604 namespace std {
00605 
00613   template<class F, int dim>
00614     inline const concepts::Point<F,dim> conj(const concepts::Point<F,dim>& v) { 
00615       concepts::Point<F,dim> res;
00616       F* d = (F*)res; const F* e = (const F*)v;
00617       for(uint i = dim; i--;) *d++ += conj(*e++);
00618       return res;
00619     }
00620 
00626   template<class F, int dim>
00627     inline const concepts::Real norm(const concepts::Point<F,dim>& v) { 
00628       return v.l2_2();
00629     }
00630 
00631   // ******************************************************************** arg **
00632 
00638   concepts::Real arg(const concepts::Point<concepts::Real,2>& p);
00639 
00640 } // namespace std
00641 
00642 #endif // vectMatr_hh

Home | Doxygen Documentation | Tutorials | Developer Tools (restricted)