My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
complex.cpp
Go to the documentation of this file.
1 /*
2  * complex.cpp - complex number class implementation
3  *
4  * Copyright (C) 2003, 2004, 2005, 2006, 2007 Stefan Jahn <stefan@lkcc.org>
5  * Copyright (C) 2006 Gunther Kraut <gn.kraut@t-online.de>
6  *
7  * This is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this package; see the file COPYING. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  * $Id: complex.cpp 1825 2011-03-11 20:42:14Z ela $
23  *
24  */
25 
31 #if HAVE_CONFIG_H
32 # include <config.h>
33 #endif
34 
35 #include <math.h>
36 
37 #include "complex.h"
38 #include "consts.h"
39 #include "fspecial.h"
40 
41 using namespace fspecial;
42 
50 nr_complex_t rect (const nr_double_t x, const nr_double_t y) {
51  return nr_complex_t (x, y);
52 }
53 
54 #ifndef HAVE_CXX_COMPLEX_NORM
55 
62 nr_double_t norm (const nr_complex_t z) {
63  nr_double_t r = real (z);
64  nr_double_t i = imag (z);
65  return r * r + i * i;
66 }
67 #endif
68 
69 #ifndef HAVE_CXX_COMPLEX_POLAR
70 
76 nr_complex_t polar (const nr_double_t mag, const nr_double_t ang) {
77  return rect (mag * cos (ang), mag * sin (ang));
78 }
79 #endif
80 
81 #ifndef HAVE_CXX_COMPLEX_POLAR_COMPLEX
82 
90  return a * exp (rect (imag (p), -real (p)));
91 }
92 #endif
93 
94 #ifndef HAVE_CXX_COMPLEX_COS
95 
101  nr_double_t r = real (z);
102  nr_double_t i = imag (z);
103  return (polar (exp (-i), r) + polar (exp (i), -r)) / 2.0;
104 }
105 #endif
106 
107 #ifndef HAVE_CXX_COMPLEX_ACOS
108 
114  nr_double_t r = real (z);
115  nr_double_t i = imag (z);
116 #if 0
117  return rect (0.0, -2.0) * log (M_SQRT1_2 * (sqrt (z + 1) + sqrt (z - 1)));
118 #else
119  nr_complex_t y = sqrt (z * z - 1.0);
120  if (r * i < 0.0) y = -y;
121  return rect (0, -1.0) * log (z + y);
122 #endif
123 }
124 #endif
125 
126 #ifndef HAVE_CXX_COMPLEX_COSH
127 
133  nr_double_t r = real (z);
134  nr_double_t i = imag (z);
135  return (polar (exp (r), i) + polar (exp (-r), -i)) / 2.0;
136 }
137 #endif
138 
139 #ifndef HAVE_CXX_COMPLEX_ACOSH
140 
146  return log (z + sqrt (z * z - 1.0));
147 }
148 #endif
149 
150 #ifndef HAVE_CXX_COMPLEX_EXP
151 
157  nr_double_t mag = exp (real (z));
158  return nr_complex_t (mag * cos (imag (z)), mag * sin (imag (z)));
159 }
160 #endif
161 
169  nr_double_t mag = limexp (real (z));
170  return nr_complex_t (mag * cos (imag (z)), mag * sin (imag (z)));
171 }
172 
173 #ifndef HAVE_CXX_COMPLEX_LOG
174 
180  nr_double_t phi = arg (z);
181  return nr_complex_t (log (abs (z)), phi);
182 }
183 #endif
184 
185 #ifndef HAVE_CXX_COMPLEX_LOG10
186 
192  nr_double_t phi = arg (z);
193  return nr_complex_t (log10 (abs (z)), phi * M_LOG10E);
194 }
195 #endif
196 
197 #ifndef HAVE_CXX_COMPLEX_LOG2
198 
204  nr_double_t phi = arg (z);
205  return nr_complex_t (log (abs (z)) * M_LOG2E, phi * M_LOG2E);
206 }
207 #endif
208 
209 #ifndef HAVE_CXX_COMPLEX_POW
210 
216 nr_complex_t pow (const nr_complex_t z, const nr_double_t d) {
217  return polar (pow (abs (z), d), arg (z) * d);
218 }
219 
226 nr_complex_t pow (const nr_double_t d, const nr_complex_t z) {
227  return exp (z * log (d));
228 }
229 
237  return exp (z2 * log (z1));
238 }
239 #endif
240 
241 #ifndef HAVE_CXX_COMPLEX_SIN
242 
248  nr_double_t r = real (z);
249  nr_double_t i = imag (z);
250  return (polar (exp (-i), r - M_PI_2) - polar (exp (i), -r - M_PI_2)) / 2.0;
251 }
252 #endif
253 
254 #ifndef HAVE_CXX_COMPLEX_ASIN
255 
261  nr_double_t r = real (z);
262  nr_double_t i = imag (z);
263  return nr_complex_t (0.0, -1.0) * log (rect (-i, r) + sqrt (1.0 - z * z));
264 }
265 #endif
266 
267 #ifndef HAVE_CXX_COMPLEX_SINH
268 
274  nr_double_t r = real (z);
275  nr_double_t i = imag (z);
276  return (polar (exp (r), i) - polar (exp (-r), -i)) / 2.0;
277 }
278 #endif
279 
280 #ifndef HAVE_CXX_COMPLEX_ASINH
281 
287  return log (z + sqrt (z * z + 1.0));
288 }
289 #endif
290 
291 #ifndef HAVE_CXX_COMPLEX_SQRT
292 
301  nr_double_t r = real (z);
302  nr_double_t i = imag (z);
303 #if 0
304  if (i == 0.0) {
305  return r < 0.0 ? nr_complex_t (0.0, sqrt (-r)) : nr_complex_t (sqrt (r));
306  } else {
307  nr_double_t phi = arg (z);
308  return polar (sqrt (fabs (z)), phi / 2.0);
309  }
310 #else /* better numerical behaviour, avoiding arg() and polar() */
311  if (r == 0.0 && i == 0.0) {
312  return nr_complex_t (0.0, 0.0);
313  } else {
314  nr_double_t x = fabs (r);
315  nr_double_t y = fabs (i);
316  nr_double_t k;
317  if (x >= y) {
318  nr_double_t t = y / x;
319  k = sqrt (x) * sqrt (0.5 * (1.0 + sqrt (1.0 + t * t)));
320  } else {
321  nr_double_t t = x / y;
322  k = sqrt (y) * sqrt (0.5 * (t + sqrt (1.0 + t * t)));
323  }
324  if (r >= 0.0) {
325  return nr_complex_t (k, i / (2.0 * k));
326  } else {
327  nr_double_t vi = (i >= 0) ? k : -k;
328  return nr_complex_t (i / (2.0 * vi), vi);
329  }
330  }
331 #endif
332 }
333 #endif
334 
335 #ifndef HAVE_CXX_COMPLEX_TAN
336 
342  nr_double_t r = 2.0 * real (z);
343  nr_double_t i = 2.0 * imag (z);
344  return rect (0.0, -1.0) + rect (0.0, 2.0) / (polar (exp (-i), r) + 1.0);
345 }
346 #endif
347 
348 #ifndef HAVE_CXX_COMPLEX_ATAN
349 
355  return rect (0.0, -0.5) * log (rect (0, 2) / (z + rect (0, 1)) - 1.0);
356 }
357 #endif
358 
359 #ifndef HAVE_CXX_COMPLEX_ATAN2
360 
369  nr_complex_t a = atan (y / x);
370  return real (x) > 0.0 ? a : -a;
371 }
372 #endif
373 
374 #ifndef HAVE_CXX_COMPLEX_TANH
375 
381  nr_double_t r = 2.0 * real (z);
382  nr_double_t i = 2.0 * imag (z);
383  return 1.0 - 2.0 / (polar (exp (r), i) + 1.0);
384 }
385 #endif
386 
387 #ifndef HAVE_CXX_COMPLEX_ATANH
388 
394  return 0.5 * log ( 2.0 / (1.0 - z) - 1.0);
395 }
396 #endif
397 
404  nr_double_t r = 2.0 * real (z);
405  nr_double_t i = 2.0 * imag (z);
406  return rect (0.0, 1.0) + rect (0.0, 2.0) / (polar (exp (-i), r) - 1.0);
407 }
408 
415  return rect (0.0, -0.5) * log (rect (0, 2) / (z - rect (0, 1)) + 1.0);
416 }
417 
425  return log ((1.0 + sqrt (1.0 - z * z)) / z);
426 }
427 
434  nr_double_t r = 2.0 * real (z);
435  nr_double_t i = 2.0 * imag (z);
436  return 1.0 + 2.0 / (polar (exp (r), i) - 1.0);
437 }
438 
445  return 0.5 * log (2.0 / (z - 1.0) + 1.0);
446 }
447 
455 nr_double_t dB (const nr_complex_t z) {
456  return 10.0 * log10 (norm (z));
457 }
458 
466  return (z - zref) / (z + zref);
467 }
468 
475  return (1.0 - y * zref) / (1.0 + y * zref);
476 }
477 
484  return zref * (1.0 + r) / (1.0 - r);
485 }
486 
493  return (1.0 - r) / (1.0 + r) / zref;
494 }
495 
496 #ifndef HAVE_CXX_COMPLEX_FLOOR
497 
507  return rect (floor (real (z)), floor (imag (z)));
508 }
509 #endif
510 
511 #ifndef HAVE_CXX_COMPLEX_FMOD
512 
521  nr_complex_t n = floor (x / y);
522  return x - n * y;
523 }
524 
533 nr_complex_t fmod (const nr_complex_t x, const nr_double_t y) {
534  nr_complex_t n = floor (x / y);
535  return x - n * y;
536 }
537 
546 nr_complex_t fmod (const nr_double_t x, const nr_complex_t y) {
547  nr_complex_t n = floor (x / y);
548  return x - n * y;
549 }
550 #endif
551 
566  if (z == 0) return 0;
567  return z / abs (z);
568 }
569 
584  if (z == 0) return nr_complex_t (1);
585  return z / abs (z);
586 }
587 
599 nr_double_t xhypot (const nr_complex_t a, const nr_complex_t b) {
600  nr_double_t c = norm (a);
601  nr_double_t d = norm (b);
602  if (c > d)
603  return abs (a) * sqrt (1 + d / c);
604  else if (d == 0)
605  return 0;
606  else
607  return abs (b) * sqrt (1 + c / d);
608 }
609 
611 nr_double_t xhypot (const nr_double_t a, const nr_complex_t b) {
612  return xhypot (nr_complex_t (a), b);
613 }
614 
616 nr_double_t xhypot (const nr_complex_t a, const nr_double_t b) {
617  return xhypot (a, nr_complex_t (b));
618 }
619 
628  if (z == 0) return 1;
629  return sin (z) / z;
630 }
631 
640  return rect (ceil (real (z)), ceil (imag (z)));
641 }
642 
652  nr_double_t x = real (z);
653  nr_double_t y = imag (z);
654  x = (x > 0) ? floor (x) : ceil (x);
655  y = (y > 0) ? floor (y) : ceil (y);
656  return rect (x, y);
657 }
658 
667  return rect (round (real (z)), round (imag (z)));
668 }
669 
678  return rect (trunc (real (z)), trunc (imag (z)));
679 }
680 
688  nr_double_t r = real (z);
689  nr_double_t i = imag (z);
690  return rect (r * r - i * i, 2 * r * i);
691 }
692 
702  nr_double_t x = real (z);
703  nr_double_t y = imag (z);
704  if (x < 0.0)
705  x = 0.0;
706  else if (x > 0.0)
707  x = 1.0;
708  else
709  x = 0.5;
710  if (y < 0.0)
711  y = 0.0;
712  else if (y > 0.0)
713  y = 1.0;
714  else
715  y = 0.5;
716  return rect (x, y);
717 }
718 
719 nr_complex_t cbesselj (unsigned int, nr_complex_t);
720 
728 nr_complex_t jn (const int n, const nr_complex_t z) {
729  return cbesselj (n, z);
730 }
731 
739 nr_complex_t yn (const int n, const nr_complex_t z) {
740  return rect (yn (n, real (z)), 0);
741 }
742 
750  return rect (i0 (real (z)), 0);
751 }
752 
760  return rect (erf (real (z)), 0);
761 }
762 
770  return rect (erfc (real (z)), 0);
771 }
772 
780  return rect (erfinv (real (z)), 0);
781 }
782 
790  return rect (erfcinv (real (z)), 0);
791 }
792 
799 bool operator==(const nr_complex_t z1, const nr_complex_t z2) {
800  return (real (z1) == real (z2)) && (imag (z1) == imag (z2));
801 }
802 
809 bool operator!=(const nr_complex_t z1, const nr_complex_t z2) {
810  return (real (z1) != real (z2)) || (imag (z1) != imag (z2));
811 }
812 
816 bool operator>=(const nr_complex_t z1, const nr_complex_t z2) {
817  return norm (z1) >= norm (z2);
818 }
819 
823 bool operator<=(const nr_complex_t z1, const nr_complex_t z2) {
824  return norm (z1) <= norm (z2);
825 }
826 
830 bool operator>(const nr_complex_t z1, const nr_complex_t z2) {
831  return norm (z1) > norm (z2);
832 }
833 
837 bool operator<(const nr_complex_t z1, const nr_complex_t z2) {
838  return norm (z1) < norm (z2);
839 }
840 
845  return z1 - z2 * floor (z1 / z2);
846 }
847 
851 nr_complex_t operator%(const nr_complex_t z1, const nr_double_t r2) {
852  return z1 - r2 * floor (z1 / r2);
853 }
854 
858 nr_complex_t operator%(const nr_double_t r1, const nr_complex_t z2) {
859  return r1 - z2 * floor (r1 / z2);
860 }