3 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Jorma Olavi Tähtinen, Brian Gough
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 /* Basic complex arithmetic functions
22 * Original version by Jorma Olavi Tähtinen <jotahtin@cc.hut.fi>
24 * Modified for GSL by Brian Gough, 3/2000
27 /* The following references describe the methods used in these
30 * T. E. Hull and Thomas F. Fairgrieve and Ping Tak Peter Tang,
31 * "Implementing Complex Elementary Functions Using Exception
32 * Handling", ACM Transactions on Mathematical Software, Volume 20
33 * (1994), pp 215-244, Corrigenda, p553
35 * Hull et al, "Implementing the complex arcsin and arccosine
36 * functions using exception handling", ACM Transactions on
37 * Mathematical Software, Volume 23 (1997) pp 299-335
39 * Abramowitz and Stegun, Handbook of Mathematical Functions, "Inverse
40 * Circular Functions in Terms of Real and Imaginary Parts", Formulas
41 * 4.4.37, 4.4.38, 4.4.39
46 #include <gsl/gsl_math.h>
47 #include <gsl/gsl_complex.h>
48 #include <gsl/gsl_complex_math.h>
50 /**********************************************************************
52 **********************************************************************/
54 #ifndef HIDE_INLINE_STATIC
56 gsl_complex_rect (double x, double y)
57 { /* return z = x + i y */
59 GSL_SET_COMPLEX (&z, x, y);
65 gsl_complex_polar (double r, double theta)
66 { /* return z = r exp(i theta) */
68 GSL_SET_COMPLEX (&z, r * cos (theta), r * sin (theta));
72 /**********************************************************************
73 * Properties of complex numbers
74 **********************************************************************/
77 gsl_complex_arg (gsl_complex z)
78 { /* return arg(z), -pi < arg(z) <= +pi */
79 double x = GSL_REAL (z);
80 double y = GSL_IMAG (z);
82 if (x == 0.0 && y == 0.0)
91 gsl_complex_abs (gsl_complex z)
93 return hypot (GSL_REAL (z), GSL_IMAG (z));
97 gsl_complex_abs2 (gsl_complex z)
99 double x = GSL_REAL (z);
100 double y = GSL_IMAG (z);
102 return (x * x + y * y);
106 gsl_complex_logabs (gsl_complex z)
107 { /* return log|z| */
108 double xabs = fabs (GSL_REAL (z));
109 double yabs = fabs (GSL_IMAG (z));
123 /* Handle underflow when u is close to 0 */
125 return log (max) + 0.5 * log1p (u * u);
129 /***********************************************************************
130 * Complex arithmetic operators
131 ***********************************************************************/
134 gsl_complex_add (gsl_complex a, gsl_complex b)
136 double ar = GSL_REAL (a), ai = GSL_IMAG (a);
137 double br = GSL_REAL (b), bi = GSL_IMAG (b);
140 GSL_SET_COMPLEX (&z, ar + br, ai + bi);
145 gsl_complex_add_real (gsl_complex a, double x)
148 GSL_SET_COMPLEX (&z, GSL_REAL (a) + x, GSL_IMAG (a));
153 gsl_complex_add_imag (gsl_complex a, double y)
156 GSL_SET_COMPLEX (&z, GSL_REAL (a), GSL_IMAG (a) + y);
162 gsl_complex_sub (gsl_complex a, gsl_complex b)
164 double ar = GSL_REAL (a), ai = GSL_IMAG (a);
165 double br = GSL_REAL (b), bi = GSL_IMAG (b);
168 GSL_SET_COMPLEX (&z, ar - br, ai - bi);
173 gsl_complex_sub_real (gsl_complex a, double x)
176 GSL_SET_COMPLEX (&z, GSL_REAL (a) - x, GSL_IMAG (a));
181 gsl_complex_sub_imag (gsl_complex a, double y)
184 GSL_SET_COMPLEX (&z, GSL_REAL (a), GSL_IMAG (a) - y);
189 gsl_complex_mul (gsl_complex a, gsl_complex b)
191 double ar = GSL_REAL (a), ai = GSL_IMAG (a);
192 double br = GSL_REAL (b), bi = GSL_IMAG (b);
195 GSL_SET_COMPLEX (&z, ar * br - ai * bi, ar * bi + ai * br);
200 gsl_complex_mul_real (gsl_complex a, double x)
203 GSL_SET_COMPLEX (&z, x * GSL_REAL (a), x * GSL_IMAG (a));
208 gsl_complex_mul_imag (gsl_complex a, double y)
211 GSL_SET_COMPLEX (&z, -y * GSL_IMAG (a), y * GSL_REAL (a));
216 gsl_complex_div (gsl_complex a, gsl_complex b)
218 double ar = GSL_REAL (a), ai = GSL_IMAG (a);
219 double br = GSL_REAL (b), bi = GSL_IMAG (b);
221 double s = 1.0 / gsl_complex_abs (b);
226 double zr = (ar * sbr + ai * sbi) * s;
227 double zi = (ai * sbr - ar * sbi) * s;
230 GSL_SET_COMPLEX (&z, zr, zi);
235 gsl_complex_div_real (gsl_complex a, double x)
238 GSL_SET_COMPLEX (&z, GSL_REAL (a) / x, GSL_IMAG (a) / x);
243 gsl_complex_div_imag (gsl_complex a, double y)
246 GSL_SET_COMPLEX (&z, GSL_IMAG (a) / y, - GSL_REAL (a) / y);
251 gsl_complex_conjugate (gsl_complex a)
254 GSL_SET_COMPLEX (&z, GSL_REAL (a), -GSL_IMAG (a));
259 gsl_complex_negative (gsl_complex a)
262 GSL_SET_COMPLEX (&z, -GSL_REAL (a), -GSL_IMAG (a));
267 gsl_complex_inverse (gsl_complex a)
269 double s = 1.0 / gsl_complex_abs (a);
272 GSL_SET_COMPLEX (&z, (GSL_REAL (a) * s) * s, -(GSL_IMAG (a) * s) * s);
276 /**********************************************************************
277 * Elementary complex functions
278 **********************************************************************/
281 gsl_complex_sqrt (gsl_complex a)
285 if (GSL_REAL (a) == 0.0 && GSL_IMAG (a) == 0.0)
287 GSL_SET_COMPLEX (&z, 0, 0);
291 double x = fabs (GSL_REAL (a));
292 double y = fabs (GSL_IMAG (a));
298 w = sqrt (x) * sqrt (0.5 * (1.0 + sqrt (1.0 + t * t)));
303 w = sqrt (y) * sqrt (0.5 * (t + sqrt (1.0 + t * t)));
306 if (GSL_REAL (a) >= 0.0)
308 double ai = GSL_IMAG (a);
309 GSL_SET_COMPLEX (&z, w, ai / (2.0 * w));
313 double ai = GSL_IMAG (a);
314 double vi = (ai >= 0) ? w : -w;
315 GSL_SET_COMPLEX (&z, ai / (2.0 * vi), vi);
323 gsl_complex_sqrt_real (double x)
329 GSL_SET_COMPLEX (&z, sqrt (x), 0.0);
333 GSL_SET_COMPLEX (&z, 0.0, sqrt (-x));
340 gsl_complex_exp (gsl_complex a)
342 double rho = exp (GSL_REAL (a));
343 double theta = GSL_IMAG (a);
346 GSL_SET_COMPLEX (&z, rho * cos (theta), rho * sin (theta));
351 gsl_complex_pow (gsl_complex a, gsl_complex b)
355 if (GSL_REAL (a) == 0 && GSL_IMAG (a) == 0.0)
357 if (GSL_REAL (b) == 0 && GSL_IMAG (b) == 0.0)
359 GSL_SET_COMPLEX (&z, 1.0, 0.0);
363 GSL_SET_COMPLEX (&z, 0.0, 0.0);
366 else if (GSL_REAL (b) == 1.0 && GSL_IMAG (b) == 0.0)
370 else if (GSL_REAL (b) == -1.0 && GSL_IMAG (b) == 0.0)
372 return gsl_complex_inverse (a);
376 double logr = gsl_complex_logabs (a);
377 double theta = gsl_complex_arg (a);
379 double br = GSL_REAL (b), bi = GSL_IMAG (b);
381 double rho = exp (logr * br - bi * theta);
382 double beta = theta * br + bi * logr;
384 GSL_SET_COMPLEX (&z, rho * cos (beta), rho * sin (beta));
391 gsl_complex_pow_real (gsl_complex a, double b)
395 if (GSL_REAL (a) == 0 && GSL_IMAG (a) == 0)
397 GSL_SET_COMPLEX (&z, 0, 0);
401 double logr = gsl_complex_logabs (a);
402 double theta = gsl_complex_arg (a);
403 double rho = exp (logr * b);
404 double beta = theta * b;
405 GSL_SET_COMPLEX (&z, rho * cos (beta), rho * sin (beta));
412 gsl_complex_log (gsl_complex a)
414 double logr = gsl_complex_logabs (a);
415 double theta = gsl_complex_arg (a);
418 GSL_SET_COMPLEX (&z, logr, theta);
423 gsl_complex_log10 (gsl_complex a)
425 return gsl_complex_mul_real (gsl_complex_log (a), 1 / log (10.));
429 gsl_complex_log_b (gsl_complex a, gsl_complex b)
431 return gsl_complex_div (gsl_complex_log (a), gsl_complex_log (b));
434 /***********************************************************************
435 * Complex trigonometric functions
436 ***********************************************************************/
439 gsl_complex_sin (gsl_complex a)
441 double R = GSL_REAL (a), I = GSL_IMAG (a);
447 /* avoid returing negative zero (-0.0) for the imaginary part */
449 GSL_SET_COMPLEX (&z, sin (R), 0.0);
453 GSL_SET_COMPLEX (&z, sin (R) * cosh (I), cos (R) * sinh (I));
460 gsl_complex_cos (gsl_complex a)
462 double R = GSL_REAL (a), I = GSL_IMAG (a);
468 /* avoid returing negative zero (-0.0) for the imaginary part */
470 GSL_SET_COMPLEX (&z, cos (R), 0.0);
474 GSL_SET_COMPLEX (&z, cos (R) * cosh (I), sin (R) * sinh (-I));
481 gsl_complex_tan (gsl_complex a)
483 double R = GSL_REAL (a), I = GSL_IMAG (a);
489 double D = pow (cos (R), 2.0) + pow (sinh (I), 2.0);
491 GSL_SET_COMPLEX (&z, 0.5 * sin (2 * R) / D, 0.5 * sinh (2 * I) / D);
496 double C = 2 * u / (1 - pow (u, 2.0));
497 double D = 1 + pow (cos (R), 2.0) * pow (C, 2.0);
499 double S = pow (C, 2.0);
500 double T = 1.0 / tanh (I);
502 GSL_SET_COMPLEX (&z, 0.5 * sin (2 * R) * S / D, T / D);
509 gsl_complex_sec (gsl_complex a)
511 gsl_complex z = gsl_complex_cos (a);
512 return gsl_complex_inverse (z);
516 gsl_complex_csc (gsl_complex a)
518 gsl_complex z = gsl_complex_sin (a);
519 return gsl_complex_inverse(z);
524 gsl_complex_cot (gsl_complex a)
526 gsl_complex z = gsl_complex_tan (a);
527 return gsl_complex_inverse (z);
530 /**********************************************************************
531 * Inverse Complex Trigonometric Functions
532 **********************************************************************/
535 gsl_complex_arcsin (gsl_complex a)
536 { /* z = arcsin(a) */
537 double R = GSL_REAL (a), I = GSL_IMAG (a);
542 z = gsl_complex_arcsin_real (R);
546 double x = fabs (R), y = fabs (I);
547 double r = hypot (x + 1, y), s = hypot (x - 1, y);
548 double A = 0.5 * (r + s);
554 const double A_crossover = 1.5, B_crossover = 0.6417;
556 if (B <= B_crossover)
564 double D = 0.5 * (A + x) * (y2 / (r + x + 1) + (s + (1 - x)));
565 real = atan (x / sqrt (D));
570 double D = 0.5 * (Apx / (r + x + 1) + Apx / (s + (x - 1)));
571 real = atan (x / (y * sqrt (D)));
575 if (A <= A_crossover)
581 Am1 = 0.5 * (y2 / (r + (x + 1)) + y2 / (s + (1 - x)));
585 Am1 = 0.5 * (y2 / (r + (x + 1)) + (s + (x - 1)));
588 imag = log1p (Am1 + sqrt (Am1 * (A + 1)));
592 imag = log (A + sqrt (A * A - 1));
595 GSL_SET_COMPLEX (&z, (R >= 0) ? real : -real, (I >= 0) ? imag : -imag);
602 gsl_complex_arcsin_real (double a)
603 { /* z = arcsin(a) */
608 GSL_SET_COMPLEX (&z, asin (a), 0.0);
614 GSL_SET_COMPLEX (&z, -M_PI_2, acosh (-a));
618 GSL_SET_COMPLEX (&z, M_PI_2, -acosh (a));
626 gsl_complex_arccos (gsl_complex a)
627 { /* z = arccos(a) */
628 double R = GSL_REAL (a), I = GSL_IMAG (a);
633 z = gsl_complex_arccos_real (R);
637 double x = fabs (R), y = fabs (I);
638 double r = hypot (x + 1, y), s = hypot (x - 1, y);
639 double A = 0.5 * (r + s);
645 const double A_crossover = 1.5, B_crossover = 0.6417;
647 if (B <= B_crossover)
655 double D = 0.5 * (A + x) * (y2 / (r + x + 1) + (s + (1 - x)));
656 real = atan (sqrt (D) / x);
661 double D = 0.5 * (Apx / (r + x + 1) + Apx / (s + (x - 1)));
662 real = atan ((y * sqrt (D)) / x);
666 if (A <= A_crossover)
672 Am1 = 0.5 * (y2 / (r + (x + 1)) + y2 / (s + (1 - x)));
676 Am1 = 0.5 * (y2 / (r + (x + 1)) + (s + (x - 1)));
679 imag = log1p (Am1 + sqrt (Am1 * (A + 1)));
683 imag = log (A + sqrt (A * A - 1));
686 GSL_SET_COMPLEX (&z, (R >= 0) ? real : M_PI - real, (I >= 0) ? -imag : imag);
693 gsl_complex_arccos_real (double a)
694 { /* z = arccos(a) */
699 GSL_SET_COMPLEX (&z, acos (a), 0);
705 GSL_SET_COMPLEX (&z, M_PI, -acosh (-a));
709 GSL_SET_COMPLEX (&z, 0, acosh (a));
717 gsl_complex_arctan (gsl_complex a)
718 { /* z = arctan(a) */
719 double R = GSL_REAL (a), I = GSL_IMAG (a);
724 GSL_SET_COMPLEX (&z, atan (R), 0);
728 /* FIXME: This is a naive implementation which does not fully
729 take into account cancellation errors, overflow, underflow
730 etc. It would benefit from the Hull et al treatment. */
732 double r = hypot (R, I);
736 double u = 2 * I / (1 + r * r);
738 /* FIXME: the following cross-over should be optimized but 0.1
743 imag = 0.25 * (log1p (u) - log1p (-u));
747 double A = hypot (R, I + 1);
748 double B = hypot (R, I - 1);
749 imag = 0.5 * log (A / B);
756 GSL_SET_COMPLEX (&z, M_PI_2, imag);
760 GSL_SET_COMPLEX (&z, -M_PI_2, imag);
764 GSL_SET_COMPLEX (&z, 0, imag);
769 GSL_SET_COMPLEX (&z, 0.5 * atan2 (2 * R, ((1 + r) * (1 - r))), imag);
777 gsl_complex_arcsec (gsl_complex a)
778 { /* z = arcsec(a) */
779 gsl_complex z = gsl_complex_inverse (a);
780 return gsl_complex_arccos (z);
784 gsl_complex_arcsec_real (double a)
785 { /* z = arcsec(a) */
788 if (a <= -1.0 || a >= 1.0)
790 GSL_SET_COMPLEX (&z, acos (1 / a), 0.0);
796 GSL_SET_COMPLEX (&z, 0, acosh (1 / a));
800 GSL_SET_COMPLEX (&z, M_PI, -acosh (-1 / a));
808 gsl_complex_arccsc (gsl_complex a)
809 { /* z = arccsc(a) */
810 gsl_complex z = gsl_complex_inverse (a);
811 return gsl_complex_arcsin (z);
815 gsl_complex_arccsc_real (double a)
816 { /* z = arccsc(a) */
819 if (a <= -1.0 || a >= 1.0)
821 GSL_SET_COMPLEX (&z, asin (1 / a), 0.0);
827 GSL_SET_COMPLEX (&z, M_PI_2, -acosh (1 / a));
831 GSL_SET_COMPLEX (&z, -M_PI_2, acosh (-1 / a));
839 gsl_complex_arccot (gsl_complex a)
840 { /* z = arccot(a) */
843 if (GSL_REAL (a) == 0.0 && GSL_IMAG (a) == 0.0)
845 GSL_SET_COMPLEX (&z, M_PI_2, 0);
849 z = gsl_complex_inverse (a);
850 z = gsl_complex_arctan (z);
856 /**********************************************************************
857 * Complex Hyperbolic Functions
858 **********************************************************************/
861 gsl_complex_sinh (gsl_complex a)
863 double R = GSL_REAL (a), I = GSL_IMAG (a);
866 GSL_SET_COMPLEX (&z, sinh (R) * cos (I), cosh (R) * sin (I));
871 gsl_complex_cosh (gsl_complex a)
873 double R = GSL_REAL (a), I = GSL_IMAG (a);
876 GSL_SET_COMPLEX (&z, cosh (R) * cos (I), sinh (R) * sin (I));
881 gsl_complex_tanh (gsl_complex a)
883 double R = GSL_REAL (a), I = GSL_IMAG (a);
889 double D = pow (cos (I), 2.0) + pow (sinh (R), 2.0);
891 GSL_SET_COMPLEX (&z, sinh (R) * cosh (R) / D, 0.5 * sin (2 * I) / D);
895 double D = pow (cos (I), 2.0) + pow (sinh (R), 2.0);
896 double F = 1 + pow (cos (I) / sinh (R), 2.0);
898 GSL_SET_COMPLEX (&z, 1.0 / (tanh (R) * F), 0.5 * sin (2 * I) / D);
905 gsl_complex_sech (gsl_complex a)
907 gsl_complex z = gsl_complex_cosh (a);
908 return gsl_complex_inverse (z);
912 gsl_complex_csch (gsl_complex a)
914 gsl_complex z = gsl_complex_sinh (a);
915 return gsl_complex_inverse (z);
919 gsl_complex_coth (gsl_complex a)
921 gsl_complex z = gsl_complex_tanh (a);
922 return gsl_complex_inverse (z);
925 /**********************************************************************
926 * Inverse Complex Hyperbolic Functions
927 **********************************************************************/
930 gsl_complex_arcsinh (gsl_complex a)
931 { /* z = arcsinh(a) */
932 gsl_complex z = gsl_complex_mul_imag(a, 1.0);
933 z = gsl_complex_arcsin (z);
934 z = gsl_complex_mul_imag (z, -1.0);
939 gsl_complex_arccosh (gsl_complex a)
940 { /* z = arccosh(a) */
941 gsl_complex z = gsl_complex_arccos (a);
942 z = gsl_complex_mul_imag (z, GSL_IMAG(z) > 0 ? -1.0 : 1.0);
947 gsl_complex_arccosh_real (double a)
948 { /* z = arccosh(a) */
953 GSL_SET_COMPLEX (&z, acosh (a), 0);
959 GSL_SET_COMPLEX (&z, 0, acos (a));
963 GSL_SET_COMPLEX (&z, acosh (-a), M_PI);
971 gsl_complex_arctanh (gsl_complex a)
972 { /* z = arctanh(a) */
973 if (GSL_IMAG (a) == 0.0)
975 return gsl_complex_arctanh_real (GSL_REAL (a));
979 gsl_complex z = gsl_complex_mul_imag(a, 1.0);
980 z = gsl_complex_arctan (z);
981 z = gsl_complex_mul_imag (z, -1.0);
987 gsl_complex_arctanh_real (double a)
988 { /* z = arctanh(a) */
991 if (a > -1.0 && a < 1.0)
993 GSL_SET_COMPLEX (&z, atanh (a), 0);
997 GSL_SET_COMPLEX (&z, atanh (1 / a), (a < 0) ? M_PI_2 : -M_PI_2);
1004 gsl_complex_arcsech (gsl_complex a)
1005 { /* z = arcsech(a); */
1006 gsl_complex t = gsl_complex_inverse (a);
1007 return gsl_complex_arccosh (t);
1011 gsl_complex_arccsch (gsl_complex a)
1012 { /* z = arccsch(a) */
1013 gsl_complex t = gsl_complex_inverse (a);
1014 return gsl_complex_arcsinh (t);
1018 gsl_complex_arccoth (gsl_complex a)
1019 { /* z = arccoth(a) */
1020 gsl_complex t = gsl_complex_inverse (a);
1021 return gsl_complex_arctanh (t);