summaryrefslogtreecommitdiff
path: root/Utilib/src/ALPADE.f
blob: fd0d42c7ef6e52a61c8ad60d9310b599c63d2b97 (plain)
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
*DECK ALPADE
      SUBROUTINE ALPADE(NORIN,X,Y,EPSRID,NOR,A,B,PREC,IER)
*
*-----------------------------------------------------------------------
*
*Purpose:
* compute the polynomial coefficients of a Pade approximation using an
* inverse differences collocation.
*
*Copyright:
* Copyright (C) 1996 Ecole Polytechnique de Montreal
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version
*
*Author(s): A. Hebert
*
*Parameters: input
* NORIN   2*NORIN+1 is the number of collocation points.
* X       abscissa of the collocation points.
* Y       ordinates of the collocation points.
* EPSRID  epsilon used in polynomial simplification.
*
*Parameters: output
* NOR     order of the polynomials.
* A       polynomial coefficients of the numerator of the Pade
*         approximation. a(0) is the constant term.
* B       polynomial coefficients of the denominator of the Pade
*         approximation. b(0) is the constant term.
*         DOUBLE PRECISION A(0:NOR),B(0:NOR)
* PREC    accuracy of the fit.
* IER     error flag (=0: no error; =1: negative pole removing).
*
*-----------------------------------------------------------------------
*
*----
*  SUBROUTINE ARGUMENTS
*----
      INTEGER NORIN,IER
      REAL X(0:2*NORIN),Y(0:2*NORIN),PREC
      DOUBLE PRECISION EPSRID,A(0:NORIN),B(0:NORIN)
*----
*  LOCAL VARIABLES
*----
      PARAMETER (MAXNOR=10)
      DOUBLE PRECISION DC(0:MAXNOR),DENOM,DY(0:2*MAXNOR,0:2*MAXNOR),
     1 ERR1,ERR2,GARINF,SCC,SDD
      COMPLEX*16 DDA(0:MAXNOR-2),DDB(0:MAXNOR-2),SIGX0(MAXNOR),
     1 SIGXW(MAXNOR)
      LOGICAL LINF,LFAIL
*
      IER=0
      IF(NORIN.GT.MAXNOR) CALL XABORT('ALPADE: INSUFFICIENT MAXNOR.')
      LINF=X(2*NORIN).GE.1.0E10
      JMAX=2*NORIN
      ERR2=DBLE(Y(1))
      GARINF=0.0D0
      DY(0:2*MAXNOR,0:2*MAXNOR)=0.0D0
      DO 15 J=0,2*NORIN
      IF(X(J).LE.0.0) CALL XABORT('ALPADE: ZERO OR NEGATIVE ABSCISSA.')
      IF(Y(J).LE.0.0) CALL XABORT('ALPADE: ZERO OR NEGATIVE ORDINATE.')
      ERR1=0.0D0
      DO 10 I=J,2*NORIN
      IF(J.EQ.0) THEN
         DY(I,J)=DBLE(Y(I))
      ELSE IF(LINF.AND.(MOD(J,2).EQ.1).AND.(I.EQ.2*NORIN)) THEN
         DENOM=DY(I,J-1)-DY(J-1,J-1)
         IF(DENOM.EQ.0.0) CALL XABORT('ALPADE: ALGORITHM FAILURE(1).')
         DY(I,J)=1.0D0/DENOM
      ELSE IF(LINF.AND.(I.EQ.2*NORIN)) THEN
         DENOM=DY(I,J-1)
         IF(DENOM.EQ.0.0) CALL XABORT('ALPADE: ALGORITHM FAILURE(2).')
         DY(I,J)=1.0D0/DENOM
      ELSE
         DENOM=DY(I,J-1)-DY(J-1,J-1)
         IF(DENOM.EQ.0.0) CALL XABORT('ALPADE: ALGORITHM FAILURE(3).')
         DY(I,J)=(DBLE(X(I))-DBLE(X(J-1)))/DENOM
      ENDIF
      ERR1=MAX(ERR1,ABS(DY(I,J)-DY(J,J)))
   10 CONTINUE
      IF(MOD(J,2).EQ.0) GARINF=GARINF+DY(J,J)
      IF(LINF.AND.(ERR1.LE.1.0D-6*ERR2).AND.(ABS(GARINF-Y(2*NORIN)).LE.
     1 1.0D-5*ABS(GARINF))) THEN
         JMAX=J
         GO TO 20
      ENDIF
      ERR2=ERR1
   15 CONTINUE
*
   20 IF(MOD(JMAX,2).NE.0) CALL XABORT('ALPADE: ALGORITHM FAILURE(4).')
      N=0
      MM=JMAX-1
      A(0)=DY(JMAX,JMAX)
      B(0)=1.0D0
      NOR=JMAX/2
      DO 60 K=1,NOR
      DC(0)=0.0D0
      DO 30 I=0,N
      DC(I+1)=B(I)
      DC(I)=DC(I)-B(I)*X(MM)+A(I)*DY(MM,MM)
   30 CONTINUE
      MM=MM-1
      B(0)=0.0D0
      DO 40 I=0,N
      B(I+1)=A(I)
      B(I)=B(I)-A(I)*X(MM)+DC(I)*DY(MM,MM)
   40 CONTINUE
      B(N+1)=B(I)+DC(N+1)*DY(MM,MM)
      DO 50 I=0,N+1
      A(I)=B(I)
      B(I)=DC(I)
   50 CONTINUE
      MM=MM-1
      N=N+1
   60 CONTINUE
*
* POLYNOMIAL SIMPLIFICATION.
      DDA(0)=A(NOR)
      DDB(0)=B(NOR)
      IF(NOR.EQ.0) GO TO 120
      CALL ALROOT(A,NOR,SIGX0,LFAIL)
      IF(LFAIL) CALL XABORT('ALPADE: POLYNOMIAL ROOT FINDING FAILURE.')
      CALL ALROOT(B,NOR,SIGXW,LFAIL)
      IF(LFAIL) CALL XABORT('ALPADE: POLYNOMIAL ROOT FINDING FAILURE.')
      IJNOR=1
   70 XXX=ABS(REAL(CMPLX(SIGXW(IJNOR)))-REAL(CMPLX(SIGX0(IJNOR))))
      IF(XXX.LT.EPSRID*ABS(SIGXW(IJNOR))) THEN
         NOR=NOR-1
         DO 80 I=IJNOR,NOR
         SIGX0(I)=SIGX0(I+1)
         SIGXW(I)=SIGXW(I+1)
   80    CONTINUE
      ELSE IF((DBLE(SIGXW(IJNOR)).GT.0.).AND.(DIMAG(SIGXW(IJNOR)).EQ.0.)
     1 ) THEN
         IER=1
         NOR=NOR-1
         DO 90 I=IJNOR,NOR
         SIGX0(I)=SIGX0(I+1)
         SIGXW(I)=SIGXW(I+1)
   90    CONTINUE
      ELSE
         IJNOR=IJNOR+1
      ENDIF
      IF(IJNOR.LE.NOR) GO TO 70
      IF(NOR.LT.0) CALL XABORT('ALPADE: ALGORITHM FAILURE(5).')
      DO 110 I=1,NOR
      DDA(I)=DDA(I-1)
      DDB(I)=DDB(I-1)
      DO 100 J=I-1,1,-1
      DDA(J)=DDA(J-1)-DDA(J)*SIGX0(I)
      DDB(J)=DDB(J-1)-DDB(J)*SIGXW(I)
  100 CONTINUE
      DDA(0)=-DDA(0)*SIGX0(I)
      DDB(0)=-DDB(0)*SIGXW(I)
  110 CONTINUE
  120 DENOM=DBLE(DDB(NOR))
      DO 130 I=0,NOR
      A(I)=DBLE(DDA(I))/DENOM
      B(I)=DBLE(DDB(I))/DENOM
  130 CONTINUE
*
* TEST THE ACCURACY OF THE PADE APPROXIMATION.
      PREC=0.0
      PREC1=0.0
      DO 150 I=0,2*NORIN
      SCC=A(NOR)
      SDD=B(NOR)
      IF(X(I).LT.1.0E10) THEN
         DO 140 INOR=NOR-1,0,-1
         SCC=A(INOR)+SCC*X(I)
         SDD=B(INOR)+SDD*X(I)
  140    CONTINUE
      ENDIF
      PREC=MAX(PREC,ABS(REAL(SCC/SDD)/Y(I)-1.0))
      PREC1=MAX(PREC1,ABS(Y(2*NORIN)/Y(I)-1.0))
  150 CONTINUE
      IF((IER.NE.0).AND.(PREC.GT.0.99*PREC1)) THEN
*        USE A UNIFORM REPRESENTATION.
         NOR=0
         A(0)=DBLE(Y(2*NORIN))
         B(0)=1.0D0
         PREC=PREC1
      ENDIF
      RETURN
      END