123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- //**********************************************************************************//
- // Copyright (C) 2009-2015 Ovidio Pena <ovidio@bytesfall.com> //
- // //
- // This file is part of scattnlay //
- // //
- // 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 3 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. //
- // //
- // The only additional remark is that we expect that all publications //
- // describing work using this software, or all commercial products //
- // using it, cite the following reference: //
- // [1] O. Pena and U. Pal, "Scattering of electromagnetic radiation by //
- // a multilayered sphere," Computer Physics Communications, //
- // vol. 180, Nov. 2009, pp. 2348-2354. //
- // //
- // You should have received a copy of the GNU General Public License //
- // along with this program. If not, see <http://www.gnu.org/licenses/>. //
- //**********************************************************************************//
- #include <math.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include "ucomplex.h"
- complex Cadd(complex z1, complex z2) {
- complex zr;
- zr.r = z1.r + z2.r;
- zr.i = z1.i + z2.i;
- return zr;
- }
- complex Csub(complex z1, complex z2) {
- complex zr;
- zr.r = z1.r - z2.r;
- zr.i = z1.i - z2.i;
- return zr;
- }
- complex Cmul(complex z1, complex z2) {
- complex zr;
- zr.r = (z1.r*z2.r) - (z1.i*z2.i);
- zr.i = (z1.r*z2.i) + (z1.i*z2.r);
- return zr;
- }
- complex RCmul(double r, complex z) {
- complex zr;
- zr.r = z.r*r;
- zr.i = z.i*r;
- return zr;
- }
- complex Cdiv(complex z1, complex z2) {
- /* The following algorithm is used to properly handle
- denominator overflow:
- | a + b(d/c) b - a(d/c)
- | ---------- + ----------- I if |d| < |c|
- a + b I | c + d(d/c) c + d(d/c)
- ------- = |
- c + d I | b + a(c/d) -a + b(c/d)
- | ---------- + ----------- I if |d| >= |c|
- | d + c(c/d) d + c(c/d)
- */
- complex zr;
- double tmp, denom;
- if(fabs(z2.r) > fabs(z2.i)) {
- tmp = z2.i/z2.r;
- denom = z2.r + z2.i*tmp;
- zr.r = (z1.r + z1.i*tmp)/denom;
- zr.i = (z1.i - z1.r*tmp)/denom;
- } else {
- tmp = z2.r/z2.i;
- denom = z2.i + z2.r*tmp;
- zr.r = (z1.i + z1.r*tmp)/denom;
- zr.i = (-z1.r + z1.i*tmp)/denom;
- }
- return zr;
- }
- complex Complex(double re, double im) {
- complex zr;
- zr.r = re;
- zr.i = im;
- return zr;
- }
- double Cabs(complex z) {
- double r;
- r = sqrt((z.r*z.r) + (z.i*z.i));
- return r;
- }
- double Carc(complex z) {
- double r;
- r = atan2(z.i, z.r);
- return r;
- }
- complex Conjg(complex z) {
- complex zr;
- zr.r = z.r;
- zr.i = -z.i;
- return zr;
- }
- complex Cinv(complex z) {
- complex zr;
- double denom;
- denom = (z.r*z.r) + (z.i*z.i);
- zr.r = z.r/denom;
- zr.i = -z.i/denom;
- return zr;
- }
- complex Cexp(complex z) {
- // exp(a + ib) = exp(a)*exp(ib) = exp(a)*[cos(b) + i sin(b)]
- complex zr;
- double expz;
- expz = exp(z.r);
- zr.r = expz*cos(z.i);
- zr.i = expz*sin(z.i);
- return zr;
- }
- complex Clog(complex z) {
- // ln( p exp(i0)) = ln(p) + i0 + 2kpi
- complex zr;
- zr.r = log(Cabs(z));
- zr.i = atan2(z.i, z.r);
- return zr;
- }
- complex Csqrt(complex z) {
- complex zr;
- double root, q;
- if((z.r != 0.0) ||(z.i != 0.0)) {
- root = sqrt(0.5*(fabs(z.r) + Cabs(z)));
- q = z.i/(2.0*root);
- if(z.r >= 0.0) {
- zr.r = root;
- zr.i = q;
- } else if(z.i < 0.0) {
- zr.r = -q;
- zr.i = -root;
- } else {
- zr.r = q;
- zr.i = root;
- }
- } else zr = z;
- return zr;
- }
- // complex trigonometric functions
- // complex cosinus
- complex Ccos(complex z) {
- // cos(x+iy) = cos(x).cos(iy) - sin(x).sin(iy)
- // cos(ix) = cosh(x) et sin(ix) = i.sinh(x)
- complex zr;
- zr.r = cos(z.r)*cosh(z.i);
- zr.i = -sin(z.r)*sinh(z.i);
- return zr;
- }
- // complex sinus
- complex Csin(complex z) {
- // sin(x+iy) = sin(x).cos(iy) + cos(x).sin(iy)
- // cos(ix) = cosh(x) et sin(ix) = i.sinh(x)
- complex zr;
- zr.r = sin(z.r)*cosh(z.i);
- zr.i = cos(z.r)*sinh(z.i);
- return zr;
- }
- // tangent
- complex Ctan(complex z) {
- return Cdiv(Csin(z), Ccos(z));
- }
- // Inverse trigonometric functions
- // complex arc cosinus
- complex Carc_cos(complex z) {
- // arccos(z) = -i.arcch(z)
- complex temp = Carc_ch(z);
- return Complex(temp.i, -temp.r);
- }
- // complex arc sinus
- complex Carc_sin(complex z) {
- // arcsin(z) = -i.arcsh(i.z)
- complex temp = Carc_sh(Complex(-z.i, z.r));
- return Complex(temp.i, -temp.r);
- }
- // complex arc tangent
- complex Carc_tan(complex z) {
- // arctg(z) = -i.arcth(i.z)
- complex temp = Carc_th(Complex(-z.i, z.r));
- return Complex(temp.i, -temp.r);
- }
- // Hyberbolic complex functions
- // complex hyberbolic cosinus
- complex Cch(complex z) {
- // cosh(x+iy) = cosh(x).cosh(iy) + sinh(x).sinh(iy)
- // cosh(iy) = cos(y) et sinh(iy) = i.sin(y)
- complex zr;
- zr.r = cosh(z.r)*cos(z.i);
- zr.i = sinh(z.r)*sin(z.i);
- return zr;
- }
- // complex hyberbolic sinus
- complex Csh(complex z) {
- // sinh(x+iy) = sinh(x).cosh(iy) + cosh(x).sinh(iy)
- // cosh(iy) = cos(y) et sinh(iy) = i.sin(y)
- complex zr;
- zr.r = sinh(z.r)*cos(z.i);
- zr.i = cosh(z.r)*sin(z.i);
- return zr;
- }
- // complex hyberbolic tangent
- complex Cth(complex z) {
- // th(x) = sinh(x)/cosh(x)
- // cosh(x) > 1 qq x
- complex temp, zr;
- temp = Cch(z);
- zr = Csh(z);
- return Cdiv(zr, temp);
- }
- // Inverse complex hyperbolic functions
- // complex hyperbolic arc cosinus
- complex Carc_ch(complex z) {
- // _________
- // arcch(z) = -/+ ln(z + V z.z - 1 )
- complex zr;
- complex z2 = Cmul(z, z);
- zr = Clog(Cadd(z, Csqrt(Complex(z2.r - 1.0, z2.i))));
- zr.r = -zr.r;
- zr.i = -zr.i;
- return zr;
- }
- // complex hyperbolic arc sinus
- complex Carc_sh(complex z) {
- // ________
- // arcsh(z) = ln(z + V 1 + z.z)
- complex z2 = Cmul(z, z);
- return Clog(Cadd(z, Csqrt(Complex(z2.r + 1.0, z2.i))));
- }
- // complex hyperbolic arc tangent
- complex Carc_th(complex z) {
- // arcth(z) = 1/2 ln((z + 1)/(1 - z))
- return RCmul(0.5, Clog(Cdiv(Complex(z.r + 1.0, z.i), Complex(1.0 - z.r, -z.i))));
- }
|