00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef HxComplex_h
00013 #define HxComplex_h
00014
00015
00016
00017 #include "HxIoFwd.h"
00018 #include "HxMath.h"
00019 #include "HxString.h"
00020
00021 #undef min
00022 #undef max
00023
00024 class HxScalarInt;
00025 #include "HxScalarDouble.h"
00026 class HxVec2Int;
00027 class HxVec2Double;
00028 class HxVec3Int;
00029 class HxVec3Double;
00030
00031
00035 class L_HXBASIS HxComplex
00036 {
00037 public:
00038
00040
00042 HxComplex();
00043
00045 HxComplex(double re, double im);
00046
00048 HxComplex(const HxComplex& rhs);
00050
00051 void* operator new(size_t, void * = 0);
00052
00053 HxComplex& operator=(const HxComplex& rhs);
00054
00056
00059 int dim() const;
00060
00062 double x() const;
00063
00065 double y() const;
00066
00068 double getValue(int dimension) const;
00069 void setValue(int dimension, double value);
00071
00073
00075 operator HxScalarInt() const;
00076
00078 operator HxScalarDouble() const;
00079
00081 operator HxVec2Int() const;
00082
00084 operator HxVec2Double() const;
00085
00087 operator HxVec3Int() const;
00088
00090 operator HxVec3Double() const;
00092
00094
00098 int operator==(const HxComplex& v) const;
00099
00101 int operator!=(const HxComplex& v) const;
00102
00104 int operator< (const HxComplex& v) const;
00105
00107 int operator<=(const HxComplex& v) const;
00108
00110 int operator> (const HxComplex& v) const;
00111
00113 int operator>=(const HxComplex& v) const;
00114
00119 static const HxComplex SMALL_VAL;
00120
00125 static const HxComplex LARGE_VAL;
00127
00129
00133 HxComplex operator-() const;
00134
00136 HxComplex complement() const;
00137
00139 HxComplex conjugate() const;
00140
00142 HxScalarDouble abs() const;
00143
00145 HxScalarDouble arg() const;
00146
00148 HxComplex ceil() const;
00149
00151 HxComplex floor() const;
00152
00154 HxComplex round() const;
00155
00157 HxComplex sum() const;
00158
00160 HxComplex product() const;
00161
00163 HxScalarDouble min() const;
00164
00166 HxScalarDouble max() const;
00167
00169 HxScalarDouble norm1() const;
00170
00172 HxScalarDouble norm2() const;
00173
00175 HxScalarDouble normInf() const;
00176
00178 HxComplex sqrt() const;
00179
00181 HxComplex sin() const;
00182
00184 HxComplex cos() const;
00185
00187 HxComplex tan() const;
00188
00190 HxComplex asin() const;
00191
00193 HxComplex acos() const;
00194
00196 HxComplex atan() const;
00197
00199 HxComplex atan2() const;
00200
00202 HxComplex sinh() const;
00203
00205 HxComplex cosh() const;
00206
00208 HxComplex tanh() const;
00209
00211 HxComplex exp() const;
00212
00214 HxComplex log() const;
00215
00217 HxComplex log10() const;
00219
00221
00225 HxComplex& operator+=(const HxComplex& v);
00226
00228 HxComplex& operator-=(const HxComplex& v);
00229
00231 HxComplex& operator*=(const HxComplex& v);
00232
00234 HxComplex& operator/=(const HxComplex& v);
00235
00236
00238 friend HxComplex operator+(const HxComplex& v1,
00239 const HxComplex& v2);
00240
00242 friend HxComplex operator-(const HxComplex& v1,
00243 const HxComplex& v2);
00244
00246 friend HxComplex operator*(const HxComplex& v1,
00247 const HxComplex& v2);
00248
00250 friend HxComplex operator/(const HxComplex& v1,
00251 const HxComplex& v2);
00252
00253
00255 HxComplex min(const HxComplex& v) const;
00256
00258 HxComplex& minAssign(const HxComplex& v);
00259
00261 HxComplex max(const HxComplex& v) const;
00262
00264 HxComplex& maxAssign(const HxComplex& v);
00265
00267 HxComplex inf(const HxComplex& v) const;
00268
00270 HxComplex& infAssign(const HxComplex& v);
00271
00273 HxComplex sup(const HxComplex& v) const;
00274
00276 HxComplex& supAssign(const HxComplex& v);
00277
00279 HxComplex pow(const HxComplex& v) const;
00280
00282 HxComplex mod(const HxComplex& v) const;
00283
00285 HxComplex and(const HxComplex& v) const;
00286
00288 HxComplex or(const HxComplex& v) const;
00289
00291 HxComplex xor(const HxComplex& v) const;
00292
00294 HxComplex leftShift(const HxComplex& v) const;
00295
00297 HxComplex rightShift(const HxComplex& v) const;
00298
00300 HxScalarDouble dot(const HxComplex& v) const;
00301
00303 HxComplex cross(const HxComplex& v) const;
00305
00307
00309 STD_OSTREAM& put(STD_OSTREAM& os) const;
00310
00312 HxString toString() const;
00314
00315 private:
00316 double _values[2];
00317 };
00318
00319 typedef HxComplex (*HxUpoComplex)(const HxComplex& a);
00320 typedef HxComplex (*HxBpoComplex)(const HxComplex& a1, const HxComplex& a2);
00321
00322 inline STD_OSTREAM&
00323 operator<<(STD_OSTREAM& os, const HxComplex v)
00324 {
00325 return v.put(os);
00326 }
00327
00328 inline
00329 HxComplex::HxComplex()
00330 {
00331 }
00332
00333 inline
00334 HxComplex::HxComplex(double re, double im)
00335 {
00336 _values[0] = re;
00337 _values[1] = im;
00338 }
00339
00340 inline
00341 HxComplex::HxComplex(const HxComplex& v)
00342 {
00343 _values[0] = v._values[0];
00344 _values[1] = v._values[1];
00345 }
00346
00347 inline HxComplex&
00348 HxComplex::operator=(const HxComplex& rhs)
00349 {
00350 _values[0] = rhs._values[0];
00351 _values[1] = rhs._values[1];
00352 return *this;
00353 }
00354
00355 inline void*
00356 HxComplex::operator new(size_t size, void *m)
00357 {
00358 return m ? m : new char[size];
00359 }
00360
00361 inline int
00362 HxComplex::dim() const
00363 {
00364 return 2;
00365 }
00366
00367 inline double
00368 HxComplex::x() const
00369 {
00370 return _values[0];
00371 }
00372
00373 inline double
00374 HxComplex::y() const
00375 {
00376 return _values[1];
00377 }
00378
00379 inline double
00380 HxComplex::getValue(int dim) const
00381 {
00382 return _values[dim - 1];
00383 }
00384
00385 inline void
00386 HxComplex::setValue(int dim, double val)
00387 {
00388 _values[dim - 1] = val;
00389 }
00390
00391 inline int
00392 HxComplex::operator==(const HxComplex& v) const
00393 {
00394 return (_values[0] == v._values[0]) && (_values[1] == v._values[1]);
00395 }
00396
00397 inline int
00398 HxComplex::operator!=(const HxComplex& v) const
00399 {
00400 return (_values[0] != v._values[0]) || (_values[1] != v._values[1]);
00401 }
00402
00403 inline int
00404 HxComplex::operator<(const HxComplex& v) const
00405 {
00406 return (fabs(_values[0]) + fabs(_values[1])) <
00407 (fabs(v._values[0]) + fabs(v._values[1]));
00408 }
00409
00410 inline int
00411 HxComplex::operator<=(const HxComplex& v) const
00412 {
00413 return (fabs(_values[0]) + fabs(_values[1])) <=
00414 (fabs(v._values[0]) + fabs(v._values[1]));
00415 }
00416
00417 inline int
00418 HxComplex::operator>(const HxComplex& v) const
00419 {
00420 return (fabs(_values[0]) + fabs(_values[1])) >
00421 (fabs(v._values[0]) + fabs(v._values[1]));
00422 }
00423
00424 inline int
00425 HxComplex::operator>=(const HxComplex& v) const
00426 {
00427 return (fabs(_values[0]) + fabs(_values[1])) >=
00428 (fabs(v._values[0]) + fabs(v._values[1]));
00429 }
00430
00431 inline HxComplex
00432 HxComplex::operator-() const
00433 {
00434 return HxComplex(-_values[0], -_values[1]);
00435 }
00436
00437 inline HxComplex
00438 HxComplex::complement() const
00439 {
00440 return HxComplex(-_values[0], -_values[1]);
00441 }
00442
00443 inline HxComplex
00444 HxComplex::conjugate() const
00445 {
00446 return HxComplex(_values[0], -_values[1]);
00447 }
00448
00449 inline HxScalarDouble
00450 HxComplex::abs() const
00451 {
00452 return HxScalarDouble(::sqrt(_values[0]*_values[0]+_values[1]*_values[1]));
00453 }
00454
00455 inline HxScalarDouble
00456 HxComplex::arg() const
00457 {
00458 return HxScalarDouble(::atan2(_values[1], _values[0]));
00459 }
00460
00461 inline HxComplex
00462 HxComplex::ceil() const
00463 {
00464 return HxComplex(::ceil(_values[0]), ::ceil(_values[1]));
00465 }
00466
00467 inline HxComplex
00468 HxComplex::floor() const
00469 {
00470 return HxComplex(::floor(_values[0]), ::floor(_values[1]));
00471 }
00472
00473 inline HxComplex
00474 HxComplex::round() const
00475 {
00476 return HxComplex((int) (_values[0] + ((_values[0] >= 0) ? 0.5 : -0.5)),
00477 (int) (_values[1] + ((_values[1] >= 0) ? 0.5 : -0.5)));
00478 }
00479
00480 inline HxComplex
00481 HxComplex::sqrt() const
00482 {
00483 double a = _values[0];
00484 double b = _values[1];
00485 double sq = a*a+b*b;
00486 double arg = ::atan(b/a)*0.5;
00487 double mul = ::pow(sq, 0.25)*::exp(a*0.5);
00488
00489 return HxComplex(mul*::cos(arg), mul*::sin(arg));
00490 }
00491
00492 inline HxComplex
00493 HxComplex::sin() const
00494 {
00495 return HxComplex(::sin(_values[0])*::cosh(_values[1]),
00496 ::cos(_values[0])*::sinh(_values[1]));
00497 }
00498
00499 inline HxComplex
00500 HxComplex::cos() const
00501 {
00502 return HxComplex(::cos(_values[0])*::cosh(_values[1]),
00503 -::sin(_values[0])*::sinh(_values[1]));
00504 }
00505
00506 inline HxComplex
00507 HxComplex::tan() const
00508 {
00509 double den = ::cos(2*_values[0])+::cosh(2*_values[1]);
00510
00511 return HxComplex(::sin(2*_values[0])/den, ::sinh(2*_values[1])/den);
00512 }
00513
00514 inline HxComplex
00515 HxComplex::asin() const
00516 {
00517 double a = _values[0];
00518 double b = _values[1];
00519
00520 HxComplex c = HxComplex(1-a*a+b*b, 2*a*b).sqrt() + HxComplex(-b,a);
00521
00522 return HxComplex(c.arg().x(), -::log(c.abs().x()));
00523 }
00524
00525 inline HxComplex
00526 HxComplex::acos() const
00527 {
00528 double a = _values[0];
00529 double b = _values[1];
00530
00531 HxComplex c = HxComplex(1-a*a+b*b, 2*a*b).sqrt() + HxComplex(-b,a);
00532
00533 return HxComplex(M_PI/2.0 - c.arg().x(), ::log(c.abs().x()));
00534 }
00535
00536 inline HxComplex
00537 HxComplex::atan() const
00538 {
00539 double a = _values[0];
00540 double b = _values[1];
00541
00542 HxComplex cp = HxComplex(1-b,a);
00543 HxComplex cm = HxComplex(1+b,-a);
00544
00545 return HxComplex(0.5*(cp.arg().x()-cm.arg().x()),
00546 0.5*(::log(cm.abs().x())-::log(cp.abs().x())));
00547 }
00548
00549 inline HxComplex
00550 HxComplex::sinh() const
00551 {
00552 return HxComplex(::sinh(_values[0])*::cos(_values[1]),
00553 ::cosh(_values[0])*::sin(_values[1]));
00554 }
00555
00556 inline HxComplex
00557 HxComplex::cosh() const
00558 {
00559 return HxComplex(::cosh(_values[0])*::cos(_values[1]),
00560 ::sinh(_values[0])*::sin(_values[1]));
00561 }
00562
00563 inline HxComplex
00564 HxComplex::tanh() const
00565 {
00566 double den = ::cosh(2*_values[0])+::cos(2*_values[1]);
00567
00568 return HxComplex(::sinh(2*_values[0])/den, ::sin(2*_values[1])/den);
00569 }
00570
00571 inline HxComplex
00572 HxComplex::exp() const
00573 {
00574 double ea = ::exp(_values[0]);
00575 return HxComplex(::cos(_values[1])*ea, ::sin(_values[1])*ea);
00576 }
00577
00578 inline HxComplex
00579 HxComplex::log() const
00580 {
00581 double re = _values[0];
00582 double im = _values[1];
00583 double mag = ::sqrt(re*re+im*im);
00584
00585 return HxComplex(::log(mag), ::atan(re/im));
00586 }
00587
00588 const double theLog10 = 1./log(10.0);
00589
00590 inline HxComplex
00591 HxComplex::log10() const
00592 {
00593 double re = _values[0];
00594 double im = _values[1];
00595 double mag = ::sqrt(re*re+im*im);
00596
00597 return HxComplex(::log(mag)*theLog10, ::atan(re/im)*theLog10);
00598 }
00599
00600 inline HxComplex&
00601 HxComplex::operator+=(const HxComplex& v)
00602 {
00603 _values[0] += v._values[0];
00604 _values[1] += v._values[1];
00605 return *this;
00606 }
00607
00608 inline HxComplex&
00609 HxComplex::operator-=(const HxComplex& v)
00610 {
00611 _values[0] -= v._values[0];
00612 _values[1] -= v._values[1];
00613 return *this;
00614 }
00615
00616 inline HxComplex&
00617 HxComplex::operator*=(const HxComplex& v)
00618 {
00619 double re = _values[0]*v._values[0] - _values[1]*v._values[1];
00620 double im = _values[0]*v._values[1] + _values[1]*v._values[0];
00621 _values[0] = re;
00622 _values[1] = im;
00623 return *this;
00624 }
00625
00626 inline HxComplex&
00627 HxComplex::operator/=(const HxComplex& v)
00628 {
00629 double re = v._values[0];
00630 double im = v._values[1];
00631 double sq = re*re+im*im;
00632
00633 double mulre = _values[0]*re + _values[1]*im;
00634 double mulim = _values[1]*re - _values[0]*im;
00635 _values[0] = mulre / sq;
00636 _values[1] = mulim / sq;
00637
00638 return *this;
00639 }
00640
00641 inline HxComplex
00642 operator+(const HxComplex& v1, const HxComplex& v2)
00643 {
00644 return HxComplex(v1._values[0] + v2._values[0],
00645 v1._values[1] + v2._values[1]);
00646 }
00647
00648 inline HxComplex
00649 operator-(const HxComplex& v1, const HxComplex& v2)
00650 {
00651 return HxComplex(v1._values[0] - v2._values[0],
00652 v1._values[1] - v2._values[1]);
00653 }
00654
00655 inline HxComplex
00656 operator*(const HxComplex& v1, const HxComplex& v2)
00657 {
00658 double re = v1._values[0]*v2._values[0] - v1._values[1]*v2._values[1];
00659 double im = v1._values[0]*v2._values[1] + v1._values[1]*v2._values[0];
00660
00661 return HxComplex(re, im);
00662 }
00663
00664 inline HxComplex
00665 operator/(const HxComplex& v1, const HxComplex& v2)
00666 {
00667 double re = v2._values[0];
00668 double im = v2._values[1];
00669 double sq = re*re+im*im;
00670
00671 double mulre = v1._values[0]*re + v1._values[1]*im;
00672 double mulim = v1._values[1]*re - v1._values[0]*im;
00673
00674 return HxComplex(mulre / sq, mulim / sq);
00675 }
00676
00677 inline HxComplex
00678 HxComplex::min(const HxComplex& v) const
00679 {
00680 return (operator<(v)) ? (*this) : v;
00681 }
00682
00683 inline HxComplex&
00684 HxComplex::minAssign(const HxComplex& v)
00685 {
00686 if (operator<(v))
00687 return *this;
00688 operator=(v);
00689 return *this;
00690 }
00691
00692 inline HxComplex
00693 HxComplex::max(const HxComplex& v) const
00694 {
00695 return (operator>(v)) ? (*this) : v;
00696 }
00697
00698 inline HxComplex&
00699 HxComplex::maxAssign(const HxComplex& v)
00700 {
00701 if (operator>(v))
00702 return *this;
00703 operator=(v);
00704 return *this;
00705 }
00706
00707 inline HxComplex
00708 HxComplex::inf(const HxComplex& v) const
00709 {
00710 return HxComplex((_values[0] < v._values[0]) ? _values[0] : v._values[0],
00711 (_values[1] < v._values[1]) ? _values[1] : v._values[1]);
00712 }
00713
00714 inline HxComplex&
00715 HxComplex::infAssign(const HxComplex& v)
00716 {
00717 _values[0] = (_values[0] < v._values[0]) ? _values[0] : v._values[0];
00718 _values[1] = (_values[1] < v._values[1]) ? _values[1] : v._values[1];
00719 return *this;
00720 }
00721
00722 inline HxComplex
00723 HxComplex::sup(const HxComplex& v) const
00724 {
00725 return HxComplex((_values[0] > v._values[0]) ? _values[0] : v._values[0],
00726 (_values[1] > v._values[1]) ? _values[1] : v._values[1]);
00727 }
00728
00729 inline HxComplex&
00730 HxComplex::supAssign(const HxComplex& v)
00731 {
00732 _values[0] = (_values[0] > v._values[0]) ? _values[0] : v._values[0];
00733 _values[1] = (_values[1] > v._values[1]) ? _values[1] : v._values[1];
00734 return *this;
00735 }
00736
00737 inline HxComplex
00738 HxComplex::pow(const HxComplex& v) const
00739 {
00740 if (v._values[1] == 0) {
00741 double a = _values[0];
00742 double b = _values[1];
00743 double c = v._values[0];
00744 double sq = a*a+b*b;
00745 double arg = ::atan(b/a)*c;
00746 double mul = ::pow(sq, c/2)*::exp(a*c);
00747
00748 return HxComplex(mul*::cos(arg), mul*::sin(arg));
00749 }
00750
00751 return (v * (*this).log()).exp();
00752 }
00753
00754 inline HxComplex
00755 HxComplex::mod(const HxComplex&) const
00756 {
00757 return (*this);
00758 }
00759
00760 inline HxComplex
00761 HxComplex::and(const HxComplex&) const
00762 {
00763 return (*this);
00764 }
00765
00766 inline HxComplex
00767 HxComplex::or(const HxComplex&) const
00768 {
00769 return (*this);
00770 }
00771
00772 inline HxComplex
00773 HxComplex::xor(const HxComplex&) const
00774 {
00775 return (*this);
00776 }
00777
00778 inline HxComplex
00779 HxComplex::leftShift(const HxComplex&) const
00780 {
00781 return (*this);
00782 }
00783
00784 inline HxComplex
00785 HxComplex::rightShift(const HxComplex&) const
00786 {
00787 return (*this);
00788 }
00789
00790 inline HxComplex
00791 HxComplex::cross(const HxComplex&) const
00792 {
00793 return HxComplex(0, 0);
00794 }
00795
00796 inline HxComplex
00797 HxComplex::sum() const
00798 {
00799 return *this;
00800 }
00801
00802 inline HxComplex
00803 HxComplex::product() const
00804 {
00805 return *this;
00806 }
00807
00808 inline HxScalarDouble
00809 HxComplex::min() const
00810 {
00811 return (_values[0] < _values[1]) ? _values[0] : _values[1];
00812 }
00813
00814 inline HxScalarDouble
00815 HxComplex::max() const
00816 {
00817 return (_values[0] > _values[1]) ? _values[0] : _values[1];
00818 }
00819
00820 #endif