|
|
1.1 ! root 1: subroutine buram(npts, mesh, fn, m, n, p, q, delk) ! 2: integer npts ! 3: integer m, n ! 4: real mesh(npts), fn(npts), p(1), q(1), delk ! 5: common /dfccom/ nitr ! 6: integer nitr ! 7: integer ier, maxitr, nerror, i, itol ! 8: real fnmin, fnmax ! 9: logical smonor ! 10: c Buram is a double precision subroutine which finds a ! 11: c a rational function which is the best approximation, ! 12: c in the uniform or minimax sense, to a given discrete ! 13: c function. The rational function is represented as ! 14: c the quotient of two polynomials each expanded in terms ! 15: c of Tchebychev polynomials. This routine is a shell ! 16: c which in turn calls the routine Burm1 with certain ! 17: c default values for the initial approximation and for ! 18: c the stopping criteria. ! 19: c Input: ! 20: c npts - the number of mesh points. ! 21: c mesh - the array of mesh points. ! 22: c fn - the array of function values. ! 23: c m - the degree of the desired numerator polynomial. ! 24: c n - the degree of the desired denominator polynomial. ! 25: c Output: ! 26: c p - the array of coefficients for the numerator polynomial. ! 27: c q - the array of coefficients for the denominator polynomial. ! 28: c delk - the maximum error in the approximation. ! 29: c Error States (asterisk indicates recoverable): ! 30: c 1 - invalid degree ! 31: c 2 - too few mesh points ! 32: c 3 - mesh is not strictly monotone ! 33: c 4* - approximation equals function ! 34: c 5* - no improvement in approximation ! 35: c 6* - reached 50 iterations ! 36: call enter(1) ! 37: if (m .lt. 0 .or. n .lt. 0) call seterr( ! 38: 1 23h Buram - invalid degree, 23, 1, 2) ! 39: if (npts .lt. m+n+2) call seterr(28h Buram - too few mesh points ! 40: 1 , 28, 2, 2) ! 41: if (.not. smonor(mesh, npts, 1)) call seterr( ! 42: 1 38h Buram - mesh is not strictly monotone, 38, 3, 2) ! 43: c Initialize the numerator and demoninator polynomials. ! 44: fnmax = fn(1) ! 45: fnmin = fn(1) ! 46: do 3 i = 2, npts ! 47: if (fnmax .ge. fn(i)) goto 1 ! 48: fnmax = fn(i) ! 49: goto 2 ! 50: 1 if (fn(i) .lt. fnmin) fnmin = fn(i) ! 51: 2 continue ! 52: 3 continue ! 53: call setr(m+1, 0.0e0, p) ! 54: p(1) = 0.5e0*(fnmax+fnmin) ! 55: call setr(n+1, 0.0e0, q) ! 56: q(1) = 1.0e0 ! 57: delk = fnmax-p(1) ! 58: nitr = 0 ! 59: if (m .eq. 0 .and. n .eq. 0) goto 11 ! 60: maxitr = 50 ! 61: itol = 2 ! 62: call burm1(npts, mesh, fn, maxitr, itol, m, n, p, q, delk) ! 63: if (nerror(ier) .eq. 0) goto 10 ! 64: if (ier .ne. 7) goto 4 ! 65: call newerr(38h Buram - approximation equals function, ! 66: 1 39, 4, 1) ! 67: goto 9 ! 68: 4 if (ier .ne. 8) goto 5 ! 69: call newerr( ! 70: 1 40h Buram - no improvement in approximation, 40, 5, ! 71: 2 1) ! 72: goto 8 ! 73: 5 if (ier .ne. 9) goto 6 ! 74: call newerr(30h Buram - reached 50 iterations, 30 ! 75: 1 , 6, 1) ! 76: goto 7 ! 77: 6 call eprint ! 78: 7 continue ! 79: 8 continue ! 80: 9 continue ! 81: 10 continue ! 82: 11 call leave ! 83: return ! 84: end ! 85: subroutine burm1(npts, mesh, fn, maxitr, itol, m, n, p, q, ! 86: 1 delk) ! 87: integer npts ! 88: integer maxitr, itol, m, n ! 89: real mesh(npts), fn(npts), p(1), q(1), delk ! 90: common /cstak/ dstak ! 91: double precision dstak(500) ! 92: integer istkgt, iexptr, j, idig, iflr, istak(1000) ! 93: integer enptr, qkptr, i1mach, npptr, nqptr ! 94: real abs, qlrg, float, ws(1000), r1mach ! 95: logical smonor ! 96: equivalence (dstak, istak) ! 97: equivalence (dstak, ws) ! 98: c Burm1 is a double precision subroutine which finds a ! 99: c a rational function which is the best approximation, ! 100: c in the uniform or minimax sense, to a given discrete ! 101: c function. The rational function is represented as ! 102: c the quotient of two polynomials each expanded in terms ! 103: c of Tchebychev polynomials. This routine starts from an ! 104: c initial approximation and terminates for one of four ! 105: c reasons: (1) the error curve equioscillates and the ! 106: c alternating extrema match to ITOL digits, (2) the number ! 107: c of iterations exceeds MAXITR, (3) the approximation ! 108: c cannot be improved, or (4) the approximation is essentially ! 109: c equal to the given discrete function. ! 110: c Input: ! 111: c npts - the number of mesh points. ! 112: c mesh - the array of mesh points. ! 113: c fn - the array of function values. ! 114: c maxitr - the maximum number of iterations. ! 115: c itol - the number of digits to which the extrema should match. ! 116: c m - the degree of the desired numerator polynomial. ! 117: c n - the degree of the desired denominator polynomial. ! 118: c p - the array of coefficients for the initial numerator. ! 119: c q - the array of coefficients for the initial denominator. ! 120: c Output: ! 121: c p - the array of coefficients for the numerator polynomial. ! 122: c q - the array of coefficients for the denominator polynomial. ! 123: c delk - the maximum error in the approximation. ! 124: c Error States (asterisk indicates recoverable): ! 125: c 1 - invalid degree ! 126: c 2 - too few mesh points ! 127: c 3 - mesh is not strictly monotone ! 128: c 4 - maxitr .lt. 0 ! 129: c 5 - invalid accuracy request ! 130: c 6 - denominator is nonpositive ! 131: c 7* - approximation equals function ! 132: c 8* - no improvement in approximation ! 133: c 9* - reached maximum no. of iterations ! 134: call enter(1) ! 135: if (m .lt. 0 .or. n .lt. 0) call seterr( ! 136: 1 23h Burm1 - invalid degree, 23, 1, 2) ! 137: if (npts .lt. m+n+2) call seterr(28h Burm1 - too few mesh points ! 138: 1 , 28, 2, 2) ! 139: if (.not. smonor(mesh, npts, 1)) call seterr( ! 140: 1 38h Burm1 - mesh is not strictly monotone, 38, 3, 2) ! 141: if (maxitr .lt. 0) call seterr(22h Burm1 - maxitr .lt. 0, 22, 4, 2 ! 142: 1 ) ! 143: idig = iflr(r1mach(5)*float(i1mach(11))) ! 144: if (itol .lt. 1 .or. idig .lt. itol) call seterr( ! 145: 1 33h Burm1 - invalid accuracy request, 36, 5, 2) ! 146: qlrg = abs(q(1)) ! 147: j = 2 ! 148: goto 2 ! 149: 1 j = j+1 ! 150: 2 if (j .gt. n+1) goto 3 ! 151: if (qlrg .lt. abs(q(j))) qlrg = abs(q(j)) ! 152: goto 1 ! 153: 3 if (qlrg .ne. 0.e0) goto 4 ! 154: call seterr(35h Burm1 - denominator is nonpositive, 35, 6, 2) ! 155: goto 11 ! 156: 4 j = 1 ! 157: goto 6 ! 158: 5 j = j+1 ! 159: 6 if (j .gt. n+1) goto 7 ! 160: q(j) = q(j)/qlrg ! 161: goto 5 ! 162: 7 j = 1 ! 163: goto 9 ! 164: 8 j = j+1 ! 165: 9 if (j .gt. m+1) goto 10 ! 166: p(j) = p(j)/qlrg ! 167: goto 8 ! 168: 10 continue ! 169: 11 npptr = istkgt(m+1, 3) ! 170: nqptr = istkgt(n+1, 3) ! 171: enptr = istkgt(npts, 3) ! 172: qkptr = istkgt(npts, 3) ! 173: iexptr = istkgt(npts, 2) ! 174: call b1rm1(npts, mesh, fn, maxitr, itol, m, n, p, q, delk, ws( ! 175: 1 npptr), ws(nqptr), ws(enptr), ws(qkptr), istak(iexptr)) ! 176: call leave ! 177: return ! 178: end ! 179: subroutine b1rm1(npts, x, fn, maxitr, itol, m, n, p, q, ! 180: 1 delk, newp, newq, en, qk, iext) ! 181: integer npts ! 182: integer maxitr, itol, m, n, iext(npts) ! 183: real x(npts), fn(npts), p(1), q(1), delk, newp(1) ! 184: real newq(1), en(npts), qk(npts) ! 185: common /dfccom/ nitr ! 186: integer nitr ! 187: integer ier, nex, nerror, i, imin, imax ! 188: integer ilrg, lrgex ! 189: real bnd, abs, eps, delnew, r1mach ! 190: eps = r1mach(4)*10.0e0**itol ! 191: call extrmr(npts, fn, nex, iext, imax, imin, ilrg) ! 192: bnd = abs(fn(ilrg))*eps ! 193: call enqk(npts, x, fn, m, n, p, q, qk, en) ! 194: do 1 i = 1, npts ! 195: if (qk(i) .le. 0.0e0) call seterr( ! 196: 1 35h Burm1 - denominator is nonpositive, 35, 6, 2) ! 197: 1 continue ! 198: call extrmr(npts, en, nex, iext, imax, imin, ilrg) ! 199: delk = abs(en(ilrg)) ! 200: delnew = delk ! 201: call movefr(m+1, p, newp) ! 202: call movefr(n+1, q, newq) ! 203: nitr = 0 ! 204: goto 3 ! 205: 2 nitr = nitr+1 ! 206: 3 if (nitr .ge. maxitr) goto 6 ! 207: c call Outpt3 (x,npts,p,q,delk,m,n,en,iext,nex) ! 208: if (delk .gt. bnd) goto 4 ! 209: call seterr(38h Burm1 - approximation equals function, 39, 7 ! 210: 1 , 1) ! 211: return ! 212: c Test for optimal solution. ! 213: 4 if (lrgex(npts, en, nex, iext, ilrg, itol) .ge. m+n+2) return ! 214: call lpstp(npts, x, fn, qk, delnew, m, n, newp, newq) ! 215: if (nerror(ier) .ne. 0) call erroff ! 216: call enqk(npts, x, fn, m, n, newp, newq, qk, en) ! 217: call extrmr(npts, en, nex, iext, imax, imin, ilrg) ! 218: delnew = abs(en(ilrg)) ! 219: if (delk .gt. delnew) goto 5 ! 220: call seterr(40h Burm1 - no improvement in approximation, 40, ! 221: 1 8, 1) ! 222: return ! 223: 5 call movefr(m+1, newp, p) ! 224: call movefr(n+1, newq, q) ! 225: delk = delnew ! 226: goto 2 ! 227: 6 call seterr(42h Burm1 - reached maximum no. of iterations, 42, 9 ! 228: 1 , 1) ! 229: return ! 230: end ! 231: subroutine enqk(npts, x, fn, m, n, p, q, qk, en) ! 232: integer npts ! 233: integer m, n ! 234: real x(npts), fn(npts), p(1), q(1), qk(npts), en(npts) ! 235: integer i ! 236: real pk, tchbp ! 237: c ! 238: c Subroutine Enqk computes en & Qk. ! 239: c en=error values at mesh points. ! 240: c Qk=value of denominator polynomial at mesh points. ! 241: c ! 242: if (npts .le. 0 .or. m .lt. 0 .or. n .lt. 0) call seterr( ! 243: 1 22henQk-invalid dimension, 22, 1, 2) ! 244: do 1 i = 1, npts ! 245: qk(i) = tchbp(n, q, x(i), x(1), x(npts)) ! 246: if (qk(i) .eq. 0.e0) call seterr(20henQk-divisor .eq. 0., 20, 2 ! 247: 1 , 2) ! 248: pk = tchbp(m, p, x(i), x(1), x(npts)) ! 249: en(i) = (fn(i)*qk(i)-pk)/qk(i) ! 250: 1 continue ! 251: return ! 252: end ! 253: integer function lrgex(npts, en, nex, iext, ilrg, tol) ! 254: integer nex, npts ! 255: integer iext(nex), ilrg, tol ! 256: real en(npts) ! 257: integer j, k, l ! 258: real abs, hold ! 259: c ! 260: c Function Lrgex finds the no. of error extrema with magnitudes ! 261: c within tolerance of magnitude of largest error. ! 262: c ! 263: if (npts .le. 0) call seterr(24hLrgex -invalid dimension, 24, 1, 2 ! 264: 1 ) ! 265: if (nex .le. 0 .or. ilrg .le. 0) call seterr( ! 266: 1 20hLrgex -invalid index, 20, 2, 2) ! 267: k = 0 ! 268: do 1 j = 1, nex ! 269: l = iext(j) ! 270: hold = abs(en(ilrg))-abs(en(l)) ! 271: if (hold .le. 10.**(-tol)*abs(en(ilrg))) k = k+1 ! 272: 1 continue ! 273: lrgex = k ! 274: return ! 275: end ! 276: subroutine lpstp(npts, mesh, fn, qk, delk, m, n, p, q) ! 277: integer npts ! 278: integer m, n ! 279: real mesh(npts), fn(npts), qk(npts), delk, p(1), q(1) ! 280: common /cstak/ dstak ! 281: double precision dstak(500) ! 282: integer istkgt, aptr, bptr, cptr, xptr, istak(1000) ! 283: real ws(1000) ! 284: equivalence (dstak, istak) ! 285: equivalence (dstak, ws) ! 286: c Lpstp defines the linear programming subproblem of the ! 287: c Differential Correction algorithm. It also provides ! 288: c the interface to the general purpose linear programming ! 289: c package. ! 290: c Input: ! 291: c npts - the number of mesh points. ! 292: c mesh - the array of mesh points. ! 293: c fn - the array of function values. ! 294: c Qk - the array of current denominator values. ! 295: c delk - the current minimax error. ! 296: c m - the degree of the numerator polynomial. ! 297: c n - the degree of the denominator polynomial. ! 298: c p - the current numerator polynomial. ! 299: c q - the current denominator polynomial. ! 300: c Output: ! 301: c p - the array of coefficients for the numerator polynomial. ! 302: c q - the array of coefficients for the denominator polynomial. ! 303: c Error States (asterisk indicates fatal): ! 304: c 1* - invalid degree ! 305: c 2* - too few mesh points ! 306: c 3* - nonpositive delk ! 307: c 4 - no improvement in the lp subproblem ! 308: call enter(1) ! 309: if (m .lt. 0 .or. n .lt. 0) call seterr( ! 310: 1 23h Lpstp - invalid degree, 23, 1, 2) ! 311: if (npts .lt. m+n+2) call seterr(28h Lpstp - too few mesh points ! 312: 1 , 28, 2, 2) ! 313: aptr = istkgt(3*npts+1, 3) ! 314: bptr = istkgt(2*(npts+n+1), 3) ! 315: cptr = istkgt(m+n+3, 3) ! 316: xptr = istkgt(m+n+3, 3) ! 317: call l9stp(npts, mesh, fn, qk, delk, m, n, p, q, ws(aptr), ws( ! 318: 1 bptr), ws(cptr), ws(xptr)) ! 319: call leave ! 320: return ! 321: end ! 322: subroutine l9stp(npts, mesh, fn, qk, delk, m, n, p, q, a, b, ! 323: 1 c, x) ! 324: integer npts ! 325: integer m, n ! 326: real mesh(npts), fn(npts), qk(npts), delk, p(1), q(1) ! 327: real a(1), b(1), c(1), x(1) ! 328: common /difcom/ nptsc, mc, nc, i1, i2, i3, i4 ! 329: integer nptsc, mc, nc, i1, i2, i3 ! 330: integer i4 ! 331: external difmt ! 332: integer ier, nerror, i, j, ierr, mm ! 333: integer nn ! 334: real abs, ctx, ctxnew, qlrg, float, r1mach ! 335: nptsc = npts ! 336: mc = m ! 337: nc = n ! 338: i1 = npts ! 339: i2 = i1+npts ! 340: i3 = i2+n+1 ! 341: i4 = i3+n+1 ! 342: mm = i4 ! 343: nn = m+n+3 ! 344: call movefr(n+1, q, x) ! 345: call movefr(m+1, p, x(n+2)) ! 346: x(nn) = 0.e0 ! 347: call setr(i2, 0.0e0, b) ! 348: call setr(i4-i2, -1.0e0, b(i2+1)) ! 349: call setr(nn, 0.0e0, c) ! 350: c(nn) = -1.0e0 ! 351: call movefr(npts, mesh, a) ! 352: call movefr(npts, fn, a(npts+1)) ! 353: call movefr(npts, qk, a(2*npts+1)) ! 354: if (delk .le. 0.0e0) call seterr(25h Lpstp - nonpositive delk, 25, ! 355: 1 3, 2) ! 356: a(3*npts+1) = delk ! 357: ctx = 0.0e0 ! 358: c Solve the LP problem: max C(T)X subject to AX >= B. ! 359: c The subroutine Difmt derives the matrix A from ! 360: c the data stored in the array A. ! 361: call lpph2(a, mm, nn, difmt, b, c, x, 4*mm, ctxnew) ! 362: if (nerror(ier) .ne. 0) call erroff ! 363: if (ctx .ge. ctxnew) goto 10 ! 364: qlrg = 0.0e0 ! 365: j = 1 ! 366: goto 2 ! 367: 1 j = j+1 ! 368: 2 if (j .gt. n+1) goto 3 ! 369: if (qlrg .lt. abs(x(j))) qlrg = abs(x(j)) ! 370: goto 1 ! 371: 3 j = 1 ! 372: goto 5 ! 373: 4 j = j+1 ! 374: 5 if (j .gt. n+1) goto 6 ! 375: q(j) = x(j)/qlrg ! 376: goto 4 ! 377: 6 i = 0 ! 378: j = n+2 ! 379: goto 8 ! 380: 7 j = j+1 ! 381: 8 if (j .gt. m+n+2) goto 9 ! 382: i = i+1 ! 383: p(i) = x(j)/qlrg ! 384: goto 7 ! 385: 9 continue ! 386: goto 11 ! 387: 10 call seterr(44h Lpstp - no improvement in the lp subproblem, ! 388: 1 44, 4, 1) ! 389: 11 return ! 390: end ! 391: subroutine difmt(inprod, a, mm, nn, irow, x, dinprd) ! 392: integer nn ! 393: integer mm, irow ! 394: real a(1), x(nn), dinprd ! 395: logical inprod ! 396: common /difcom/ npts, m, n, i1, i2, i3, i4 ! 397: integer npts, m, n, i1, i2, i3 ! 398: integer i4 ! 399: integer max0, irm1, irm2, irm3, j, zptr ! 400: integer jp, maxmn, fnptr, qzptr ! 401: real fct, delk, z, fn, fdelk, tchbp ! 402: real qz ! 403: c Difmt handles references by the LP routine to ! 404: c the matrix for the linear programming subproblem. ! 405: call enter(1) ! 406: if (mm .ne. i4 .or. nn .ne. m+n+3) call seterr( ! 407: 1 26h Difmt - invalid dimension, 26, 1, 2) ! 408: if (irow .lt. 0 .or. mm .lt. irow) call seterr( ! 409: 1 22h Difmt - invalid index, 22, 2, 2) ! 410: irm1 = irow-i1 ! 411: irm2 = irow-i2 ! 412: irm3 = irow-i3 ! 413: if ((.not. inprod) .or. i2 .ge. irow) goto 3 ! 414: if (i3 .ge. irow) goto 1 ! 415: dinprd = -x(irm3) ! 416: goto 2 ! 417: 1 dinprd = x(irm2) ! 418: 2 continue ! 419: goto 18 ! 420: 3 if (i2 .ge. irow) goto 6 ! 421: call setr(nn, 0.0e0, x) ! 422: if (i3 .ge. irow) goto 4 ! 423: x(irm3) = -1.0e0 ! 424: goto 5 ! 425: 4 x(irm2) = 1.0e0 ! 426: 5 continue ! 427: goto 17 ! 428: 6 if (i1 .ge. irow) goto 7 ! 429: fct = -1.0e0 ! 430: zptr = irm1 ! 431: goto 8 ! 432: 7 fct = 1.0e0 ! 433: zptr = irow ! 434: 8 z = a(zptr) ! 435: fnptr = zptr+npts ! 436: fn = a(fnptr) ! 437: qzptr = fnptr+npts ! 438: qz = a(qzptr) ! 439: delk = a(3*npts+1) ! 440: fdelk = fct*fn+delk ! 441: if (.not. inprod) goto 9 ! 442: dinprd = fdelk*tchbp(n, x, z, a(1), a(npts))-fct*tchbp(m, ! 443: 1 x(n+2), z, a(1), a(npts))+qz*x(nn) ! 444: goto 16 ! 445: 9 maxmn = max0(m, n) ! 446: call tchcf(z, a(1), a(npts), maxmn, x) ! 447: j = m+1 ! 448: goto 11 ! 449: 10 j = j-1 ! 450: 11 if (1 .gt. j) goto 12 ! 451: jp = j+n+1 ! 452: x(jp) = (-fct)*x(j) ! 453: goto 10 ! 454: 12 j = 1 ! 455: goto 14 ! 456: 13 j = j+1 ! 457: 14 if (j .gt. n+1) goto 15 ! 458: x(j) = fdelk*x(j) ! 459: goto 13 ! 460: 15 x(nn) = qz ! 461: 16 continue ! 462: 17 continue ! 463: 18 call leave ! 464: return ! 465: end ! 466: subroutine tchcf(x, a, b, deg, xx) ! 467: integer deg ! 468: real x, a, b, xx(1) ! 469: integer i ! 470: real twoxx ! 471: c ! 472: c Subroutine Tchcf computes the deg+1 Tchebycheff ! 473: c coefficients of the point x. ! 474: c ! 475: call enter(1) ! 476: if (deg .lt. 0) call seterr(21h Tchcf-invalid degree, 21, 1, 2) ! 477: xx(1) = 1.e0 ! 478: if (deg .le. 0) goto 3 ! 479: if (b .gt. a) goto 1 ! 480: call seterr(23h Tchcf-invalid interval, 23, 2, 2) ! 481: goto 2 ! 482: 1 xx(2) = 2.e0*(x-(a+b)/2.e0)/(b-a) ! 483: cscale x to the interval (-1.e0,1.e0) ! 484: 2 continue ! 485: 3 if (deg .gt. 1) twoxx = 2.e0*xx(2) ! 486: i = 3 ! 487: goto 5 ! 488: 4 i = i+1 ! 489: 5 if (i .gt. deg+1) goto 6 ! 490: xx(i) = twoxx*xx(i-1)-xx(i-2) ! 491: goto 4 ! 492: 6 call leave ! 493: return ! 494: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.