📄 math.c
字号:
/* complex/math.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000 Jorma Olavi T鋒tinen, Brian Gough * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* Basic complex arithmetic functions * Original version by Jorma Olavi T鋒tinen <jotahtin@cc.hut.fi> * * Modified for GSL by Brian Gough, 3/2000 *//* The following references describe the methods used in these * functions, * * T. E. Hull and Thomas F. Fairgrieve and Ping Tak Peter Tang, * "Implementing Complex Elementary Functions Using Exception * Handling", ACM Transactions on Mathematical Software, Volume 20 * (1994), pp 215-244, Corrigenda, p553 * * Hull et al, "Implementing the complex arcsin and arccosine * functions using exception handling", ACM Transactions on * Mathematical Software, Volume 23 (1997) pp 299-335 * * Abramowitz and Stegun, Handbook of Mathematical Functions, "Inverse * Circular Functions in Terms of Real and Imaginary Parts", Formulas * 4.4.37, 4.4.38, 4.4.39 */#include <config.h>#include <math.h>#include <gsl/gsl_math.h>#include <gsl/gsl_complex.h>#include <gsl/gsl_complex_math.h>/********************************************************************** * Complex numbers **********************************************************************/#ifndef HIDE_INLINE_STATICgsl_complexgsl_complex_rect (double x, double y){ /* return z = x + i y */ gsl_complex z; GSL_SET_COMPLEX (&z, x, y); return z;}#endifgsl_complexgsl_complex_polar (double r, double theta){ /* return z = r exp(i theta) */ gsl_complex z; GSL_SET_COMPLEX (&z, r * cos (theta), r * sin (theta)); return z;}/********************************************************************** * Properties of complex numbers **********************************************************************/doublegsl_complex_arg (gsl_complex z){ /* return arg(z), -pi < arg(z) <= +pi */ double x = GSL_REAL (z); double y = GSL_IMAG (z); if (x == 0.0 && y == 0.0) { return 0; } return atan2 (y, x);}doublegsl_complex_abs (gsl_complex z){ /* return |z| */ return hypot (GSL_REAL (z), GSL_IMAG (z));}doublegsl_complex_abs2 (gsl_complex z){ /* return |z|^2 */ double x = GSL_REAL (z); double y = GSL_IMAG (z); return (x * x + y * y);}doublegsl_complex_logabs (gsl_complex z){ /* return log|z| */ double xabs = fabs (GSL_REAL (z)); double yabs = fabs (GSL_IMAG (z)); double max, u; if (xabs >= yabs) { max = xabs; u = yabs / xabs; } else { max = yabs; u = xabs / yabs; } /* Handle underflow when u is close to 0 */ return log (max) + 0.5 * log1p (u * u);}/*********************************************************************** * Complex arithmetic operators ***********************************************************************/gsl_complexgsl_complex_add (gsl_complex a, gsl_complex b){ /* z=a+b */ double ar = GSL_REAL (a), ai = GSL_IMAG (a); double br = GSL_REAL (b), bi = GSL_IMAG (b); gsl_complex z; GSL_SET_COMPLEX (&z, ar + br, ai + bi); return z;}gsl_complexgsl_complex_add_real (gsl_complex a, double x){ /* z=a+x */ gsl_complex z; GSL_SET_COMPLEX (&z, GSL_REAL (a) + x, GSL_IMAG (a)); return z;}gsl_complexgsl_complex_add_imag (gsl_complex a, double y){ /* z=a+iy */ gsl_complex z; GSL_SET_COMPLEX (&z, GSL_REAL (a), GSL_IMAG (a) + y); return z;}gsl_complexgsl_complex_sub (gsl_complex a, gsl_complex b){ /* z=a-b */ double ar = GSL_REAL (a), ai = GSL_IMAG (a); double br = GSL_REAL (b), bi = GSL_IMAG (b); gsl_complex z; GSL_SET_COMPLEX (&z, ar - br, ai - bi); return z;}gsl_complexgsl_complex_sub_real (gsl_complex a, double x){ /* z=a-x */ gsl_complex z; GSL_SET_COMPLEX (&z, GSL_REAL (a) - x, GSL_IMAG (a)); return z;}gsl_complexgsl_complex_sub_imag (gsl_complex a, double y){ /* z=a-iy */ gsl_complex z; GSL_SET_COMPLEX (&z, GSL_REAL (a), GSL_IMAG (a) - y); return z;}gsl_complexgsl_complex_mul (gsl_complex a, gsl_complex b){ /* z=a*b */ double ar = GSL_REAL (a), ai = GSL_IMAG (a); double br = GSL_REAL (b), bi = GSL_IMAG (b); gsl_complex z; GSL_SET_COMPLEX (&z, ar * br - ai * bi, ar * bi + ai * br); return z;}gsl_complexgsl_complex_mul_real (gsl_complex a, double x){ /* z=a*x */ gsl_complex z; GSL_SET_COMPLEX (&z, x * GSL_REAL (a), x * GSL_IMAG (a)); return z;}gsl_complexgsl_complex_mul_imag (gsl_complex a, double y){ /* z=a*iy */ gsl_complex z; GSL_SET_COMPLEX (&z, -y * GSL_IMAG (a), y * GSL_REAL (a)); return z;}gsl_complexgsl_complex_div (gsl_complex a, gsl_complex b){ /* z=a/b */ double ar = GSL_REAL (a), ai = GSL_IMAG (a); double br = GSL_REAL (b), bi = GSL_IMAG (b); double s = 1.0 / gsl_complex_abs (b); double sbr = s * br; double sbi = s * bi; double zr = (ar * sbr + ai * sbi) * s; double zi = (ai * sbr - ar * sbi) * s; gsl_complex z; GSL_SET_COMPLEX (&z, zr, zi); return z;}gsl_complexgsl_complex_div_real (gsl_complex a, double x){ /* z=a/x */ gsl_complex z; GSL_SET_COMPLEX (&z, GSL_REAL (a) / x, GSL_IMAG (a) / x); return z;}gsl_complexgsl_complex_div_imag (gsl_complex a, double y){ /* z=a/(iy) */ gsl_complex z; GSL_SET_COMPLEX (&z, GSL_IMAG (a) / y, - GSL_REAL (a) / y); return z;}gsl_complexgsl_complex_conjugate (gsl_complex a){ /* z=conj(a) */ gsl_complex z; GSL_SET_COMPLEX (&z, GSL_REAL (a), -GSL_IMAG (a)); return z;}gsl_complexgsl_complex_negative (gsl_complex a){ /* z=-a */ gsl_complex z; GSL_SET_COMPLEX (&z, -GSL_REAL (a), -GSL_IMAG (a)); return z;}gsl_complexgsl_complex_inverse (gsl_complex a){ /* z=1/a */ double s = 1.0 / gsl_complex_abs (a); gsl_complex z; GSL_SET_COMPLEX (&z, (GSL_REAL (a) * s) * s, -(GSL_IMAG (a) * s) * s); return z;}/********************************************************************** * Elementary complex functions **********************************************************************/gsl_complexgsl_complex_sqrt (gsl_complex a){ /* z=sqrt(a) */ gsl_complex z; if (GSL_REAL (a) == 0.0 && GSL_IMAG (a) == 0.0) { GSL_SET_COMPLEX (&z, 0, 0); } else { double x = fabs (GSL_REAL (a)); double y = fabs (GSL_IMAG (a)); double w; if (x >= y) { double t = y / x; w = sqrt (x) * sqrt (0.5 * (1.0 + sqrt (1.0 + t * t))); } else { double t = x / y; w = sqrt (y) * sqrt (0.5 * (t + sqrt (1.0 + t * t))); } if (GSL_REAL (a) >= 0.0) { double ai = GSL_IMAG (a); GSL_SET_COMPLEX (&z, w, ai / (2.0 * w)); } else { double ai = GSL_IMAG (a); double vi = (ai >= 0) ? w : -w; GSL_SET_COMPLEX (&z, ai / (2.0 * vi), vi); } } return z;}gsl_complexgsl_complex_sqrt_real (double x){ /* z=sqrt(x) */ gsl_complex z; if (x >= 0) { GSL_SET_COMPLEX (&z, sqrt (x), 0.0); } else { GSL_SET_COMPLEX (&z, 0.0, sqrt (-x)); } return z;}gsl_complexgsl_complex_exp (gsl_complex a){ /* z=exp(a) */ double rho = exp (GSL_REAL (a)); double theta = GSL_IMAG (a); gsl_complex z; GSL_SET_COMPLEX (&z, rho * cos (theta), rho * sin (theta)); return z;}gsl_complexgsl_complex_pow (gsl_complex a, gsl_complex b){ /* z=a^b */ gsl_complex z; if (GSL_REAL (a) == 0 && GSL_IMAG (a) == 0.0) { GSL_SET_COMPLEX (&z, 0.0, 0.0); } else { double logr = gsl_complex_logabs (a); double theta = gsl_complex_arg (a); double br = GSL_REAL (b), bi = GSL_IMAG (b); double rho = exp (logr * br - bi * theta); double beta = theta * br + bi * logr; GSL_SET_COMPLEX (&z, rho * cos (beta), rho * sin (beta)); } return z;}gsl_complexgsl_complex_pow_real (gsl_complex a, double b){ /* z=a^b */ gsl_complex z; if (GSL_REAL (a) == 0 && GSL_IMAG (a) == 0) { GSL_SET_COMPLEX (&z, 0, 0); } else { double logr = gsl_complex_logabs (a); double theta = gsl_complex_arg (a); double rho = exp (logr * b); double beta = theta * b; GSL_SET_COMPLEX (&z, rho * cos (beta), rho * sin (beta)); } return z;}gsl_complexgsl_complex_log (gsl_complex a){ /* z=log(a) */ double logr = gsl_complex_logabs (a); double theta = gsl_complex_arg (a); gsl_complex z; GSL_SET_COMPLEX (&z, logr, theta); return z;}gsl_complexgsl_complex_log10 (gsl_complex a){ /* z = log10(a) */ return gsl_complex_mul_real (gsl_complex_log (a), 1 / log (10.));}gsl_complexgsl_complex_log_b (gsl_complex a, gsl_complex b){ return gsl_complex_div (gsl_complex_log (a), gsl_complex_log (b));}/*********************************************************************** * Complex trigonometric functions ***********************************************************************/gsl_complexgsl_complex_sin (gsl_complex a){ /* z = sin(a) */ double R = GSL_REAL (a), I = GSL_IMAG (a); gsl_complex z; if (I == 0.0) { /* avoid returing negative zero (-0.0) for the imaginary part */ GSL_SET_COMPLEX (&z, sin (R), 0.0); } else { GSL_SET_COMPLEX (&z, sin (R) * cosh (I), cos (R) * sinh (I)); } return z;}gsl_complexgsl_complex_cos (gsl_complex a){ /* z = cos(a) */ double R = GSL_REAL (a), I = GSL_IMAG (a); gsl_complex z; if (I == 0.0) { /* avoid returing negative zero (-0.0) for the imaginary part */ GSL_SET_COMPLEX (&z, cos (R), 0.0); } else { GSL_SET_COMPLEX (&z, cos (R) * cosh (I), sin (R) * sinh (-I)); } return z;}gsl_complexgsl_complex_tan (gsl_complex a){ /* z = tan(a) */ double R = GSL_REAL (a), I = GSL_IMAG (a); gsl_complex z; if (fabs (I) < 1) { double D = pow (cos (R), 2.0) + pow (sinh (I), 2.0); GSL_SET_COMPLEX (&z, 0.5 * sin (2 * R) / D, 0.5 * sinh (2 * I) / D); } else { double u = exp (-I); double C = 2 * u / (1 - pow (u, 2.0)); double D = 1 + pow (cos (R), 2.0) * pow (C, 2.0); double S = pow (C, 2.0); double T = 1.0 / tanh (I); GSL_SET_COMPLEX (&z, 0.5 * sin (2 * R) * S / D, T / D); } return z;}gsl_complexgsl_complex_sec (gsl_complex a){ /* z = sec(a) */ gsl_complex z = gsl_complex_cos (a); return gsl_complex_inverse (z);}gsl_complexgsl_complex_csc (gsl_complex a){ /* z = csc(a) */ gsl_complex z = gsl_complex_sin (a); return gsl_complex_inverse(z);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -