00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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
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
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
00203
00204
00205
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 }
00217
00218
00219
00220
00221
00223 template <cplx_representation R, class T>
00224 class cplx;
00225
00226
00227
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
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
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
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
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
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
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
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
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
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
00589
00590
00591
00592
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
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 }
00652
00653 }
00654
00655 #endif // !NTG_VECT_CPLX_HH