cplx.hh

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

Generated on Thu Apr 15 20:13:07 2004 for Olena by doxygen 1.3.6-20040222