Code covered by the BSD License  

Highlights from
slatec

from slatec by Ben Barrowes
The slatec library converted into matlab functions.

[z,id,kode,ai,nz,ierr]=cairy(z,id,kode,ai,nz,ierr);
function [z,id,kode,ai,nz,ierr]=cairy(z,id,kode,ai,nz,ierr);
%***BEGIN PROLOGUE  CAIRY
%***PURPOSE  Compute the Airy function Ai(z) or its derivative dAi/dz
%            for complex argument z.  A scaling option is available
%            to help avoid underflow and overflow.
%***LIBRARY   SLATEC
%***CATEGORY  C10D
%***TYPE      COMPLEX (CAIRY-C, ZAIRY-C)
%***KEYWORDS  AIRY FUNCTION, BESSEL FUNCTION OF ORDER ONE THIRD,
%             BESSEL FUNCTION OF ORDER TWO THIRDS
%***AUTHOR  Amos, D. E., (SNL)
%***DESCRIPTION
%
%         On KODE=1, CAIRY computes the complex Airy function Ai(z)
%         or its derivative dAi/dz on ID=0 or ID=1 respectively. On
%         KODE=2, a scaling option exp(zeta)*Ai(z) or exp(zeta)*dAi/dz
%         is provided to remove the exponential decay in -pi/3<arg(z)
%         <pi/3 and the exponential growth in pi/3<abs(arg(z))<pi where
%         zeta=(2/3)*z**(3/2).
%
%         While the Airy functions Ai(z) and dAi/dz are analytic in
%         the whole z-plane, the corresponding scaled functions defined
%         for KODE=2 have a cut along the negative real axis.
%
%         Input
%           Z      - Argument of type COMPLEX
%           ID     - Order of derivative, ID=0 or ID=1
%           KODE   - A parameter to indicate the scaling option
%                    KODE=1  returns
%                            AI=Ai(z)  on ID=0
%                            AI=dAi/dz on ID=1
%                            at z=Z
%                        =2  returns
%                            AI=exp(zeta)*Ai(z)  on ID=0
%                            AI=exp(zeta)*dAi/dz on ID=1
%                            at z=Z where zeta=(2/3)*z**(3/2)
%
%         Output
%           AI     - Result of type COMPLEX
%           NZ     - Underflow indicator
%                    NZ=0    Normal return
%                    NZ=1    AI=0 due to underflow in
%                            -pi/3<arg(Z)<pi/3 on KODE=1
%           IERR   - Error flag
%                    IERR=0  Normal return     - COMPUTATION COMPLETED
%                    IERR=1  Input error       - NO COMPUTATION
%                    IERR=2  Overflow          - NO COMPUTATION
%                            (Re(Z) too large with KODE=1)
%                    IERR=3  Precision warning - COMPUTATION COMPLETED
%                            (Result has less than half precision)
%                    IERR=4  Precision error   - NO COMPUTATION
%                            (Result has no precision)
%                    IERR=5  Algorithmic error - NO COMPUTATION
%                            (Termination condition not met)
%
% *Long Description:
%
%         Ai(z) and dAi/dz are computed from K Bessel functions by
%
%                Ai(z) =  c*sqrt(z)*K(1/3,zeta)
%               dAi/dz = -c*   z   *K(2/3,zeta)
%                    c =  1/(pi*sqrt(3))
%                 zeta =  (2/3)*z**(3/2)
%
%         when abs(z)>1 and from power series when abs(z)<=1.
%
%         In most complex variable computation, one must evaluate ele-
%         mentary functions.  When the magnitude of Z is large, losses
%         of significance by argument reduction occur.  Consequently, if
%         the magnitude of ZETA=(2/3)*Z**(3/2) exceeds U1=SQRT(0.5/UR),
%         then losses exceeding half precision are likely and an error
%         flag IERR=3 is triggered where UR=R1MACH(4)=UNIT ROUNDOFF.
%         Also, if the magnitude of ZETA is larger than U2=0.5/UR, then
%         all significance is lost and IERR=4.  In order to use the INT
%         function, ZETA must be further restricted not to exceed
%         U3=I1MACH(9)=LARGEST INTEGER.  Thus, the magnitude of ZETA
%         must be restricted by MIN(U2,U3).  In IEEE arithmetic, U1,U2,
%         and U3 are approximately 2.0E+3, 4.2E+6, 2.1E+9 in single
%         precision and 4.7E+7, 2.3E+15, 2.1E+9 in doubleprecision.
%         This makes U2 limiting is single precision and U3 limiting
%         in doubleprecision.  This means that the magnitude of Z
%         cannot exceed approximately 3.4E+4 in single precision and
%         2.1E+6 in doubleprecision.  This also means that one can
%         expect to retain, in the worst cases on 32-bit machines,
%         no digits in single precision and only 6 digits in double
%         precision.
%
%         The approximate relative error in the magnitude of a complex
%         Bessel function can be expressed as P*10**S where P=MAX(UNIT
%         ROUNDOFF,1.0E-18) is the nominal precision and 10**S repre-
%         sents the increase in error due to argument reduction in the
%         elementary functions.  Here, S=MAX(1,ABS(LOG10(ABS(Z))),
%         ABS(LOG10(FNU))) approximately (i.e., S=MAX(1,ABS(EXPONENT OF
%         ABS(Z),ABS(EXPONENT OF FNU)) ).  However, the phase angle may
%         have only absolute accuracy.  This is most likely to occur
%         when one component (in magnitude) is larger than the other by
%         several orders of magnitude.  If one component is 10**K larger
%         than the other, then one can expect only MAX(ABS(LOG10(P))-K,
%         0) significant digits; or, stated another way, when K exceeds
%         the exponent of P, no significant digits remain in the smaller
%         component.  However, the phase angle retains absolute accuracy
%         because, in complex arithmetic with precision P, the smaller
%         component will not (as a rule) decrease below P times the
%         magnitude of the larger component. In these extreme cases,
%         the principal phase angle is on the order of +P, -P, PI/2-P,
%         or -PI/2+P.
%
%***REFERENCES  1. M. Abramowitz and I. A. Stegun, Handbook of Mathe-
%                 matical Functions, National Bureau of Standards
%                 Applied Mathematics Series 55, U. S. Department
%                 of Commerce, Tenth Printing (1972) or later.
%               2. D. E. Amos, Computation of Bessel Functions of
%                 Complex Argument and Large Order, Report SAND83-0643,
%                 Sandia National Laboratories, Albuquerque, NM, May
%                 1983.
%               3. D. E. Amos, A Subroutine Package for Bessel Functions
%                 of a Complex Argument and Nonnegative Order, Report
%                 SAND85-1018, Sandia National Laboratory, Albuquerque,
%                 NM, May 1985.
%               4. D. E. Amos, A portable package for Bessel functions
%                 of a complex argument and nonnegative order, ACM
%                 Transactions on Mathematical Software, 12 (September
%                 1986), pp. 265-273.
%
%***ROUTINES CALLED  CACAI, CBKNU, I1MACH, R1MACH
%***REVISION HISTORY  (YYMMDD)
%   830501  DATE WRITTEN
%   890801  REVISION DATE from Version 3.2
%   910415  Prologue converted to Version 4.0 format.  (BAB)
%   920128  Category corrected.  (WRB)
%   920811  Prologue revised.  (DWL)
%***end PROLOGUE  CAIRY
persistent aa ad ak alaz alim atrm az az3 bb bk c1 c2 ck coef cone csq cy d1 d2 dig dk elim fid firstCall fnu iflag k k1 k2 mr nn r1m5 rl s1 s2 sfac tol trm1 trm2 tth z3 z3i z3r zi zr zta ; if isempty(firstCall),firstCall=1;end; 

if isempty(cone), cone=0; end;
if isempty(csq), csq=0; end;
if isempty(cy), cy=zeros(1,1); end;
if isempty(s1), s1=0; end;
if isempty(s2), s2=0; end;
if isempty(trm1), trm1=0; end;
if isempty(trm2), trm2=0; end;
if isempty(zta), zta=0; end;
if isempty(z3), z3=0; end;
if isempty(aa), aa=0; end;
if isempty(ad), ad=0; end;
if isempty(ak), ak=0; end;
if isempty(alim), alim=0; end;
if isempty(atrm), atrm=0; end;
if isempty(az), az=0; end;
if isempty(az3), az3=0; end;
if isempty(bk), bk=0; end;
if isempty(ck), ck=0; end;
if isempty(coef), coef=0; end;
if isempty(c1), c1=0; end;
if isempty(c2), c2=0; end;
if isempty(dig), dig=0; end;
if isempty(dk), dk=0; end;
if isempty(d1), d1=0; end;
if isempty(d2), d2=0; end;
if isempty(elim), elim=0; end;
if isempty(fid), fid=0; end;
if isempty(fnu), fnu=0; end;
if isempty(rl), rl=0; end;
if isempty(r1m5), r1m5=0; end;
if isempty(sfac), sfac=0; end;
if isempty(tol), tol=0; end;
if isempty(tth), tth=0; end;
if isempty(zi), zi=0; end;
if isempty(zr), zr=0; end;
if isempty(z3i), z3i=0; end;
if isempty(z3r), z3r=0; end;
if isempty(bb), bb=0; end;
if isempty(alaz), alaz=0; end;
if isempty(iflag), iflag=0; end;
if isempty(k), k=0; end;
if isempty(k1), k1=0; end;
if isempty(k2), k2=0; end;
if isempty(mr), mr=0; end;
if isempty(nn), nn=0; end;
if firstCall,   tth =[6.66666666666666667e-01];  end;
if firstCall,  c1 =[3.55028053887817240e-01];  end;
if firstCall,  c2 =[2.58819403792806799e-01];  end;
if firstCall,  coef=[1.83776298473930683e-01];  end;
if firstCall,   cone=[complex(1.0e0,0.0e0)];  end;
firstCall=0;
%***FIRST EXECUTABLE STATEMENT  CAIRY
ierr = 0;
nz = 0;
if( id<0 || id>1 )
ierr = 1;
end;
if( kode<1 || kode>2 )
ierr = 1;
end;
if( ierr~=0 )
return;
end;
az = abs(z);
tol = max(r1mach(4),1.0e-18);
fid = id;
if( az>1.0e0 )
%-----------------------------------------------------------------------
%     CASE FOR ABS(Z).GT.1.0
%-----------------------------------------------------------------------
fnu =(1.0e0+fid)./3.0e0;
%-----------------------------------------------------------------------
%     SET PARAMETERS RELATED TO MACHINE CONSTANTS.
%     TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18.
%     ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT.
%     EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL    AND
%     EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL       ARE INTERVALS NEAR
%     UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE.
%     RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z.
%     DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG).
%-----------------------------------------------------------------------
[k1 ]=i1mach(12);
[k2 ]=i1mach(13);
[r1m5 ]=r1mach(5);
k = fix(min(abs(k1),abs(k2)));
elim = 2.303e0.*(k.*r1m5-3.0e0);
k1 = fix(i1mach(11) - 1);
aa = r1m5.*k1;
dig = min(aa,18.0e0);
aa = aa.*2.303e0;
alim = elim + max(-aa,-41.45e0);
rl = 1.2e0.*dig + 3.0e0;
alaz = log(az);
%-----------------------------------------------------------------------
%     TEST FOR RANGE
%-----------------------------------------------------------------------
aa = 0.5e0./tol;
bb = i1mach(9).*0.5e0;
aa = min(aa,bb);
aa = aa.^tth;
if( az>aa )
ierr = 4;
nz = 0;
return;
else;
aa = sqrt(aa);
if( az>aa )
ierr = 3;
end;
csq = sqrt(z);
zta = z.*csq.*complex(tth,0.0e0);
%-----------------------------------------------------------------------
%     RE(ZTA).LE.0 WHEN RE(Z).LT.0, ESPECIALLY WHEN IM(Z) IS SMALL
%-----------------------------------------------------------------------
iflag = 0;
sfac = 1.0e0;
zi = imag(z);
zr = real(z);
ak = imag(zta);
if( zr<0.0e0 )
bk = real(zta);
ck = -abs(bk);
zta = complex(ck,ak);
end;
if( zi==0.0e0 )
if( zr<=0.0e0 )
zta = complex(0.0e0,ak);
end;
end;
aa = real(zta);
if( aa<0.0e0 || zr<=0.0e0 )
if( kode~=2 )
%-----------------------------------------------------------------------
%     OVERFLOW TEST
%-----------------------------------------------------------------------
if( aa<=(-alim) )
aa = -aa + 0.25e0.*alaz;
iflag = 1;
sfac = tol;
if( aa>elim )
nz = 0;
ierr = 2;
return;
end;
end;
end;
%-----------------------------------------------------------------------
%     CBKNU AND CACAI RETURN EXP(ZTA)*K(FNU,ZTA) ON KODE=2
%-----------------------------------------------------------------------
mr = 1;
if( zi<0.0e0 )
mr = -1;
end;
[zta,fnu,kode,mr,dumvar5,cy,nn,rl,tol,elim,alim]=cacai(zta,fnu,kode,mr,1,cy,nn,rl,tol,elim,alim);
if( nn<0 )
if( nn==(-1) )
nz = 0;
ierr = 2;
return;
end;
nz = 0;
ierr = 5;
return;
else;
nz = fix(nz + nn);
end;
elseif( kode==2 ) ;
[zta,fnu,kode,dumvar4,cy,nz,tol,elim,alim]=cbknu(zta,fnu,kode,1,cy,nz,tol,elim,alim);
%-----------------------------------------------------------------------
%     UNDERFLOW TEST
%-----------------------------------------------------------------------
elseif( aa<alim ) ;
[zta,fnu,kode,dumvar4,cy,nz,tol,elim,alim]=cbknu(zta,fnu,kode,1,cy,nz,tol,elim,alim);
else;
aa = -aa - 0.25e0.*alaz;
iflag = 2;
sfac = 1.0e0./tol;
if( aa<(-elim) )
nz = 1;
ai = complex(0.0e0,0.0e0);
return;
else;
[zta,fnu,kode,dumvar4,cy,nz,tol,elim,alim]=cbknu(zta,fnu,kode,1,cy,nz,tol,elim,alim);
end;
end;
s1 = cy(1).*complex(coef,0.0e0);
if( iflag~=0 )
s1 = s1.*complex(sfac,0.0e0);
if( id==1 )
s1 = -s1.*z;
ai = s1.*complex(1.0e0./sfac,0.0e0);
return;
else;
s1 = s1.*csq;
ai = s1.*complex(1.0e0./sfac,0.0e0);
return;
end;
elseif( id==1 ) ;
ai = -z.*s1;
return;
else;
ai = csq.*s1;
return;
end;
end;
nz = 0;
ierr = 2;
return;
else;
%-----------------------------------------------------------------------
%     POWER SERIES FOR ABS(Z).LE.1.
%-----------------------------------------------------------------------
s1 = cone;
s2 = cone;
if( az<tol )
aa = 1.0e+3.*r1mach(1);
s1 = complex(0.0e0,0.0e0);
if( id==1 )
ai = -complex(c2,0.0e0);
aa = sqrt(aa);
if( az>aa )
s1 = z.*z.*complex(0.5e0,0.0e0);
end;
ai = ai + s1.*complex(c1,0.0e0);
return;
else;
if( az>aa )
s1 = complex(c2,0.0e0).*z;
end;
ai = complex(c1,0.0e0) - s1;
return;
end;
else;
aa = az.*az;
if( aa>=tol./az )
trm1 = cone;
trm2 = cone;
atrm = 1.0e0;
z3 = z.*z.*z;
az3 = az.*aa;
ak = 2.0e0 + fid;
bk = 3.0e0 - fid - fid;
ck = 4.0e0 - fid;
dk = 3.0e0 + fid + fid;
d1 = ak.*dk;
d2 = bk.*ck;
ad = min(d1,d2);
ak = 24.0e0 + 9.0e0.*fid;
bk = 30.0e0 - 9.0e0.*fid;
z3r = real(z3);
z3i = imag(z3);
for k = 1 : 25;
trm1 = trm1.*complex(z3r./d1,z3i./d1);
s1 = s1 + trm1;
trm2 = trm2.*complex(z3r./d2,z3i./d2);
s2 = s2 + trm2;
atrm = atrm.*az3./ad;
d1 = d1 + ak;
d2 = d2 + bk;
ad = min(d1,d2);
if( atrm<tol.*ad )
break;
end;
ak = ak + 18.0e0;
bk = bk + 18.0e0;
end;
end;
if( id==1 )
ai = -s2.*complex(c2,0.0e0);
if( az>tol )
ai = ai + z.*z.*s1.*complex(c1./(1.0e0+fid),0.0e0);
end;
if( kode==1 )
return;
end;
zta = z.*sqrt(z).*complex(tth,0.0e0);
ai = ai.*exp(zta);
return;
else;
ai = s1.*complex(c1,0.0e0) - z.*s2.*complex(c2,0.0e0);
if( kode==1 )
return;
end;
zta = z.*sqrt(z).*complex(tth,0.0e0);
ai = ai.*exp(zta);
return;
end;
end;
end;
end %subroutine cairy
%DECK CARG

Contact us at files@mathworks.com