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
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
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
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
00204
00205
00206
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 }
00218
00219
00220
00221
00222
00224 template <cplx_representation R, class T>
00225 class cplx;
00226
00227
00228
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
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
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
00328 const cplx<polar, float_d>
00329 to_polar() const;
00330
00331 };
00332
00333
00334
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
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
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
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
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
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
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
00595
00596
00597
00598
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
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 }
00658
00659 }
00660
00661 #endif // !NTG_VECT_CPLX_HH