File: wacos.f

package info (click to toggle)
scilab 4.0-12
  • links: PTS
  • area: non-free
  • in suites: etch, etch-m68k
  • size: 100,640 kB
  • ctags: 57,333
  • sloc: ansic: 377,889; fortran: 242,862; xml: 179,819; tcl: 42,062; sh: 10,593; ml: 9,441; makefile: 4,377; cpp: 1,354; java: 621; csh: 260; yacc: 247; perl: 130; lex: 126; asm: 72; lisp: 30
file content (144 lines) | stat: -rw-r--r-- 4,233 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
      subroutine wacos(zr, zi, ar, ai)
*
*     PURPOSE
*        Compute the arccosine of a complex number
*         a = ar + i ai = acos(z), z = zr + i zi
*       
*     CALLING LIST / PARAMETERS
*        subroutine wacos(zr,zi,ar,ai)
*        double precision zr,zi,ar,ai
*
*        zr,zi: real and imaginary parts of the complex number
*        ar,ai: real and imaginary parts of the result
*               ar,ai may have the same memory cases than zr et zi
*
*     REFERENCE
*        This is a Fortran-77 translation of an algorithm by 
*        T.E. Hull, T. F. Fairgrieve and P.T.P. Tang which 
*        appears in their article :
*          "Implementing the Complex Arcsine and Arccosine 
*           Functions Using Exception Handling", ACM, TOMS, 
*           Vol 23, No. 3, Sept 1997, p. 299-335
*
*        with some modifications so as don't rely on ieee handle
*        trap functions.
*
*     AUTHOR
*        Bruno Pincon <Bruno.Pincon@iecn.u-nancy.fr>
*        Thanks to Tom Fairgrieve
*
      implicit none

*     PARAMETERS
      double precision zr, zi, ar, ai

*     EXTERNAL FUNCTIONS
      double precision dlamch, logp1
      external         dlamch, logp1

*     CONSTANTS
      double precision LN2, PI, HALFPI, Across, Bcross
      parameter       (LN2    = 0.6931471805599453094172321d0,
     $                 HALFPI = 1.5707963267948966192313216d0,
     $                     PI = 3.1415926535897932384626433d0,
     $                 Across = 1.5d0,
     $                 Bcross = 0.6417d0)  
*     LOCAL VARIABLES
      double precision x, y, A, B, R, S, Am1, szr, szi


*     STATIC VARIABLES
      double precision LSUP, LINF, EPSM
      save             LSUP, LINF, EPSM
      logical          first
      save             first
      data             first /.true./

*     TEXT
*     got f.p. parameters used by the algorithm
      if (first) then
          LSUP = sqrt(dlamch('o'))/8.d0
          LINF = 4.d0*sqrt(dlamch('u'))
          EPSM = sqrt(dlamch('e'))
          first = .false.
      endif

*     avoid memory pb ...
      x = abs(zr)
      y = abs(zi)
      szr = sign(1.d0,zr)
      szi = sign(1.d0,zi)


      if (LINF .le. min(x,y) .and. max(x,y) .le. LSUP ) then
*        we are in the safe region
         R = sqrt((x+1.d0)**2 + y**2)
         S = sqrt((x-1.d0)**2 + y**2)
         A = 0.5d0*(R + S)
         B = x/A

*        compute the real part
         if ( B .le. Bcross ) then
            ar = acos(B)
         elseif ( x .le. 1.d0 ) then
            ar = atan( sqrt( 0.5d0*(A+x) *
     $                 ( (y**2)/(R+(x+1.d0)) + (S+(1.d0-x)) ) ) / x )
         else
            ar = atan((y*sqrt(0.5d0*((A+x)/(R+(x+1.d0))
     $                  +(A+x)/(S+(x-1.d0))))) / x)
         endif

*        compute the imaginary part
         if ( A .le. Across ) then
            if ( x .lt. 1.d0 ) then
               Am1 = 0.5d0*((y**2)/(R+(x+1.d0))+(y**2)/(S+(1.d0-x)))
            else
               Am1 = 0.5d0*((y**2)/(R+(x+1.d0))+(S+(x-1.d0)))
            endif
            ai = logp1(Am1 + sqrt(Am1*(A+1.d0)))
         else
            ai = log(A + sqrt(A**2 - 1.d0))
         endif

      else
*        HANDLE BLOC : evaluation in the special regions ...
         if ( y .le. EPSM*abs(x-1.d0) ) then
            if (x .lt. 1.d0 ) then
               ar = acos(x)
               ai = y/sqrt((1.d0+x)*(1.d0-x))
            else
               ar = 0.d0
               if ( x .le. LSUP ) then
                  ai = logp1((x-1.d0) + sqrt((x-1.d0)*(x+1.d0)))
               else
                  ai = LN2 + log(x)
               endif
            endif
         elseif (y .lt. LINF) then
            ar = sqrt(y)
            ai = ar
         elseif (EPSM*y - 1.d0 .ge. x) then
            ar = HALFPI
            ai = LN2 + log(y)
         elseif (x .gt. 1.d0) then
            ar = atan(y/x)
            ai = LN2 + log(y) + 0.5d0*logp1((x/y)**2)
         else
            ar = HALFPI
            A = sqrt(1.d0 + y**2)
            ai = 0.5d0*logp1(2.d0*y*(y+A))
         endif
      endif

*     recover the signs
      if (szr .lt. 0.d0) then
         ar = PI - ar
      endif

      if (y.ne.0.d0 .or. szr.lt.0.d0) then
         ai = - szi * ai
      endif

      end