cplx.hh

00001 // Copyright (C) 2001, 2002, 2003, 2005 EPITA Research and Development
00002 // Laboratory
00003 //
00004 // This file is part of the Olena Library.  This library is free
00005 // software; you can redistribute it and/or modify it under the terms
00006 // of the GNU General Public License version 2 as published by the
00007 // Free Software Foundation.
00008 //
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this library; see the file COPYING.  If not, write to
00016 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017 // Boston, MA 02110-1301, USA.
00018 //
00019 // As a special exception, you may use this file as part of a free
00020 // software library without restriction.  Specifically, if other files
00021 // instantiate templates or use macros or inline functions from this
00022 // file, or you compile this file and link it with other files to
00023 // produce an executable, this file does not by itself cause the
00024 // resulting executable to be covered by the GNU General Public
00025 // License.  This exception does not however invalidate any other
00026 // reasons why the executable file might be covered by the GNU General
00027 // Public License.
00028 
00029 #ifndef NTG_VECT_CPLX_HH
00030 # define NTG_VECT_CPLX_HH
00031 
00032 # include <ntg/basics.hh>
00033 # include <ntg/vect/cplx_representation.hh>
00034 # include <ntg/vect/vec.hh>
00035 
00036 # include <mlc/cmp.hh>
00037 # include <mlc/is_a.hh>
00038 
00039 /*------------------------------.
00040 | Assignements operators macros |
00041 `------------------------------*/
00042 
00043 # define ASSIGN_CPLX_SCALAR_OPERATOR_SINGLE(Rep, Name, Op)      \
00044 template <class T1, class T2> inline                            \
00045 static cplx<Rep, T1>&                                           \
00046 Name(cplx<Rep, T1>& lhs, const T2& rhs)                         \
00047 {                                                               \
00048   ntg_is_a(T2, real)::ensure();                                 \
00049   lhs.first() Op rhs;                                           \
00050   return lhs;                                                   \
00051 }
00052 
00053 # define ASSIGN_CPLX_SCALAR_OPERATOR_BOTH(Rep, Name, Op)        \
00054 template <class T1, class T2> inline                            \
00055 static cplx<Rep, T1>&                                           \
00056 Name(cplx<Rep, T1>& lhs, const T2& rhs)                         \
00057 {                                                               \
00058   ntg_is_a(T2, real)::ensure();                                 \
00059   lhs.first() Op rhs;                                           \
00060   lhs.second() Op rhs;                                          \
00061   return lhs;                                                   \
00062 }
00063 
00064 # define ASSIGN_CPLX_POLAR_SCALAR_OPERATOR(Name, Op)    \
00065 template <class T1, class T2> inline                    \
00066 static cplx<polar, T1>&                                 \
00067 Name(cplx<polar, T1>& lhs, const T2& rhs)               \
00068 {                                                       \
00069   ntg_is_a(T2, real)::ensure();                         \
00070   cplx<rect, float_d> tmp(lhs);                         \
00071   tmp.real() Op rhs;                                    \
00072   lhs = tmp;                                            \
00073   return lhs;                                           \
00074 }
00075 
00076 # define ASSIGN_CPLX_RECT_CPLX_OPERATOR_MULT(Name, Op1, Op2)    \
00077 template <class T1, cplx_representation R2, class T2> inline    \
00078 static cplx<rect, T1>&                                          \
00079 Name(cplx<rect, T1>& lhs, const cplx<R2, T2>& rhs)              \
00080 {                                                               \
00081   cplx<polar, float_d> tmp(lhs);                                \
00082   tmp.magn() Op1 (float_d)rhs.magn();                           \
00083   tmp.angle() Op2 (float_d)rhs.angle();                         \
00084   lhs = tmp;                                                    \
00085   return lhs;                                                   \
00086 }
00087 
00088 # define ASSIGN_CPLX_RECT_CPLX_OPERATOR_ADD(Name, Op1, Op2)     \
00089 template <cplx_representation R, class T1, class T2> inline     \
00090 static cplx<rect, T1>&                                          \
00091 Name(cplx<rect, T1>& lhs, const cplx<R, T2>& rhs)               \
00092 {                                                               \
00093   lhs.first() Op1 rhs.real();                                   \
00094   lhs.second() Op2 rhs.imag();                                  \
00095   return lhs;                                                   \
00096 }
00097 
00098 # define ASSIGN_CPLX_POLAR_CPLX_OPERATOR_MULT(Name, Op1, Op2)   \
00099 template <cplx_representation R, class T1, class T2> inline     \
00100 static cplx<polar, T1>&                                         \
00101 Name(cplx<polar, T1>& lhs, const cplx<R, T2>& rhs)              \
00102 {                                                               \
00103   lhs.magn() Op1 rhs.magn();                                    \
00104   lhs.angle() Op2 rhs.angle();                                  \
00105   return lhs;                                                   \
00106 }
00107 
00108 # define ASSIGN_CPLX_POLAR_CPLX_OPERATOR_ADD(Name, Op)          \
00109 template <cplx_representation R, class T1, class T2> inline     \
00110 static cplx<polar, T1>&                                         \
00111 Name(cplx<polar, T1>& lhs, const cplx<R, T2>& rhs)              \
00112 {                                                               \
00113   cplx<rect, float_d> tmp(lhs);                                 \
00114   tmp.real() Op (float_d)rhs.real();                            \
00115   tmp.imag() Op (float_d)rhs.imag();                            \
00116   lhs = tmp;                                                    \
00117   return lhs;                                                   \
00118 }
00119 
00120 # define ASSIGN_CPLX_VECTOR_OPERATOR(Rep, Name, Op)     \
00121 template <class T1, class T2> inline                    \
00122 static cplx<Rep, T1>&                                   \
00123 Name(cplx<Rep, T1>& lhs, const vec<2, T2>& rhs)         \
00124 {                                                       \
00125   lhs.first() Op rhs[0];                                \
00126   lhs.second() Op rhs[1];                               \
00127   return lhs;                                           \
00128 }
00129 
00130 /*-----------------------------.
00131 | Arithemetic operators macros |
00132 `-----------------------------*/
00133 
00134 # define ARITH_CPLX_CPLX_OPERATOR(Rep1, Rep2, Name, Op)                 \
00135 template <class T1, class T2>                                           \
00136 inline static                                                           \
00137 cplx<Rep1, ntg_return_type(Name, T1, T2)>                               \
00138 Name(const cplx<Rep1, T1>& lhs, const cplx<Rep2, T2>& rhs)              \
00139 {                                                                       \
00140   typedef cplx<Rep1, ntg_return_type(Name, T1, T2)> return_type;        \
00141   return_type result(lhs);                                              \
00142   result Op rhs;                                                        \
00143   return result;                                                        \
00144 }
00145 
00146 # define ARITH_CPLX_SCALAR_OPERATOR(Rep, Name, Op)              \
00147 template <class T1, class T2>                                   \
00148 inline static                                                   \
00149 cplx<Rep, ntg_return_type(Name, T1, T2)>                        \
00150 Name(const cplx<Rep, T1>& lhs, const T2& rhs)                   \
00151 {                                                               \
00152   ntg_is_a(T2, real)::ensure();                                 \
00153   typedef cplx<Rep, ntg_return_type(Name, T1, T2)> return_type; \
00154   return_type result(lhs);                                      \
00155   result Op rhs;                                                \
00156   return result;                                                \
00157 }
00158 
00159 # define ARITH_CPLX_SCALAR_OPERATOR_COMMUTE(Rep, Name, Op)      \
00160 template <class T1, class T2>                                   \
00161 inline static                                                   \
00162 cplx<Rep, ntg_return_type(Name, T1, T2)>                        \
00163 Name(const T1& lhs, const cplx<Rep, T2>& rhs)                   \
00164 {                                                               \
00165   return Name(rhs, lhs);                                        \
00166 }
00167 
00168 # define ARITH_CPLX_VECTOR_OPERATOR(Rep, Name, Op)              \
00169 template <class T1, class T2>                                   \
00170 inline static                                                   \
00171 cplx<Rep, ntg_return_type(Name, T1, T2)>                        \
00172 Name(const cplx<Rep, T1>& lhs, const vec<2, T2>& rhs)           \
00173 {                                                               \
00174   typedef cplx<Rep, ntg_return_type(Name, T1, T2)> return_type; \
00175   return_type result(lhs);                                      \
00176   result Op rhs;                                                \
00177   return result;                                                \
00178 }
00179 
00180 # define ARITH_CPLX_VECTOR_OPERATOR_COMMUTE_PLUS(Rep, Name, Op)         \
00181 template <class T1, class T2>                                           \
00182 inline static                                                           \
00183 cplx<Rep, ntg_return_type(Name, T1, T2)>                                \
00184 Name(const vec<2, T1>& lhs, const cplx<Rep, T2>& rhs)                   \
00185 {                                                                       \
00186   return Name(rhs, lhs);                                                \
00187 }
00188 
00189 # define ARITH_CPLX_VECTOR_OPERATOR_COMMUTE_MINUS(Rep, Name, Op)        \
00190 template <class T1, class T2>                                           \
00191 inline static                                                           \
00192 cplx<Rep, ntg_return_type(Name, T1, T2)>                                \
00193 Name(const vec<2, T1>& lhs, const cplx<Rep, T2>& rhs)                   \
00194 {                                                                       \
00195   return Name(rhs, lhs).invert();                                       \
00196 }
00197 
00198 namespace ntg {
00199 
00200   namespace internal {
00201 
00202     /*----------------------.
00203     | typetraits<cplx<R, T> |
00204     `----------------------*/
00205 
00206     // FIXME: why cplx<polar> does not inherit from vec<2, ...> ?
00207 
00208     template <cplx_representation R, class T>
00209     struct typetraits<cplx<R, T> > : 
00210       public typetraits<vec<2, T, cplx<R, T> > >
00211     {
00212       typedef cplx<R, T>        self;
00213       typedef self              ntg_type;
00214       typedef optraits<self>    optraits_type;
00215     };
00216 
00217   } // end of internal.
00218 
00219   /*-----------.
00220   | cplx<R, T> |
00221   `-----------*/
00222 
00224   template <cplx_representation R, class T>
00225   class cplx;
00226 
00227   /*--------------.
00228   | cplx<rect, T> |
00229   `--------------*/
00230 
00231   template <class T>
00232   class cplx<rect, T> : public vec<2, T, cplx<rect, T> >
00233   {
00234   public:
00235 
00236     cplx(const T& re = 0, const T& im = 0)
00237     {
00238       this->val_[0] = re;
00239       this->val_[1] = im;
00240     }
00241 
00242     cplx<rect, T>&
00243     operator=(const T& r)
00244     {
00245       this->val_[0] = r;
00246       this->val_[1] = 0;
00247       return *this;
00248     }
00249 
00250     template<cplx_representation R, class T2>
00251     cplx(const cplx<R, T2>& rhs)
00252     {
00253       this->val_[0] = (T)rhs.real();
00254       this->val_[1] = (T)rhs.imag();
00255     }
00256 
00257     template<cplx_representation R, class T2>
00258     cplx<rect, T>&
00259     operator=(const cplx<R, T2>& rhs)
00260     {
00261       this->val_[0] = (T)rhs.real();
00262       this->val_[1] = (T)rhs.imag();
00263       return *this;
00264     }
00265 
00266     template<class T2>
00267     cplx(const vec<2, T2>& rhs)
00268     {
00269       this->val_[0] = (T)rhs[0];
00270       this->val_[1] = (T)rhs[1];
00271     }
00272 
00273     template<class T2>
00274     cplx<rect, T>&
00275     operator=(const vec<2, T2>& rhs)
00276     {
00277       this->val_[0] = (T)rhs[0];
00278       this->val_[1] = (T)rhs[1];
00279       return *this;
00280     }
00281 
00282     ~cplx()
00283     {
00284       ntg_is_a(T, ntg::real)::ensure();
00285     }
00286 
00287     // accessors
00288 
00289     const T real() const { return this->val_[0]; }
00290     T& real() { return this->val_[0]; }
00291 
00292     const T imag() const { return this->val_[1]; }
00293     T& imag() { return this->val_[1]; }
00294 
00295     const T first() const { return this->val_[0]; }
00296     T& first() { return this->val_[0]; }
00297 
00298     const T second() const { return this->val_[1]; }
00299     T& second() { return this->val_[1]; }
00300 
00301     // methods
00302 
00303     const float_d
00304     magn() const
00305     {
00306       return sqrt(this->val_[0] * this->val_[0] + this->val_[1] * this->val_[1]);
00307     }
00308 
00309     const float_d
00310     angle() const
00311     {
00312       return atan2(this->val_[1], this->val_[0]);
00313     }
00314 
00315     const cplx<rect, T>
00316     conj() const
00317     {
00318       return cplx<rect, T>(this->val_[0], -this->val_[1]);
00319     }
00320 
00321     const cplx<rect, T>
00322     invert() const
00323     {
00324       return cplx<rect, T>(-this->val_[0], -this->val_[1]);
00325     }
00326 
00327     // Forward declaration.
00328     const cplx<polar, float_d>
00329     to_polar() const;
00330 
00331   };
00332 
00333   /*---------------.
00334   | cplx<polar, T> |
00335   `---------------*/
00336 
00337   template <class T>
00338   class cplx<polar, T> : public vect_value<cplx<polar, T> >
00339   {
00340   public:
00341 
00342     cplx(const T& ma = 0, const T& an = 0)
00343     {
00344       ntg_assert(ma >= 0);
00345       this->val_[0] = ma;
00346       this->val_[1] = an;
00347     }
00348 
00349     cplx<polar, T>& operator=(const T& r)
00350     {
00351       this->val_[0] = r;
00352       this->val_[1] = 0;
00353       return *this;
00354     }
00355 
00356     template<cplx_representation R, class T2>
00357     cplx(const cplx<R, T2>& rhs)
00358     {
00359       this->val_[0] = (T)rhs.magn();
00360       this->val_[1] = (T)rhs.angle();
00361     }
00362 
00363     template<cplx_representation R, class T2>
00364     cplx<polar, T>& operator=(const cplx<R, T2>& rhs)
00365     {
00366       this->val_[0] = (T)rhs.magn();
00367       this->val_[1] = (T)rhs.angle();
00368       return *this;
00369     }
00370 
00371     ~cplx()
00372     {
00373       ntg_is_a(T, ntg::real)::ensure();
00374     }
00375 
00376     // accessors
00377 
00378     const T magn() const { return this->val_[0]; }
00379     T& magn() { return this->val_[0]; }
00380 
00381     const T angle() const { return this->val_[1]; }
00382     T& angle() { return this->val_[1]; }
00383 
00384     const T first() const { return this->val_[0]; }
00385     T& first() { return this->val_[0]; }
00386 
00387     const T second() const { return this->val_[1]; }
00388     T& second() { return this->val_[1]; }
00389 
00390     // methods
00391 
00392     const float_d
00393     real() const
00394     {
00395       return this->val_[0] * cos(this->val_[1]);
00396     }
00397 
00398     const float_d
00399     imag() const
00400     {
00401       return this->val_[0] * sin(this->val_[1]);
00402     }
00403 
00404     const cplx<polar, T>
00405     conj() const
00406     {
00407       return cplx<polar, T>(this->val_[0], -this->val_[1]);
00408     }
00409 
00410     const cplx<rect, T>
00411     invert() const
00412     {
00413       return cplx<rect, T>(this->val_[0], this->val_[1] + M_PI);
00414     }
00415 
00416     const cplx<rect, float_d>
00417     to_rect() const
00418     {
00419       return cplx<rect, float_d>(real(), imag());
00420     }
00421 
00422   };
00423 
00424   template <class T>
00425   const cplx<polar, float_d>
00426   cplx<rect, T>::to_polar() const
00427   {
00428     return cplx<polar, float_d>(magn(), angle());
00429   }
00430 
00431   template<class T>
00432   inline std::ostream&
00433   operator<<(std::ostream& ostr, const cplx<rect, T>& rhs)
00434   {
00435     // Using an ostringstream is necessary to pretty print.
00436     std::ostringstream str;
00437     str << rhs.real() << " + " << rhs.imag() << "i";
00438     return ostr << str.str();
00439   }
00440 
00441   template<class T>
00442   inline std::ostream&
00443   operator<<(std::ostream& ostr, const cplx<polar, T>& rhs)
00444   {
00445     // Using an ostringstream is necessary to pretty print.
00446     std::ostringstream str;
00447     str << rhs.magn() << " * exp(" << rhs.angle() << "i)";
00448     return ostr << str.str();
00449   }
00450 
00451   namespace internal 
00452   {
00453 
00454     /*-------------------------.
00455     | optraits<cplx<rect, T> > |
00456     `-------------------------*/
00457   
00458     template <class T>
00459     class optraits<cplx<rect, T> > : public optraits<vec<2, T> >
00460     {
00461       typedef cplx<rect, T> self;
00462       typedef typename typetraits<self>::storage_type storage_type_;
00463     
00464     public:
00465       static self zero () { return self(); }
00466       static self unit () { return self(1); }
00467 
00468       static unsigned max_print_width() 
00469       {
00470         return 2 * ntg_max_print_width(T) + 4;
00471       }
00472     
00473       static std::string
00474       name()
00475       {
00476         std::ostringstream out;
00477         out << "cplx<rect, " <<  optraits<T>::name() << ">" << std::ends;
00478         return out.str();
00479       }
00480 
00481       ASSIGN_CPLX_SCALAR_OPERATOR_SINGLE(rect, plus_equal, +=)
00482       ASSIGN_CPLX_SCALAR_OPERATOR_SINGLE(rect, minus_equal, -=)
00483       ASSIGN_CPLX_SCALAR_OPERATOR_BOTH(rect, times_equal, *=)
00484       ASSIGN_CPLX_SCALAR_OPERATOR_BOTH(rect, div_equal, /=)
00485     
00486       ASSIGN_CPLX_RECT_CPLX_OPERATOR_ADD(plus_equal, +=, +=)
00487       ASSIGN_CPLX_RECT_CPLX_OPERATOR_ADD(minus_equal, -=, -=)
00488       ASSIGN_CPLX_RECT_CPLX_OPERATOR_MULT(times_equal, *=, +=)
00489       ASSIGN_CPLX_RECT_CPLX_OPERATOR_MULT(div_equal, /=, -=)
00490 
00491       ASSIGN_CPLX_VECTOR_OPERATOR(rect, plus_equal, +=)
00492       ASSIGN_CPLX_VECTOR_OPERATOR(rect, minus_equal, -=)
00493 
00494       ARITH_CPLX_SCALAR_OPERATOR(rect, plus, +=)
00495       ARITH_CPLX_SCALAR_OPERATOR_COMMUTE(rect, plus, +=)
00496       ARITH_CPLX_SCALAR_OPERATOR(rect, minus, -=)
00497       ARITH_CPLX_SCALAR_OPERATOR(rect, times, *=)
00498       ARITH_CPLX_SCALAR_OPERATOR_COMMUTE(rect, times, *=)
00499       ARITH_CPLX_SCALAR_OPERATOR(rect, div, /=)
00500 
00501       ARITH_CPLX_CPLX_OPERATOR(rect, rect, plus, +=)
00502       ARITH_CPLX_CPLX_OPERATOR(rect, rect, minus, -=)
00503       ARITH_CPLX_CPLX_OPERATOR(rect, rect, times, *=)
00504       ARITH_CPLX_CPLX_OPERATOR(rect, rect, div, /=)
00505 
00506       ARITH_CPLX_CPLX_OPERATOR(rect, polar, plus, +=)
00507       ARITH_CPLX_CPLX_OPERATOR(rect, polar, minus, -=)
00508       ARITH_CPLX_CPLX_OPERATOR(rect, polar, times, *=)
00509       ARITH_CPLX_CPLX_OPERATOR(rect, polar, div, /=)
00510 
00511       ARITH_CPLX_VECTOR_OPERATOR(rect, plus, +=)
00512       ARITH_CPLX_VECTOR_OPERATOR_COMMUTE_PLUS(rect, plus, +=)
00513       ARITH_CPLX_VECTOR_OPERATOR(rect, minus, -=)
00514       ARITH_CPLX_VECTOR_OPERATOR_COMMUTE_MINUS(rect, minus, -=)
00515 
00516       template <class T1, cplx_representation R2, class T2>
00517       inline static bool
00518       cmp_eq (const cplx<rect, T1>& lhs, const cplx<R2, T2>& rhs)
00519       {
00520         if (lhs.real() != rhs.real() || lhs.imag() != rhs.imag())
00521           return false;
00522         return true;
00523       }
00524 
00525     };
00526 
00527     /*--------------------------.
00528     | optraits<cplx<polar, T> > |
00529     `--------------------------*/
00530 
00531     template <class T>
00532     class optraits<cplx<polar, T> >
00533     {
00534       typedef cplx<polar, T> self;
00535       typedef ntgi_storage_type(self) storage_type_;
00536     
00537     public:
00538       static self zero () { return self(); }
00539     
00540       static self unit () { return self(1); }
00541     
00542       static unsigned max_print_width() 
00543       {
00544         return 2 * ntg_max_print_width(T) + 4;
00545       }
00546 
00547       static std::string
00548       name()
00549       {
00550         std::ostringstream out;
00551         out << "cplx<polar, " <<  optraits<T>::name() << ">" << std::ends;
00552         return out.str();
00553       }
00554 
00555       ASSIGN_CPLX_POLAR_SCALAR_OPERATOR(plus_equal, +=)
00556       ASSIGN_CPLX_POLAR_SCALAR_OPERATOR(minus_equal, -=)
00557       ASSIGN_CPLX_SCALAR_OPERATOR_SINGLE(polar, times_equal, *=)
00558       ASSIGN_CPLX_SCALAR_OPERATOR_SINGLE(polar, div_equal, /=)
00559 
00560       ASSIGN_CPLX_POLAR_CPLX_OPERATOR_ADD(plus_equal, +=)
00561       ASSIGN_CPLX_POLAR_CPLX_OPERATOR_ADD(minus_equal, -=)
00562       ASSIGN_CPLX_POLAR_CPLX_OPERATOR_MULT(times_equal, *=, +=)
00563       ASSIGN_CPLX_POLAR_CPLX_OPERATOR_MULT(div_equal, /=, -=)
00564 
00565       ARITH_CPLX_SCALAR_OPERATOR(polar, plus, +=)
00566       ARITH_CPLX_SCALAR_OPERATOR_COMMUTE(polar, plus, +=)
00567       ARITH_CPLX_SCALAR_OPERATOR(polar, minus, -=)
00568       ARITH_CPLX_SCALAR_OPERATOR(polar, times, *=)
00569       ARITH_CPLX_SCALAR_OPERATOR_COMMUTE(polar, times, *=)
00570       ARITH_CPLX_SCALAR_OPERATOR(polar, div, /=)
00571 
00572       ARITH_CPLX_CPLX_OPERATOR(polar, polar, plus, +=)
00573       ARITH_CPLX_CPLX_OPERATOR(polar, polar, minus, -=)
00574       ARITH_CPLX_CPLX_OPERATOR(polar, polar, times, *=)
00575       ARITH_CPLX_CPLX_OPERATOR(polar, polar, div, /=)
00576 
00577       ARITH_CPLX_CPLX_OPERATOR(polar, rect, plus, +=)
00578       ARITH_CPLX_CPLX_OPERATOR(polar, rect, minus, -=)
00579       ARITH_CPLX_CPLX_OPERATOR(polar, rect, times, *=)
00580       ARITH_CPLX_CPLX_OPERATOR(polar, rect, div, /=)
00581 
00582       template <class T1, cplx_representation R2, class T2>
00583       inline static bool
00584       cmp_eq (const cplx<polar, T1>& lhs, const cplx<R2, T2>& rhs)
00585       {
00586         if (lhs.magn() != rhs.magn() || lhs.angle() != rhs.angle())
00587           return false;
00588         return true;
00589       }
00590 
00591     };
00592     
00593     /*-----------------------.
00594     | operator traits macros |
00595     `-----------------------*/
00596 
00597     // FIXME: I think there should be an easy way to simplify this. 
00598     // -- nes
00599 
00600 # define CPLX_SCALAR_OPERATORS_TRAITS(Name, CommuteBool)        \
00601     template <cplx_representation R1, class T1, class T2>       \
00602     struct operator_traits<operator_##Name, cplx<R1, T1>, T2>   \
00603     {                                                           \
00604       enum { commutative = CommuteBool };                       \
00605       typedef cplx<R1, ntg_return_type(Name, T1, T2)> ret;      \
00606       typedef cplx<R1, T1> impl;                                \
00607     }
00608 
00609 # define CPLX_CPLX_OPERATORS_TRAITS(Name, CommuteBool)          \
00610     template <cplx_representation R1,                           \
00611               class T1,                                         \
00612               cplx_representation R2, class T2>                 \
00613     struct operator_traits<operator_##Name,                     \
00614                            cplx<R1, T1>, cplx<R2, T2> >         \
00615     {                                                           \
00616       enum { commutative = CommuteBool };                       \
00617       typedef cplx<R1, ntg_return_type(Name, T1, T2)> ret;      \
00618       typedef cplx<R1, T1> impl;                                \
00619     }
00620 
00621 # define CPLX_VECTOR_OPERATORS_TRAITS(Rep, Name, CommuteBool)   \
00622     template <class T1, class T2>                               \
00623     struct operator_traits<operator_##Name,                     \
00624                            cplx<Rep, T1>, vec<2, T2> >          \
00625     {                                                           \
00626       enum { commutative = CommuteBool };                       \
00627       typedef cplx<Rep, ntg_return_type(Name, T1, T2)> ret;     \
00628       typedef cplx<Rep, T1> impl;                               \
00629     }
00630 
00631     /*----------------.
00632     | operator traits |
00633     `----------------*/
00634  
00635     CPLX_SCALAR_OPERATORS_TRAITS(plus, true);
00636     CPLX_SCALAR_OPERATORS_TRAITS(minus, true);
00637     CPLX_SCALAR_OPERATORS_TRAITS(times, true);
00638     CPLX_SCALAR_OPERATORS_TRAITS(div, true);
00639     
00640     CPLX_CPLX_OPERATORS_TRAITS(plus, true);
00641     CPLX_CPLX_OPERATORS_TRAITS(minus, true);
00642     CPLX_CPLX_OPERATORS_TRAITS(times, true);
00643     CPLX_CPLX_OPERATORS_TRAITS(div, true);
00644 
00645     CPLX_VECTOR_OPERATORS_TRAITS(rect, plus, true);
00646     CPLX_VECTOR_OPERATORS_TRAITS(rect, minus, true);
00647 
00648     template<cplx_representation R1, class T1, 
00649              cplx_representation R2, class T2>
00650     struct operator_traits<operator_cmp, cplx<R1, T1>, cplx<R2, T2> >
00651     {
00652       enum { commutative = true };
00653       typedef cplx<R1, ntg_return_type(cmp, T1, T2)> ret;
00654       typedef cplx<R1, T1> impl;
00655     };
00656 
00657   } // end of internal.
00658 
00659 } // end of ntg.
00660 
00661 #endif // !NTG_VECT_CPLX_HH

Generated on Tue Feb 20 20:18:48 2007 for Olena by  doxygen 1.5.1