diff options
author | jcorgan | 2006-08-03 04:51:51 +0000 |
---|---|---|
committer | jcorgan | 2006-08-03 04:51:51 +0000 |
commit | 5d69a524f81f234b3fbc41d49ba18d6f6886baba (patch) | |
tree | b71312bf7f1e8d10fef0f3ac6f28784065e73e72 /gnuradio-core/src/gen_interpolator_taps | |
download | gnuradio-5d69a524f81f234b3fbc41d49ba18d6f6886baba.tar.gz gnuradio-5d69a524f81f234b3fbc41d49ba18d6f6886baba.tar.bz2 gnuradio-5d69a524f81f234b3fbc41d49ba18d6f6886baba.zip |
Houston, we have a trunk.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@3122 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'gnuradio-core/src/gen_interpolator_taps')
-rw-r--r-- | gnuradio-core/src/gen_interpolator_taps/Makefile.am | 33 | ||||
-rw-r--r-- | gnuradio-core/src/gen_interpolator_taps/README | 47 | ||||
-rw-r--r-- | gnuradio-core/src/gen_interpolator_taps/gen_interpolator_taps.c | 186 | ||||
-rw-r--r-- | gnuradio-core/src/gen_interpolator_taps/objective_fct.c | 124 | ||||
-rw-r--r-- | gnuradio-core/src/gen_interpolator_taps/praxis.f | 1705 | ||||
-rw-r--r-- | gnuradio-core/src/gen_interpolator_taps/praxis.txt | 176 | ||||
-rw-r--r-- | gnuradio-core/src/gen_interpolator_taps/simpson.c | 76 | ||||
-rw-r--r-- | gnuradio-core/src/gen_interpolator_taps/simpson.h | 3 |
8 files changed, 2350 insertions, 0 deletions
diff --git a/gnuradio-core/src/gen_interpolator_taps/Makefile.am b/gnuradio-core/src/gen_interpolator_taps/Makefile.am new file mode 100644 index 000000000..fff6372c1 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/Makefile.am @@ -0,0 +1,33 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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 2, or (at your option) +# any later version. +# +# GNU Radio 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. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = praxis.txt simpson.h + +if ENABLE_FORTRAN +noinst_PROGRAMS = gen_interpolator_taps +noinst_HEADERS = simpson.h + +gen_interpolator_taps_SOURCES = gen_interpolator_taps.c objective_fct.c simpson.c praxis.f +gen_interpolator_taps_LDADD = $(FLIBS) -lm + +endif diff --git a/gnuradio-core/src/gen_interpolator_taps/README b/gnuradio-core/src/gen_interpolator_taps/README new file mode 100644 index 000000000..cc2f1ac89 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/README @@ -0,0 +1,47 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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 2, or (at your option) +# any later version. +# +# GNU Radio 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. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +This file contains the source for gen_interpolator_taps, a program +which generates optimal interpolator taps for a fractional +interpolator. + +The ideal interpolator requires an infinite tap FIR filter to +realize. We design a separate 8 tap filter for each value of mu, +the fractional delay, that we are interested in. The taps are +selected such that the mean squared error between the ideal frequency +response and the approximation is mininimized over all frequencies of +interest. In this implementation we define ``frequencies of +interest'' as those from -B to +B, where B = 1/(4*Ts), where Ts is the +sampling period. + +For a detailed look at what this is all about, please see Chapter 9 of +"Digital Communication Receivers: Synchronization, Channel Estimation +and Signal Processing" by Meyr, Moeneclaey and Fechtel, ISBN 0-471-50275-8 + +NOTE, if you're running gen_interpolator_taps and it seg faults in +RANDOM, you're probably using g77-2.96. The fix is to use g77 3.0 or later + + cd <top_of_build_tree> + rm config.cache + export F77=g77-3.0.4 + ./configure + make diff --git a/gnuradio-core/src/gen_interpolator_taps/gen_interpolator_taps.c b/gnuradio-core/src/gen_interpolator_taps/gen_interpolator_taps.c new file mode 100644 index 000000000..0dd05651d --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/gen_interpolator_taps.c @@ -0,0 +1,186 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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 2, or (at your option) + * any later version. + * + * GNU Radio 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. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> + +#define NSTEPS 10 // how many steps of mu are in the generated table +#define MAX_NSTEPS 256 +#define NTAPS 8 // # of taps in the interpolator +#define MAX_NTAPS 128 + +extern void initpt (double x[], int ntaps); +extern double objective (double x[], int *ntaps); +extern double global_mu; +extern double global_B; + +// fortran +extern double prax2_ (double (fct)(double x[], int *ntaps), + double initv[], int *ntaps, double result[]); + +static void +usage (char *name) +{ + fprintf (stderr, "usage: %s [-v] [-n <nsteps>] [-t <ntaps>] [-B <bw>]\n", name); + exit (1); +} + +static void +printline (double x[], int ntaps, int imu, int nsteps) +{ + int i; + + printf (" { "); + for (i = 0; i < ntaps; i++){ + printf ("%12.5e", x[i]); + if (i != ntaps - 1) + printf (", "); + else + printf (" }, // %3d/%d\n", imu, nsteps); + } +} + +int +main (int argc, char **argv) +{ + double xx[MAX_NSTEPS+1][MAX_NTAPS]; + int ntaps = NTAPS; + int nsteps = NSTEPS; + int i, j; + double result; + double step_size; + int c; + int verbose = 0; + + global_B = 0.25; + + while ((c = getopt (argc, argv, "n:t:B:v")) != EOF){ + switch (c){ + case 'n': + nsteps = strtol (optarg, 0, 0); + break; + + case 't': + ntaps = strtol (optarg, 0, 0); + break; + + case 'B': + global_B = strtod (optarg, 0); + break; + + case 'v': + verbose = 1; + break; + + default: + usage (argv[0]); + break; + } + } + + if ((nsteps & 1) != 0){ + fprintf (stderr, "%s: nsteps must be even\n", argv[0]); + exit (1); + } + + if (nsteps > MAX_NSTEPS){ + fprintf (stderr, "%s: nsteps must be < %d\n", argv[0], MAX_NSTEPS); + exit (1); + } + + if ((ntaps & 1) != 0){ + fprintf (stderr, "%s: ntaps must be even\n", argv[0]); + exit (1); + } + + if (nsteps > MAX_NTAPS){ + fprintf (stderr, "%s: ntaps must be < %d\n", argv[0], MAX_NTAPS); + exit (1); + } + + if (global_B < 0 || global_B > 0.5){ + fprintf (stderr, "%s: bandwidth must be in the range (0, 0.5)\n", argv[0]); + exit (1); + } + + step_size = 1.0/nsteps; + + // the optimizer chokes on the two easy cases (0/N and N/N). We do them by hand... + + for (i = 0; i < ntaps; i++) + xx[0][i] = 0.0; + xx[0][ntaps/2] = 1.0; + + + // compute optimal values for mu <= 0.5 + + for (j = 1; j <= nsteps/2; j++){ + + global_mu = j * step_size; // this determines the MU for which we're computing the taps + + // initialize X to a reasonable starting value + + initpt (&xx[j][0], ntaps); + + // find the value of X that minimizes the value of OBJECTIVE + + result = prax2_ (objective, &xx[j][0], &ntaps, &xx[j][0]); + + if (verbose){ + fprintf (stderr, "Mu: %10.8f\t", global_mu); + fprintf (stderr, "Objective: %g\n", result); + } + } + + // now compute remaining values via symmetry + + for (j = 0; j < nsteps/2; j++){ + for (i = 0; i < ntaps; i++){ + xx[nsteps - j][i] = xx[j][ntaps-i-1]; + } + } + + // now print out the table + + printf ("\ +/*\n\ + * This file was machine generated by gen_interpolator_taps.\n\ + * DO NOT EDIT BY HAND.\n\ + */\n\n"); + + + printf ("static const int NTAPS = %4d;\n", ntaps); + printf ("static const int NSTEPS = %4d;\n", nsteps); + printf ("static const double BANDWIDTH = %g;\n\n", global_B); + + printf ("static const float taps[NSTEPS+1][NTAPS] = {\n"); + printf (" // -4 -3 -2 -1 0 1 2 3 mu\n"); + + + for (i = 0; i <= nsteps; i++) + printline (xx[i], ntaps, i, nsteps); + + printf ("};\n\n"); + + return 0; +} diff --git a/gnuradio-core/src/gen_interpolator_taps/objective_fct.c b/gnuradio-core/src/gen_interpolator_taps/objective_fct.c new file mode 100644 index 000000000..aab0008e3 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/objective_fct.c @@ -0,0 +1,124 @@ +/* -*- c -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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 2, or (at your option) + * any later version. + * + * GNU Radio 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. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * generate MMSE FIR interpolation table values + */ + +#include <math.h> +#include <assert.h> +#include "simpson.h" + +#define MU 0.5 /* the MU for which we're computing coeffs */ + +#define Ts (1.0) /* sampling period */ +#define B (1.0/(4*Ts)) /* one-sided signal bandwidth */ +//#define B (1.0/(8./3*Ts)) /* one-sided signal bandwidth */ + +static unsigned global_n; +static double *global_h; +double global_mu = MU; +double global_B = B; + +/* + * This function computes the difference squared between the ideal + * interpolator frequency response at frequency OMEGA and the + * approximation defined by the FIR coefficients in global_h[] + * + * See eqn (9-7), "Digital Communication Receivers", Meyr, Moeneclaey + * and Fechtel, Wiley, 1998. + */ + +static double +integrand (double omega) +{ + double real_ideal; + double real_approx; + double real_diff; + double imag_ideal; + double imag_approx; + double imag_diff; + + int i, n; + int I1; + double *h; + + real_ideal = cos (omega * Ts * global_mu); + imag_ideal = sin (omega * Ts * global_mu); + + n = global_n; + h = global_h; + I1 = -(n / 2); + + real_approx = 0; + imag_approx = 0; + + for (i = 0; i < n; i++){ + real_approx += h[i] * cos (-omega * Ts * (i + I1)); + imag_approx += h[i] * sin (-omega * Ts * (i + I1)); + } + + real_diff = real_ideal - real_approx; + imag_diff = imag_ideal - imag_approx; + + return real_diff * real_diff + imag_diff * imag_diff; +} + +/* + * Integrate the difference squared over all frequencies of interest. + */ +double +c_fcn (double *x, int n) +{ + assert ((n & 1) == 0); /* assert n is even */ + global_n = n; + global_h = x; + return qsimp (integrand, -2 * M_PI * global_B, 2 * M_PI * global_B); +} + +/* this is the interface expected by the calling fortran code */ + +double +objective (double x[], int *ndim) +{ + return c_fcn (x, *ndim); +} + +static double +si (double x) +{ + if (fabs (x) < 1e-9) + return 1.0; + + return sin(x) / x; +} + +/* + * starting guess for optimization + */ +void initpt (double x[], int ndim) +{ + int i; + for (i = 0; i < ndim; i++){ + x[i] = si (M_PI * ((double) (i - ndim/2) + global_mu)); + } +} diff --git a/gnuradio-core/src/gen_interpolator_taps/praxis.f b/gnuradio-core/src/gen_interpolator_taps/praxis.f new file mode 100644 index 000000000..1b648b9bb --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/praxis.f @@ -0,0 +1,1705 @@ +C +C Copyright 2002 Free Software Foundation, Inc. +C +C This file is part of GNU Radio +C +C GNU Radio is free software; you can redistribute it and/or modify +C it under the terms of the GNU General Public License as published by +C the Free Software Foundation; either version 2, or (at your option) +C any later version. +C +C GNU Radio is distributed in the hope that it will be useful, +C but WITHOUT ANY WARRANTY; without even the implied warranty of +C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +C GNU General Public License for more details. +C +C You should have received a copy of the GNU General Public License +C along with GNU Radio; see the file COPYING. If not, write to +C the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +C Boston, MA 02111-1307, USA. +C + DOUBLE PRECISION FUNCTION PRAX2(F,INITV,NDIM,OUT) + DOUBLE PRECISION INITV(128),OUT(128), F + INTEGER NDIM + EXTERNAL F +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + +C + N=NDIM + do 10 I=1,N + 10 X(I) = INITV(I) + +C + call praset + +C -1 produces no diagnostic output + jprint = -1 + nfmax = 3000 +C tighter tolerance + T=1.0D-6 +C + call praxis(f) +C + do 30 I=1,N + 30 OUT(I) = X(I) +C + prax2 = fx + return + end + + + SUBROUTINE PRASET +C +C PRASET 1.0 JUNE 1995 +C +C SET INITIAL VALUES FOR SOME QUANTITIES USED IN SUBROUTINE PRAXIS. +C THE USER CAN RESET THESE, IF DESIRED, +C AFTER CALLING PRASET AND BEFORE CALLING PRAXIS. +C +C J. P. CHANDLER, COMPUTER SCIENCE DEPARTMENT, +C OKLAHOMA STATE UNIVERSITY +C +C ON MANY MACHINES, SUBROUTINE PRAXIS WILL CAUSE UNDERFLOW AND/OR +C DIVIDE CHECK WHEN COMPUTING EPSMCH**4 AND EPSMCH**(-4). +C IN THAT CASE, SET EPSMCH=1.0D-9 (OR POSSIBLY EPSMCH=1.0D-8) +C AFTER CALLING SUBROUTINE PRASET. +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER J +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION A,B,XMID,XPLUS,RZERO,UNITR,RTWO +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + RZERO=0.0D0 + UNITR=1.0D0 + RTWO=2.0D0 +C +C NMAX IS THE DIMENSION OF THE ARRAYS V(*,*), X(*), D(*), +C Q0(*), AND Q1(*). +C + NMAX=128 +C +C NFMAX IS THE MAXIMUM NUMBER OF FUNCTION EVALUATIONS PERMITTED. +C + NFMAX=100000 +C +C LP IS THE LOGICAL UNIT NUMBER FOR PRINTED OUTPUT. +C + LP=6 +C +C T IS A CONVERGENCE TOLERANCE USED IN SUBROUTINE PRAXIS. +C + T=1.0D-5 +C +C JPRINT CONTROLS PRINTED OUTPUT IN PRAXIS. +C + JPRINT=4 +C +C H IS AN ESTIMATE OF THE DISTANCE FROM THE INITIAL POINT +C TO THE SOLUTION. +C + H=1.0D0 +C +C USE BISECTION TO COMPUTE THE VALUE OF EPSMCH, "MACHINE EPSILON". +C EPSMCH IS THE SMALLEST FLOATING POINT (REAL OR DOUBLE PRECISION) +C NUMBER WHICH, WHEN ADDED TO ONE, GIVES A RESULT GREATER THAN ONE. +C + A=RZERO + B=UNITR + 10 XMID=A+(B-A)/RTWO + IF(XMID.LE.A .OR. XMID.GE.B) GO TO 20 + XPLUS=UNITR+XMID + IF(XPLUS.GT.UNITR) THEN + B=XMID + ELSE + A=XMID + ENDIF + GO TO 10 +C + 20 EPSMCH=B +C + DO 30 J=1,NMAX + X(J)=RZERO + 30 CONTINUE +C +C JRANCH = 1 TO USE BRENT'S RANDOM, +C JRANCH = 2 TO USE FUNCTION DRANDM. +C + JRANCH=1 +C + CALL RANINI(4.0D0) +C +C DSEED IS AN INITIAL SEED FOR DRANDM, +C A SUBROUTINE THAT GENERATES PSEUDORANDOM NUMBERS +C UNIFORMLY DISTRIBUTED ON (0,1). +C + DSEED=1234567.0D0 +C +C SCBD IS AN UPPER BOUND ON THE SCALE FACTORS IN PRAXIS. +C IF THE AXES MAY BE BADLY SCALED (WHICH IS TO BE AVOIDED IF +C POSSIBLE) THEN SET SCBD = 10, OTHERWISE 1. +C + SCBD=1.0D0 +C +C ILLCIN IS THE INITIAL VALUE OF ILLC, +C THE FLAG THAT SIGNALS AN ILL-CONDITIONED PROBLEM. +C IF THE PROBLEM IS KNOWN TO BE ILL-CONDITIONED SET ILLCIN=1, +C OTHERWISE 0. +C + ILLCIN=0 +C +C KTM IS A CONVERGENCE SWITCH USED IN PRAXIS. +C KTM+1 IS THE NUMBER OF ITERATIONS WITHOUT IMPROVEMENT +C BEFORE THE ALGORITHM TERMINATES. +C KTM=4 IS VERY CAUTIOUS. +C USUALLY KTM=1 IS SATISFACTORY. +C + KTM=1 +C + RETURN +C +C END PRASET +C + END + SUBROUTINE PRAXIS(F) +C +C PRAXIS 2.0 JUNE 1995 +C +C THE PRAXIS PACKAGE MINIMIZES THE FUNCTION F(X,N) OF N +C VARIABLES X(1),...,X(N), USING THE PRINCIPAL AXIS METHOD. +C F MUST BE A SMOOTH (CONTINUOUSLY DIFFERENTIABLE) FUNCTION. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973 (ISBN 0-13-022335-2), +C PAGES 156-167 +C +C TRANSLATED FROM ALGOL W TO A.N.S.I. 1966 STANDARD BASIC FORTRAN +C BY ROSALEE TAYLOR AND SUE PINSKI, COMPUTER SCIENCE DEPARTMENT, +C OKLAHOMA STATE UNIVERSITY (DECEMBER 1973). +C +C UPDATED TO A.N.S.I. STANDARD FORTRAN 77 BY J. P. CHANDLER +C COMPUTER SCIENCE DEPARTMENT, OKLAHOMA STATE UNIVERSITY +C +C +C SUBROUTINE PRAXIS CALLS SUBPROGRAMS +C F, MINX, RANDOM (OR DRANDM), QUAD, MINFIT, SORT. +C +C SUBROUTINE QUAD CALLS MINX. +C +C SUBROUTINE MINX CALLS FLIN. +C +C SUBROUTINE FLIN CALLS F. +C +C +C INPUT QUANTITIES (SET IN THE CALLING PROGRAM)... +C +C F FUNCTION F(X,N) TO BE MINIMIZED +C +C X(*) INITIAL GUESS OF MINIMUM +C +C N DIMENSION OF X (NOTE... N MUST BE .GE. 2) +C +C H MAXIMUM STEP SIZE +C +C T TOLERANCE +C +C EPSMCH MACHINE PRECISION +C +C JPRINT PRINT SWITCH +C +C +C OUTPUT QUANTITIES... +C +C X(*) ESTIMATED POINT OF MINIMUM +C +C FX VALUE OF F AT X +C +C NL NUMBER OF LINEAR SEARCHES +C +C NF NUMBER OF FUNCTION EVALUATIONS +C +C V(*,*) EIGENVECTORS OF A +C NEW DIRECTIONS +C +C D(*) EIGENVALUES OF A +C NEW D +C +C Z(*) SCALE FACTORS +C +C +C ON ENTRY X(*) HOLDS A GUESS. ON RETURN IT HOLDS THE ESTIMATED +C POINT OF MINIMUM, WITH (HOPEFULLY) +C ABS(ERROR) LESS THAN SQRT(EPSMCH)*ABS(X) + T, WHERE +C EPSMCH IS THE MACHINE PRECISION, THE SMALLEST NUMBER SUCH THAT +C (1 + EPSMCH) IS GREATER THAN 1. +C +C T IS A TOLERANCE. +C +C H IS THE MAXIMUM STEP SIZE, SET TO ABOUT THE MAXIMUM EXPECTED +C DISTANCE FROM THE GUESS TO THE MINIMUM. IF H IS SET TOO +C SMALL OR TOO LARGE THEN THE INITIAL RATE OF CONVERGENCE WILL +C BE SLOW. +C +C THE USER SHOULD OBSERVE THE COMMENT ON HEURISTIC NUMBERS +C AT THE BEGINNING OF THE SUBROUTINE. +C +C JPRINT CONTROLS THE PRINTING OF INTERMEDIATE RESULTS. +C IT USES SUBROUTINES FLIN, MINX, QUAD, SORT, AND MINFIT. +C IF JPRINT = 1, F IS PRINTED AFTER EVERY N+1 OR N+2 LINEAR +C MINIMIZATIONS, AND FINAL X IS PRINTED, BUT INTERMEDIATE +C X ONLY IF N IS LESS THAN OR EQUAL TO 4. +C IF JPRINT = 2, EIGENVALUES OF A AND SCALE FACTORS ARE ALSO PRINTED. +C IF JPRINT = 3, F AND X ARE PRINTED AFTER EVERY FEW LINEAR +C MINIMIZATIONS. +C IF JPRINT = 4, EIGENVECTORS ARE ALSO PRINTED. +C IF JPRINT = 5, ADDITIONAL DEBUGGING INFORMATION IS ALSO PRINTED. +C +C RANDOM RETURNS A RANDOM NUMBER UNIFORMLY DISTRIBUTED IN (0, 1). +C +C THIS SUBROUTINE IS MACHINE-INDEPENDENT, APART FROM THE +C SPECIFICATION OF EPSMCH. WE ASSUME THAT EPSMCH**(-4) DOES NOT +C OVERFLOW (IF IT DOES THEN EPSMCH MUST BE INCREASED), AND THAT ON +C FLOATING-POINT UNDERFLOW THE RESULT IS SET TO ZERO. +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER ILLC,I,IK,IM,IMU,J,K,KL,KM1,KT,K2 +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION F, Y,Z,E, DABS,DSQRT,ZABS,ZSQRT,DRANDM, + * HUNDRD,HUNDTH,ONE,PT9,RHALF,TEN,TENTH,TWO,ZERO, + * DF,DLDFAC,DN,F1,XF,XL,T2,RANVAL,ARG, + * VLARGE,VSMALL,XLARGE,XLDS,FXVALU,F1VALU,S,SF,SL +C + EXTERNAL F +C + DIMENSION Y(128),Z(128),E(128) +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + ZABS(ARG)=DABS(ARG) + ZSQRT(ARG)=DSQRT(ARG) +C +C INITIALIZATION... +C + RHALF=0.5D0 + ONE=1.0D0 + TENTH=0.1D0 + HUNDTH=0.01D0 + HUNDRD=100.0D0 + ZERO=0.0D0 + PT9=0.9D0 + TEN=10.0D0 + TWO=2.0D0 +C +C MACHINE DEPENDENT NUMBERS... +C +C ON MANY COMPUTERS, VSMALL WILL UNDERFLOW, +C AND COMPUTING XLARGE MAY CAUSE A DIVISION BY ZERO. +C IN THAT CASE, EPSMCH SHOULD BE SET EQUAL TO 1.0D-9 +C (OR POSSIBLY 1.0D-8) BEFORE CALLING PRAXIS. +C + SMALL=EPSMCH*EPSMCH + VSMALL=SMALL*SMALL + XLARGE=ONE/SMALL + VLARGE=ONE/VSMALL + XM2=ZSQRT(EPSMCH) + XM4=ZSQRT(XM2) +C +C HEURISTIC NUMBERS... +C +C IF THE AXES MAY BE BADLY SCALED (WHICH IS TO BE AVOIDED IF +C POSSIBLE) THEN SET SCBD = 10, OTHERWISE 1. +C +C IF THE PROBLEM IS KNOWN TO BE ILL-CONDITIONED SET ILLC = 1, +C OTHERWISE 0. +C +C KTM+1 IS THE NUMBER OF ITERATIONS WITHOUT IMPROVEMENT +C BEFORE THE ALGORITHM TERMINATES. +C KTM=4 IS VERY CAUTIOUS. +C USUALLY KTM=1 IS SATISFACTORY. +C +C BRENT RECOMMENDED THE FOLLOWING VALUES FOR MOST PROBLEMS... +C +C SCBD=1.0 +C ILLC=0 +C KTM=1 +C +C SCBD, ILLCIN, AND KTM ARE NOW IN COMMON. +C THEY ARE INITIALIZED IN SUBROUTINE PRASET, +C AND CAN BE RESET BY THE USER AFTER CALLING PRASET. +C + ILLC=ILLCIN +C + IF(ILLC.EQ.1) THEN + DLDFAC=TENTH + ELSE + DLDFAC=HUNDTH + ENDIF +C + KT=0 + NL=0 + NF=1 + FX=F(X,N) + QF1=FX + T=SMALL+ZABS(T) + T2=T + DMIN=SMALL + IF(H.LT.HUNDRD*T) H=HUNDRD*T + XLDT=H +C + DO 20 I=1,N + DO 10 J=1,N + V(I,J)=ZERO + 10 CONTINUE + V(I,I)=ONE + 20 CONTINUE +C + QD0=ZERO + D(1)=ZERO +C +C Q0(*) AND Q1(*) ARE PREVIOUS X(*) POINTS, +C INITIALIZED IN PRAXIS, USED IN FLIN, +C AND CHANGED IN QUAD. +C + DO 30 I=1,N + Q1(I)=X(I) +C +C Q0(*) WAS NOT INITIALIZED IN BRENT'S ALGOL PROCEDURE. +C + Q0(I)=X(I) + 30 CONTINUE +C + IF(JPRINT.GT.0) THEN + WRITE(LP,40)NL,NF,FX + 40 FORMAT(/' NL =',I10,5X,'NF =',I10/5X,'FX =',1PG15.7) +C + IF(N.LE.4 .OR. JPRINT.GT.2) THEN + WRITE(LP,50)(X(I),I=1,N) + 50 FORMAT(/8X,'X'/(1X,1PG15.7,4G15.7)) + ENDIF + ENDIF +C +C MAIN LOOP... +C LABEL L0... +C + 60 SF=D(1) + S=ZERO + D(1)=ZERO +C +C MINIMIZE ALONG THE FIRST DIRECTION. +C + IF(JPRINT.GE.5) WRITE(LP,70)D(1),S,FX + 70 FORMAT(/' CALL NO. 1 TO MINX.'/ + * 5X,'D(1) =',1PG15.7,5X,'S =',G15.7,5X,'FX =',G15.7) +C + FXVALU=FX + CALL MINX(1,2,D(1),S,FXVALU,0,F) +C + IF(S.LE.ZERO) THEN + DO 80 I=1,N + V(I,1)=-V(I,1) + 80 CONTINUE + ENDIF +C + IF(SF.LE.PT9*D(1) .OR. PT9*SF.GE.D(1)) THEN +C + IF(N.GE.2) THEN + DO 90 I=2,N + D(I)=ZERO + 90 CONTINUE + ENDIF +C + ENDIF +C + IF(N.LT.2) GO TO 320 + DO 310 K=2,N +C + DO 100 I=1,N + Y(I)=X(I) + 100 CONTINUE +C + SF=FX + IF(KT.GT.0) ILLC=1 +C +C LABEL L1... +C + 110 KL=K + DF=ZERO +C + IF(ILLC.EQ.1) THEN +C +C TAKE A RANDOM STEP TO GET OUT OF A RESOLUTION VALLEY. +C +C PRAXIS ASSUMES THAT RANDOM (OR DRANDM) RETURNS +C A PSEUDORANDOM NUMBER UNIFORMLY DISTRIBUTED IN (0,1), +C AND THAT ANY INITIALIZATION OF THE RANDOM NUMBER GENERATOR +C HAS ALREADY BEEN DONE. +C + DO 130 I=1,N +C + IF(JRANCH.EQ.1) THEN + CALL RANDOM(RANVAL) + ELSE + RANVAL=DRANDM(DSEED) + ENDIF +C + S=(TENTH*XLDT+T2*TEN**KT)*(RANVAL-RHALF) + Z(I)=S +C + DO 120 J=1,N + X(J)=X(J)+S*V(J,I) + 120 CONTINUE + 130 CONTINUE +C + FX=F(X,N) + NF=NF+1 +C + IF(JPRINT.GE.1) WRITE(LP,140)NF,SF,FX + 140 FORMAT(/' ***** RANDOM STEP IN PRAXIS. NF =',I11/ + * 5X,'SF =',1PG15.7,5X,'FX =',G15.7) + ENDIF +C + IF(K.GT.N) GO TO 170 + DO 160 K2=K,N + SL=FX + S=ZERO +C +C MINIMIZE ALONG NON-CONJUGATE DIRECTIONS. +C + IF(JPRINT.GE.5) WRITE(LP,150)K2,D(K2),S,FX + 150 FORMAT(/' CALL NO. 2 TO MINX.'/ + * 5X,'K2 =',I4,5X,'D(K2) =',1PG15.7,5X, + * 'S =',G15.7/5X,'FX =',G15.7) +C + FXVALU=FX + CALL MINX(K2,2,D(K2),S,FXVALU,0,F) +C + IF(ILLC.EQ.1) THEN + S=D(K2)*(S+Z(K2))**2 + ELSE + S=SL-FX + ENDIF +C + IF(DF.LT.S) THEN + DF=S + KL=K2 + ENDIF + 160 CONTINUE +C + 170 IF(ILLC.EQ.0 .AND. DF.LT.ZABS(HUNDRD*EPSMCH*FX)) THEN +C +C NO SUCCESS WITH ILLC=0, SO TRY ONCE WITH ILLC=1 . +C + ILLC=1 +C +C GO TO L1. +C + GO TO 110 + ENDIF +C + IF(K.EQ.2 .AND. JPRINT.GT.1) THEN + WRITE(LP,180)(D(I),I=1,N) + 180 FORMAT(/' NEW D'/(1X,1PG15.7,4G15.7)) + ENDIF +C + KM1=K-1 + IF(KM1.LT.1) GO TO 210 + DO 200 K2=1,KM1 +C +C MINIMIZE ALONG CONJUGATE DIRECTIONS. +C + IF(JPRINT.GE.5) WRITE(LP,190)K2,D(K2),S,FX + 190 FORMAT(/' CALL NO. 3 TO MINX.'/ + * 5X,'K2 =',I4,5X,'D(K2) =',1PG15.7,5X, + * 'S =',G15.7/5X,'FX =',G15.7) +C + S=ZERO + FXVALU=FX + CALL MINX(K2,2,D(K2),S,FXVALU,0,F) + 200 CONTINUE +C + 210 F1=FX + FX=SF +C + XLDS=ZERO + DO 220 I=1,N + SL=X(I) + X(I)=Y(I) + SL=SL-Y(I) + Y(I)=SL + XLDS=XLDS+SL*SL + 220 CONTINUE +C + XLDS=ZSQRT(XLDS) + IF(XLDS.GT.SMALL) THEN +C +C THROW AWAY THE DIRECTION KL AND MINIMIZE ALONG +C THE NEW CONJUGATE DIRECTION. +C + IK=KL-1 + IF(K.GT.IK) GO TO 250 + DO 240 IM=K,IK + I=IK-IM+K +C + DO 230 J=1,N + V(J,I+1)=V(J,I) + 230 CONTINUE +C + D(I+1)=D(I) + 240 CONTINUE +C + 250 D(K)=ZERO +C + DO 260 I=1,N + V(I,K)=Y(I)/XLDS + 260 CONTINUE +C + IF(JPRINT.GE.5) WRITE(LP,270)K,D(K),XLDS,F1 + 270 FORMAT(/' CALL NO. 4 TO MINX.'/ + * 5X,'K =',I4,5X,'D(K) =',1PG15.7,5X, + * 'XLDS =',G15.7/5X,'F1 =',G15.7) +C + F1VALU=F1 + CALL MINX(K,4,D(K),XLDS,F1VALU,1,F) +C + IF(XLDS.LE.ZERO) THEN + XLDS=-XLDS +C + DO 280 I=1,N + V(I,K)=-V(I,K) + 280 CONTINUE + ENDIF + ENDIF +C + XLDT=DLDFAC*XLDT + IF(XLDT.LT.XLDS) XLDT=XLDS +C + IF(JPRINT.GT.0) THEN + WRITE(LP,40)NL,NF,FX + IF(N.LE.4 .OR. JPRINT.GT.2) THEN + WRITE(LP,50)(X(I),I=1,N) + ENDIF + ENDIF +C + T2=ZERO + DO 290 I=1,N + T2=T2+X(I)**2 + 290 CONTINUE + T2=XM2*ZSQRT(T2)+T +C +C SEE IF THE STEP LENGTH EXCEEDS HALF THE TOLERANCE. +C + IF(XLDT.GT.RHALF*T2) THEN + KT=0 + ELSE + KT=KT+1 + ENDIF +C +C IF(...) GO TO L2 +C + IF(KT.GT.KTM) GO TO 550 +C + IF(NF.GE.NFMAX) THEN + WRITE(LP,300)NFMAX + 300 FORMAT(/' IN PRAXIS, NF REACHED THE LIMIT NFMAX =',I11/ + * 5X,'THIS IS AN ABNORMAL TERMINATION.'/ + * 5X,'THE FUNCTION HAS NOT BEEN MINIMIZED AND', + * ' THE RESULTING X(*) VECTOR SHOULD NOT BE USED.') + GO TO 550 + ENDIF +C + 310 CONTINUE +C +C TRY QUADRATIC EXTRAPOLATION IN CASE WE ARE STUCK IN A CURVED VALLEY. +C + 320 CALL QUAD(F) +C + DN=ZERO + DO 330 I=1,N + D(I)=ONE/ZSQRT(D(I)) + IF(DN.LT.D(I)) DN=D(I) + 330 CONTINUE +C + IF(JPRINT.GT.3) THEN +C + WRITE(LP,340) + 340 FORMAT(/' NEW DIRECTIONS') +C + DO 360 I=1,N + WRITE(LP,350)I,(V(I,J),J=1,N) + 350 FORMAT(1X,I5,4X,1PG15.7,4G15.7/(10X,5G15.7)) + 360 CONTINUE + ENDIF +C + DO 380 J=1,N +C + S=D(J)/DN + DO 370 I=1,N + V(I,J)=S*V(I,J) + 370 CONTINUE + 380 CONTINUE +C + IF(SCBD.GT.ONE) THEN +C +C SCALE THE AXES TO TRY TO REDUCE THE CONDITION NUMBER. +C + S=VLARGE + DO 400 I=1,N +C + SL=ZERO + DO 390 J=1,N + SL=SL+V(I,J)**2 + 390 CONTINUE +C + Z(I)=ZSQRT(SL) + IF(Z(I).LT.XM4) Z(I)=XM4 + IF(S.GT.Z(I)) S=Z(I) + 400 CONTINUE +C + DO 410 I=1,N + SL=S/Z(I) + Z(I)=ONE/SL +C + IF(Z(I).GT.SCBD) THEN + SL=ONE/SCBD + Z(I)=SCBD + ENDIF +C +C IT APPEARS THAT THERE ARE TWO MISSING END; STATEMENTS +C AT THIS POINT IN BRENT'S LISTING. +C + 410 CONTINUE + ENDIF +C +C TRANSPOSE V FOR MINFIT. +C + IF(N.LT.2) GO TO 440 + DO 430 I=2,N +C + IMU=I-1 + DO 420 J=1,IMU + S=V(I,J) + V(I,J)=V(J,I) + V(J,I)=S + 420 CONTINUE + 430 CONTINUE +C +C FIND THE SINGULAR VALUE DECOMPOSITION OF V. +C THIS GIVES THE EIGENVALUES AND PRINCIPAL AXES +C OF THE APPROXIMATING QUADRATIC FORM +C WITHOUT SQUARING THE CONDITION NUMBER. +C + 440 CALL MINFIT(N,EPSMCH,VSMALL,V,D,E,NMAX,LP) +C + IF(SCBD.GT.ONE) THEN +C +C UNSCALING... +C + DO 460 I=1,N +C + S=Z(I) + DO 450 J=1,N + V(I,J)=S*V(I,J) + 450 CONTINUE + 460 CONTINUE +C + DO 490 I=1,N +C + S=ZERO + DO 470 J=1,N + S=S+V(J,I)**2 + 470 CONTINUE + S=ZSQRT(S) +C + D(I)=S*D(I) +C + S=ONE/S + DO 480 J=1,N + V(J,I)=S*V(J,I) + 480 CONTINUE + 490 CONTINUE + ENDIF +C + DO 500 I=1,N +C + IF(DN*D(I).GT.XLARGE) THEN + D(I)=VSMALL + ELSE IF(DN*D(I).LT.SMALL) THEN + D(I)=VLARGE + ELSE + D(I)=ONE/(DN*D(I))**2 + ENDIF + 500 CONTINUE +C +C SORT THE NEW EIGENVALUES AND EIGENVECTORS. +C + CALL SORT +C + DMIN=D(N) + IF(DMIN.LT.SMALL) DMIN=SMALL +C + IF(XM2*D(1).GT.DMIN) THEN + ILLC=1 + ELSE + ILLC=0 + ENDIF +C + IF(JPRINT.GT.1 .AND. SCBD.GT.ONE) THEN + WRITE(LP,510)(Z(I),I=1,N) + 510 FORMAT(/' SCALE FACTORS'/(1X,1PG15.7,4G15.7)) + ENDIF +C + IF(JPRINT.GT.1) THEN + WRITE(LP,520)(D(I),I=1,N) + 520 FORMAT(/' EIGENVALUES OF A'/(1X,1PG15.7,4G15.7)) + ENDIF +C + IF(JPRINT.GT.3) THEN +C + WRITE(LP,530) + 530 FORMAT(/' EIGENVECTORS OF A') +C + DO 540 I=1,N + WRITE(LP,350)I,(V(I,J),J=1,N) + 540 CONTINUE + ENDIF +C +C GO BACK TO THE MAIN LOOP. +C GO TO L0 +C +C HANDLE THE CASE N .EQ. 1 IN AN AD HOC WAY. +C (BRENT DID NOT PROVIDE FOR THIS CASE.) +C + IF(N.GE.2) GO TO 60 +C +C LABEL L2... +C + 550 IF(JPRINT.GT.0) THEN + WRITE(LP,560)(X(I),I=1,N) + 560 FORMAT(//7X,'X'/(1X,1PG15.7,4G15.7)) + ENDIF +C + FX=F(X,N) +C + IF(JPRINT.GE.0) WRITE(LP,570)FX,NL,NF + 570 FORMAT(/' EXIT PRAXIS. FX =',1PG25.17,5X,'NL =',I8, + * 5X,'NF =',I9) +C + RETURN +C +C END PRAXIS +C + END + SUBROUTINE QUAD(F) +C +C THIS SUBROUTINE LOOKS FOR THE MINIMUM ALONG +C A CURVE DEFINED BY Q0, Q1, AND X. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGE 161 +C +C SUBROUTINE QUAD IS CALLED BY SUBROUTINE PRAXIS. +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER I +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION F, DSQRT,ZSQRT,ARG, + * ONE,QA,QB,QC,S,TWO,XL,ZERO,QF1VAL +C + EXTERNAL F +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + ZSQRT(ARG)=DSQRT(ARG) +C + ZERO=0.0D0 + ONE=1.0D0 +C + S=FX + FX=QF1 + QF1=S + QD1=ZERO +C + DO 10 I=1,N + S=X(I) + XL=Q1(I) + X(I)=XL + Q1(I)=S + QD1=QD1+(S-XL)**2 + 10 CONTINUE +C + QD1=ZSQRT(QD1) + XL=QD1 + S=ZERO +C + IF(QD0.GT.ZERO .AND. QD1.GT.ZERO .AND. NL.GE.3*N*N) THEN +C + IF(JPRINT.GE.1) WRITE(LP,20)NF,QD0,QD1,FX,QF1 + 20 FORMAT(/' ***** CALL MINX FROM QUAD. NF =',I11/ + * 5X,'QD0 =',1PG15.7,5X,'QD1 =',G15.7/ + * 5X,'FX =',G15.7,5X,'QF1 =',G15.7) +C + QF1VAL=QF1 + CALL MINX(0,2,S,XL,QF1VAL,1,F) + QA=XL*(XL-QD1)/(QD0*(QD0+QD1)) + QB=(XL+QD0)*(QD1-XL)/(QD0*QD1) + QC=XL*(XL+QD0)/(QD1*(QD0+QD1)) + ELSE + FX=QF1 + QA=ZERO + QB=ZERO + QC=ONE + ENDIF +C + QD0=QD1 +C + DO 30 I=1,N + S=Q0(I) + Q0(I)=X(I) + X(I)=QA*S+QB*X(I)+QC*Q1(I) + 30 CONTINUE +C + RETURN +C +C END QUAD +C + END + SUBROUTINE MINX(J,NITS,D2,X1,F1,IFK,F) +C +C SUBROUTINE MINX MINIMIZES F FROM X IN THE DIRECTION V(*,J) +C UNLESS J IS LESS THAN 1, WHEN A QUADRATIC SEARCH IS DONE IN +C THE PLANE DEFINED BY Q0, Q1, AND X. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 159-160 +C +C SUBROUTINE MINX IS CALLED BY SUBROUTINES PRAXIS AND QUAD. +C +C D2 AND X1 RETURN RESULTS. +C J, NITS, F1 AND IFK ARE VALUE PARAMETERS THAT RETURN NOTHING. +C DO NOT SEND A COMMON VARIABLE TO MINX FOR PARAMETER F1. +C +C +C D2 IS AN APPROXIMATION TO HALF OF +C THE SECOND DERIVATIVE OF F (OR ZERO). +C +C X1 IS AN ESTIMATE OF DISTANCE TO MINIMUM, +C RETURNED AS THE DISTANCE FOUND. +C +C IF IFK = 1 THEN F1 IS FLIN(X1), OTHERWISE X1 AND F1 ARE +C IGNORED ON ENTRY UNLESS FINAL FX IS GREATER THAN F1. +C +C NITS CONTROLS THE NUMBER OF TIMES AN ATTEMPT IS MADE TO +C HALVE THE INTERVAL. +C + EXTERNAL F +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER IFK,J,NITS, I,IDZ,K +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION D2,X1, + * DABS,DSQRT,ZABS,ZSQRT,ARG, + * HUNDTH,RHALF,TWO,ZERO, + * DENOM,D1,FM,F0,F1,F2,S,SF1,SX1,T2,XM,X2 +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + ZSQRT(ARG)=DSQRT(ARG) + ZABS(ARG)=DABS(ARG) +C + HUNDTH=0.01D0 + ZERO=0.0D0 + TWO=2.0D0 + RHALF=0.5D0 +C + SF1=F1 + SX1=X1 + K=0 + XM=ZERO + FM=FX + F0=FX +C + IF(D2.LT.EPSMCH) THEN + IDZ=1 + ELSE + IDZ=0 + ENDIF +C +C FIND THE STEP SIZE. +C + S=ZERO + DO 10 I=1,N + S=S+X(I)**2 + 10 CONTINUE + S=ZSQRT(S) +C + IF(IDZ.EQ.1) THEN + DENOM=DMIN + ELSE + DENOM=D2 + ENDIF +C + T2=XM4*ZSQRT(ZABS(FX)/DENOM+S*XLDT)+XM2*XLDT + S=XM4*S+T + IF(IDZ.EQ.1 .AND. T2.GT.S) T2=S + IF(T2.LT.SMALL) T2=SMALL + IF(T2.GT.HUNDTH*H) T2=HUNDTH*H +C + IF(IFK.EQ.1 .AND. F1.LE.FM) THEN + XM=X1 + FM=F1 + ENDIF +C + IF(IFK.EQ.0 .OR. ZABS(X1).LT.T2) THEN +C + IF(X1.GE.ZERO) THEN + X1=T2 + ELSE + X1=-T2 + ENDIF +C + CALL FLIN(X1,J,F,F1) + ENDIF +C + IF(F1.LT.FM) THEN + XM=X1 + FM=F1 + ENDIF +C +C LABEL L0... +C + 20 IF(IDZ.EQ.1) THEN +C +C EVALUATE FLIN AT ANOTHER POINT, +C AND ESTIMATE THE SECOND DERIVATIVE. +C + IF(F0.LT.F1) THEN + X2=-X1 + ELSE + X2=TWO*X1 + ENDIF +C + CALL FLIN(X2,J,F,F2) +C + IF(F2.LE.FM) THEN + XM=X2 + FM=F2 + ENDIF +C + D2=(X2*(F1-F0)-X1*(F2-F0))/(X1*X2*(X1-X2)) +C + IF(JPRINT.GE.5) WRITE(LP,30)X1,X2,F0,F1,F2,D2 + 30 FORMAT(/' COMPUTE D2 IN SUBROUTINE MINX.'/ + * 5X,'X1 =',1PG15.7,5X,'X2 =',G15.7/ + * 5X,'F0 =',G15.7,5X,'F1 =',G15.7,5X,'F2 =',G15.7/ + * 5X,'D2 =',G15.7) + ENDIF +C +C ESTIMATE THE FIRST DERIVATIVE AT 0. +C + D1=(F1-F0)/X1-X1*D2 + IDZ=1 +C +C PREDICT THE MINIMUM. +C + IF(D2.LE.SMALL) THEN +C + IF(D1.LT.ZERO) THEN + X2=H + ELSE + X2=-H + ENDIF +C + ELSE + X2=-RHALF*D1/D2 + ENDIF +C + IF(ZABS(X2).GT.H) THEN +C + IF(X2.GT.ZERO) THEN + X2=H + ELSE + X2=-H + ENDIF + ENDIF +C +C EVALUATE F AT THE PREDICTED MINIMUM. +C LABEL L1... +C + 40 CALL FLIN(X2,J,F,F2) +C + IF(K.LT.NITS .AND. F2.GT.F0) THEN +C +C NO SUCCESS, SO TRY AGAIN. +C + K=K+1 +C +C IF(...) GO TO L0 +C + IF(F0.LT.F1 .AND. X1*X2.GT.ZERO) GO TO 20 + X2=X2/TWO +C +C GO TO L1 +C + GO TO 40 +C + ENDIF +C +C INCREMENT THE ONE-DIMENSIONAL SEARCH COUNTER. +C + NL=NL+1 +C + IF(F2.GT.FM) THEN + X2=XM + ELSE + FM=F2 + ENDIF +C +C GET A NEW ESTIMATE OF THE SECOND DERIVATIVE. +C + IF(ZABS(X2*(X2-X1)).GT.SMALL) THEN + D2=(X2*(F1-F0)-X1*(FM-F0))/(X1*X2*(X1-X2)) +C + IF(JPRINT.GE.5) WRITE(LP,50)X1,X2,F0,FM,F1,D2 + 50 FORMAT(/' RECOMPUTE D2 IN SUBROUTINE MINX.'/ + * 5X,'X1 =',1PG15.7,5X,'X2 =',G15.7/ + * 5X,'F0 =',G15.7,5X,'FM =',G15.7,5X,'F1 =',G15.7/ + * 5X,'D2 =',G15.7) +C + ELSE IF(K.GT.0) THEN + D2=ZERO +C + IF(JPRINT.GE.5) WRITE(LP,60) + 60 FORMAT(/' SET D2=0 IN SUBROUTINE MINX.') + ELSE + D2=D2 + ENDIF +C + IF(D2.LE.SMALL) THEN + D2=SMALL +C + IF(JPRINT.GE.5) WRITE(LP,70)D2 + 70 FORMAT(/' SET D2=SMALL=',1PG15.7,' IN SUBROUTINE MINX.') + ENDIF +C + IF(JPRINT.GE.5) WRITE(LP,80)X1,X2,FX,FM,SF1 + 80 FORMAT(/' SUBROUTINE MINX. X1 =',1PG15.7,5X,'X2 =',G15.7/ + * 5X,'FX =',G15.7,5X,'FM =',G15.7,5X,'SF1 =',G15.7) +C + X1=X2 + FX=FM + IF(SF1.LT.FX) THEN + FX=SF1 + X1=SX1 + ENDIF +C +C UPDATE X FOR A LINEAR SEARCH BUT NOT FOR A PARABOLIC SEARCH. +C + IF(J.GT.0) THEN +C + DO 90 I=1,N + X(I)=X(I)+X1*V(I,J) + 90 CONTINUE + ENDIF +C + IF(JPRINT.GE.5) WRITE(LP,100)D2,X1,F1,FX + 100 FORMAT(/' LEAVE SUBROUTINE MINX.'/ + * 5X,'D2 =',1PG15.7,5X,'X1 =',G15.7,5X,'F1 =',G15.7/ + * 5X,'FX =',G15.7) +C + RETURN +C +C END MINX +C + END + SUBROUTINE FLIN(XL,J,F,FLN) +C +C FLIN IS A FUNCTION OF ONE VARIABLE XL WHICH IS MINIMIZED BY +C SUBROUTINE MINX. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 159-160 +C +C SUBROUTINE FLIN IS CALLED BY SUBROUTINE MINX. +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER J, I +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION XL,F,FLN, TT, QA,QB,QC +C + DIMENSION TT(128) +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + IF(J.GT.0) THEN +C +C LINEAR SEARCH... +C + DO 10 I=1,N + TT(I)=X(I)+XL*V(I,J) + 10 CONTINUE +C + ELSE +C +C SEARCH ALONG A PARABOLIC SPACE CURVE. +C + QA=XL*(XL-QD1)/(QD0*(QD0+QD1)) + QB=(XL+QD0)*(QD1-XL)/(QD0*QD1) + QC=XL*(XL+QD0)/(QD1*(QD0+QD1)) +C + DO 20 I=1,N + TT(I)=QA*Q0(I)+QB*X(I)+QC*Q1(I) + 20 CONTINUE + ENDIF +C +C INCREMENT FUNCTION EVALUATION COUNTER. +C + NF=NF+1 + FLN=F(TT,N) +C + RETURN +C +C END FLIN +C + END + SUBROUTINE MINFIT(N,EPS,TOL,AB,Q,E,NMAX,LP) +C +C AN IMPROVED VERSION OF MINFIT, RESTRICTED TO M=N, P=0. +C SEE GOLUB AND REINSCH (1970). +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 156-158 +C +C G. H. GOLUB AND C. REINSCH, +C "SINGULAR VALUE DECOMPOSITION AND LEAST SQUARES SOLUTIONS', +C NUMERISCHE MATHEMATIK 14 (1970) PAGES 403-420 +C +C THE SINGULAR VALUES OF THE ARRAY AB ARE RETURNED IN Q, +C AND AB IS OVERWRITTEN WITH THE ORTHOGONAL MATRIX V SUCH THAT +C U.DIAG(Q)=AB.V, WHERE U IS ANOTHER ORTHOGONAL MATRIX. +C +C SUBROUTINE MINFIT IS CALLED BY SUBROUTINE PRAXIS. +C + INTEGER N,NMAX,LP, + * I,II,J,JTHIRT,K,KK,KT,L,LL2,LPI,L2 +C + DOUBLE PRECISION EPS,TOL,AB,Q,E, + * DABS,DSQRT,ZABS,ZSQRT,ARG, + * C,DENOM,F,G,H,ONE,X,Y,Z,ZERO,S,TWO +C + DIMENSION AB(NMAX,N),Q(N),E(N) +C + ZABS(ARG)=DABS(ARG) + ZSQRT(ARG)=DSQRT(ARG) +C + JTHIRT=30 +C + ZERO=0.0D0 + ONE=1.0D0 + TWO=2.0D0 +C +C HOUSEHOLDER'S REDUCTION TO BIDIAGONAL FORM... +C + X=ZERO + G=ZERO +C + DO 140 I=1,N + E(I)=G + S=ZERO + L=I+1 +C + DO 10 J=I,N + S=S+AB(J,I)**2 + 10 CONTINUE +C + IF(S.LT.TOL) THEN + G=ZERO + ELSE + F=AB(I,I) +C + IF(F.LT.ZERO) THEN + G=ZSQRT(S) + ELSE + G=-ZSQRT(S) + ENDIF +C + H=F*G-S + AB(I,I)=F-G +C + IF(L.GT.N) GO TO 60 + DO 50 J=L,N +C + F=ZERO + IF(I.GT.N) GO TO 30 + DO 20 K=I,N + F=F+AB(K,I)*AB(K,J) + 20 CONTINUE + 30 F=F/H +C + IF(I.GT.N) GO TO 50 + DO 40 K=I,N + AB(K,J)=AB(K,J)+F*AB(K,I) + 40 CONTINUE + 50 CONTINUE + ENDIF +C + 60 Q(I)=G + S=ZERO +C + IF(I.LE.N) THEN +C + IF(L.GT.N) GO TO 80 + DO 70 J=L,N + S=S+AB(I,J)**2 + 70 CONTINUE + ENDIF +C + 80 IF(S.LT.TOL) THEN + G=ZERO + ELSE + F=AB(I,I+1) +C + IF(F.LT.ZERO) THEN + G=ZSQRT(S) + ELSE + G=-ZSQRT(S) + ENDIF +C + H=F*G-S + AB(I,I+1)=F-G + IF(L.GT.N) GO TO 130 + DO 90 J=L,N + E(J)=AB(I,J)/H + 90 CONTINUE +C + DO 120 J=L,N +C + S=ZERO + DO 100 K=L,N + S=S+AB(J,K)*AB(I,K) + 100 CONTINUE +C + DO 110 K=L,N + AB(J,K)=AB(J,K)+S*E(K) + 110 CONTINUE + 120 CONTINUE + ENDIF +C + 130 Y=ZABS(Q(I))+ZABS(E(I)) +C + IF(Y.GT.X) X=Y + 140 CONTINUE +C +C ACCUMULATION OF RIGHT-HAND TRANSFORMATIONS... +C + DO 210 II=1,N + I=N-II+1 +C + IF(G.NE.ZERO) THEN + H=AB(I,I+1)*G +C + IF(L.GT.N) GO TO 200 + DO 150 J=L,N + AB(J,I)=AB(I,J)/H + 150 CONTINUE +C + DO 180 J=L,N +C + S=ZERO + DO 160 K=L,N + S=S+AB(I,K)*AB(K,J) + 160 CONTINUE +C + DO 170 K=L,N + AB(K,J)=AB(K,J)+S*AB(K,I) + 170 CONTINUE + 180 CONTINUE + ENDIF +C + IF(L.GT.N) GO TO 200 + DO 190 J=L,N + AB(J,I)=ZERO + AB(I,J)=ZERO + 190 CONTINUE +C + 200 AB(I,I)=ONE + G=E(I) + L=I + 210 CONTINUE +C +C DIAGONALIZATION OF THE BIDIAGONAL FORM... +C + EPS=EPS*X + DO 330 KK=1,N + K=N-KK+1 + KT=0 +C +C LABEL TESTFSPLITTING... +C + 220 KT=KT+1 +C + IF(KT.GT.JTHIRT) THEN + E(K)=ZERO + WRITE(LP,230) + 230 FORMAT(' QR FAILED.') + ENDIF +C + DO 240 LL2=1,K + L2=K-LL2+1 + L=L2 +C +C IF(...) GO TO TESTFCONVERGENCE +C + IF(ZABS(E(L)).LE.EPS) GO TO 270 +C +C IF(...) GO TO CANCELLATION +C + IF(ZABS(Q(L-1)).LE.EPS) GO TO 250 + 240 CONTINUE +C +C CANCELLATION OF E(L) IF L IS GREATER THAN 1... +C LABEL CANCELLATION... +C + 250 C=ZERO + S=ONE + IF(L.GT.K) GO TO 270 + DO 260 I=L,K + F=S*E(I) + E(I)=C*E(I) +C +C IF(...) GO TO TESTFCONVERGENCE +C + IF(ZABS(F).LE.EPS) GO TO 270 + G=Q(I) +C + IF(ZABS(F).LT.ZABS(G)) THEN + H=ZABS(G)*ZSQRT(ONE+(F/G)**2) + ELSE IF(F.NE.ZERO) THEN + H=ZABS(F)*ZSQRT(ONE+(G/F)**2) + ELSE + H=ZERO + ENDIF +C + Q(I)=H +C + IF(H.EQ.ZERO) THEN + H=ONE + G=ONE + ENDIF +C +C THE ABOVE REPLACES Q(I) AND H BY SQUARE ROOT OF (G*G+F*F) +C WHICH MAY GIVE INCORRECT RESULTS IF THE SQUARES UNDERFLOW OR IF +C F = G = 0 . +C + C=G/H + S=-F/H + 260 CONTINUE +C +C LABEL TESTFCONVERGENCE... +C + 270 Z=Q(K) +C +C IF(...) GO TO CONVERGENCE +C + IF(L.EQ.K) GO TO 310 +C +C SHIFT FROM BOTTOM 2*2 MINOR. +C + X=Q(L) + Y=Q(K-1) + G=E(K-1) + H=E(K) + F=((Y-Z)*(Y+Z)+(G-H)*(G+H))/(TWO*H*Y) + G=ZSQRT(F*F+ONE) +C + IF(F.LT.ZERO) THEN + DENOM=F-G + ELSE + DENOM=F+G + ENDIF +C + F=((X-Z)*(X+Z)+H*(Y/DENOM-H))/X +C +C NEXT QR TRANSFORMATION... +C + S=ONE + C=ONE + LPI=L+1 + IF(LPI.GT.K) GO TO 300 + DO 290 I=LPI,K + G=E(I) + Y=Q(I) + H=S*G + G=G*C +C + IF(ZABS(F).LT.ZABS(H)) THEN + Z=ZABS(H)*ZSQRT(ONE+(F/H)**2) + ELSE IF(F.NE.ZERO) THEN + Z=ZABS(F)*ZSQRT(ONE+(H/F)**2) + ELSE + Z=ZERO + ENDIF +C + E(I-1)=Z +C + IF(Z.EQ.ZERO) THEN + F=ONE + Z=ONE + ENDIF +C + C=F/Z + S=H/Z + F=X*C+G*S + G=-X*S+G*C + H=Y*S + Y=Y*C +C + DO 280 J=1,N + X=AB(J,I-1) + Z=AB(J,I) + AB(J,I-1)=X*C+Z*S + AB(J,I)=-X*S+Z*C + 280 CONTINUE +C + IF(ZABS(F).LT.ZABS(H)) THEN + Z=ZABS(H)*ZSQRT(ONE+(F/H)**2) + ELSE IF(F.NE.ZERO) THEN + Z=ZABS(F)*ZSQRT(ONE+(H/F)**2) + ELSE + Z=ZERO + ENDIF +C + Q(I-1)=Z +C + IF(Z.EQ.ZERO) THEN + F=ONE + Z=ONE + ENDIF +C + C=F/Z + S=H/Z + F=C*G+S*Y + X=-S*G+C*Y + 290 CONTINUE +C + 300 E(L)=ZERO + E(K)=F + Q(K)=X +C +C GO TO TESTFSPLITTING +C + GO TO 220 +C +C LABEL CONVERGENCE... +C + 310 IF(Z.LT.ZERO) THEN +C +C Q(K) IS MADE NON-NEGATIVE. +C + Q(K)=-Z + DO 320 J=1,N + AB(J,K)=-AB(J,K) + 320 CONTINUE + ENDIF + 330 CONTINUE +C + RETURN +C +C END MINFIT +C + END + SUBROUTINE SORT +C +C THIS SUBROUTINE SORTS THE ELEMENTS OF D +C AND THE CORRESPONDING COLUMNS OF V INTO DESCENDING ORDER. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 158-159 +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER I,IPI,J,K,NMI +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION S +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + NMI=N-1 + IF(NMI.LT.1) GO TO 50 + DO 40 I=1,NMI + K=I + S=D(I) + IPI=I+1 + IF(IPI.GT.N) GO TO 20 +C + DO 10 J=IPI,N +C + IF(D(J).GT.S) THEN + K=J + S=D(J) + ENDIF + 10 CONTINUE +C + 20 IF(K.GT.I) THEN + D(K)=D(I) + D(I)=S +C + DO 30 J=1,N + S=V(J,I) + V(J,I)=V(J,K) + V(J,K)=S + 30 CONTINUE + ENDIF + 40 CONTINUE +C + 50 RETURN +C +C END SORT +C + END + SUBROUTINE RANINI(RVALUE) +C +C SUBROUTINE RANINI PERFORMS INITIALIZATION FOR SUBROUTINE RANDOM. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 163-164 +C + INTEGER JRAN2,I +C + DOUBLE PRECISION RVALUE,R,RAN3,DMOD,DABS,RAN1 +C + COMMON /COMRAN/ RAN3(127),RAN1,JRAN2 +C + R=DMOD(DABS(RVALUE),8190.0D0)+1 + JRAN2=127 +C + 10 IF(JRAN2.GT.0) THEN + JRAN2=JRAN2-1 + RAN1=-2.0D0**55 +C + DO 20 I=1,7 + R=DMOD(1756.0D0*R,8191.0D0) + RAN1=(RAN1+(R-DMOD(R,32.0D0))/32.0D0)/256.0D0 + 20 CONTINUE +C + RAN3(JRAN2+1)=RAN1 + GO TO 10 + ENDIF +C + RETURN +C +C END RANINI +C + END + SUBROUTINE RANDOM(RANVAL) +C +C SUBROUTINE RANDOM RETURNS A DOUBLE PRECISION PSEUDORANDOM NUMBER +C UNIFORMLY DISTRIBUTED IN (0,1) (INCLUDING 0 BUT NOT 1). +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 163-164 +C +C BEFORE THE FIRST CALL TO RANDOM, THE USER MUST +C CALL RANINI(R) ONCE (ONLY) WITH R A DOUBLE PRECISION NUMBER +C EQUAL TO ANY INTEGER VALUE. +C BRENT (PAGE 166) USED THE EQUIVALENT OF +C CALL RANINI(4.0D0) . +C +C THE ALGORITHM USED IN SUBROUTINE RANDOM RETURNS X(N)/2**56, +C WHERE X(N) = X(N-1) + X(N-127) (MOD 2**56) . +C SINCE (1 + X + X**127) IS PRIMITIVE (MOD 2), +C THE PERIOD IS AT LEAST (2**127 - 1), WHICH EXCEEDS 10**38. +C +C SEE "SEMINUMERICAL ALGORITHMS", VOLUME 2 OF +C "THE ART OF COMPUTER PROGRAMMING" BY DONALD E. KNUTH, +C ADDISON-WESLEY 1969, PAGES 26, 34, AND 464. +C +C X(N) IS STORED IN DOUBLE PRECISION AS RAN3 = X(N)/2**56 - 1/2, +C AND ALL DOUBLE PRECISION ARITHMETIC IS EXACT. +C + INTEGER JRAN2 +C + DOUBLE PRECISION RANVAL,RAN3,RAN1 +C + COMMON /COMRAN/ RAN3(127),RAN1,JRAN2 +C + IF(JRAN2.EQ.0) THEN + JRAN2=126 + ELSE + JRAN2=JRAN2-1 + ENDIF +C + RAN1=RAN1+RAN3(JRAN2+1) + IF(RAN1.LT.0.0D0) THEN + RAN1=RAN1+0.5D0 + ELSE + RAN1=RAN1-0.5D0 + ENDIF +C + RAN3(JRAN2+1)=RAN1 + RANVAL=RAN1+0.5D0 +C + RETURN +C +C END RANDOM +C + END + DOUBLE PRECISION FUNCTION DRANDM(DL) +C +C SIMPLE PORTABLE PSEUDORANDOM NUMBER GENERATOR. +C +C DRANDM RETURNS FUNCTION VALUES THAT ARE PSEUDORANDOM +C NUMBERS UNIFORMLY DISTRIBUTED ON THE INTERVAL (0,1). +C +C 'NUMERICAL MATHEMATICS AND COMPUTING' BY WARD CHENEY AND +C DAVID KINCAID, BROOKS/COLE PUBLISHING COMPANY +C (FIRST EDITION, 1980), PAGE 203 +C +C AT THE BEGINNING OF EXECUTION, OR WHENEVER A NEW SEQUENCE IS +C TO BE INITIATED, SET DL EQUAL TO AN INTEGER VALUE BETWEEN +C 1.0D0 AND 2147483646.0D0, INCLUSIVE. DO THIS ONLY ONCE. +C THEREAFTER, DO NOT SET OR ALTER DL IN ANY WAY. +C FUNCTION DRANDM WILL MODIFY DL FOR ITS OWN PURPOSES. +C +C DRANDM USES A MULTIPLICATIVE CONGRUENTIAL METHOD. +C THE NUMBERS GENERATED BY DRANDM SUFFER FROM THE PARALLEL +C PLANES DEFECT DISCOVERED BY G. MARSAGLIA, AND SHOULD NOT BE +C USED WHEN HIGH-QUALITY RANDOMNESS IS REQUIRED. IN THAT +C CASE, USE A "SHUFFLING" METHOD. +C + DOUBLE PRECISION DL,DMOD +C + 10 DL=DMOD(16807.0D0*DL,2147483647.0D0) + DRANDM=DL/2147483647.0D0 + IF(DRANDM.LE.0.0D0 .OR. DRANDM.GE.1.0D0) GO TO 10 + RETURN + END diff --git a/gnuradio-core/src/gen_interpolator_taps/praxis.txt b/gnuradio-core/src/gen_interpolator_taps/praxis.txt new file mode 100644 index 000000000..5c4b81556 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/praxis.txt @@ -0,0 +1,176 @@ +Brent's PRAXIS minimizer is available in FORTRAN 77. July 1995 + +"Algorithms for Minimization Without Derivatives" +by Richard P. Brent, Prentice-Hall, 1973 +ISBN: 0-13-022335-2 + +This book by Brent was a groundbreaking effort. +(I believe that it was his Ph.D. thesis at Stanford.) +His algorithms for finding roots and minima in +one dimension have good performance for typical problems +and guaranteed performance in the worst case. +(A later rootfinder by J. Bus and Dekker gave +a much lower bound for the worst case, +but no better performance in typical problems.) +These algorithms were implemented in both ALGOL W +and FORTRAN by Brent, and have been used fairly widely. + +Brent also gave a multi-dimensional minimization algorithm, +PRAXIS, but only shows an implementation in ALGOL W. +This routine has not been widely used, at least in the U.S. +The PRAXIS package has been translated into FORTRAN +by Rosalee Taylor, Sue Pinski, and me, and +I am making it available via anonymous ftp for use as +freeware (please do not remove our names). + + ftp a.cs.okstate.edu + anonymous + [enter your userid as password] + cd /pub/jpc + get praxis.f + quit + + +Brent's method and its performance + +Newton's method for minimization can find the minimum of a +quadratic function in one iteration, but is sometimes not +convenient to use. In the 1960s, several researchers found +iterative methods that solve quadratic problems exactly in a +finite number of steps. C. S. Smith (1962) and +M. J. D. Powell (1964) devised methods +that had this property and did not require derivatives. +G. W. Stewart modified the Davidon-Fletcher-Powell quasi-Newton +method to use finite difference approximations to approximate +the gradient. Powell's method, or later versions by Zangwill, +were the most successful of the early direct search methods +having the property of finite convergence on quadratic functions. + +Powell's method was programmed at Harwell as subroutine VA04A, +and is available as file va04a.f in the same directory as praxis.f. +VA04A is not extremely robust, and can give underflow, overflow, +or division by zero. va04a.f has several documented patches in it +where I tried to get around various abnormal terminations. +I do not recommend VA04A very strongly. + +Brent's PRAXIS added orthogonalization and several other features +to Powell's method. Brent also dealt carefully with roundoff. + +William H. Press et al. in their book "Numerical Recipes" +comment that +"Brent has a number of other cute tricks up his sleeve, +and his modification of Powell's method is probably +the best presently known." + +Roger Fletcher was less enthusiastic in his review of Brent's book +in The Computer Journal 16 (1973) 314: +"... I am not convinced that the modifications to Powell's +method are the best. Use of eigenvector directions +is not independent of scale changes to the variables, +and the use of searches in random directions is hardly +appealing. Nonetheless all the algorithms are demonstrated +to be competitive by numerical examples." + +The methods of Powell, Brent, et al. require that the function +for which a local minimum is sought must be smooth; +that is, the function and all of its first partial derivatives +must be continuous. + +Brent compared his method to the methods of Powell, of Stewart, +and of Davies, Swann, and Campey. Indirectly, he compared it +also to the Davidon-Fletcher-Powell quasi-Newton method. +He found that his method was about as efficient as the best +of these in most cases, and that it was more robust than others +in some cases. (Pages 139-155 in Brent's book give fair +comparisons to other methods. The results in Table 7.1 on +page 138 are correct, but do not include progress all the way +to convergence, and are therefore not too useful.) + +On least squares problems, all of these general minimization +methods are likely to be inefficient compared to least squares +methods such as the Gauss-Newton or Marquardt methods. + +In addition to the scale dependence that Fletcher deplored, +PRAXIS also had the disadvantage that it required N, the number +of parameters, to be greater than or equal to two. +The failure to handle N=1 is an unnecessary and pointless limitation. + + +The FORTRAN version + +We have followed Brent's PRAXIS rather closely. +I have added a patch to try to handle the case N=1, +and an option to use a simpler pseudorandom number generator, +DRANDM. The handling of N=1 is not guaranteed. + +The user writes a main program and a function subprogram +to compute the function to be minimized. +All communication between the user's main program and PRAXIS +is done via COMMON, except for an EXTERNAL parameter giving +the name of the function subprogram. +The disadvantages of using COMMON are at least two-fold: + + 1) Arrays cannot have adjustable dimensions. + + 2) Because some actual parameters are COMMON variables, + the FORTRAN version of PRAXIS probably will not pass + the Bell Labs PFORT package as being 100% standard FORTRAN. + Nevertheless, this usage will not cause any conflict in + any commercial FORTRAN compiler ever written. + (If it does, I will apologize and rewrite PRAXIS.) + +The advantage of using COMMON is that it is not necessary to pass +about fifteen more parameters every time the user calls PRAXIS. +At present all arrays are dimensioned (20) or (20,20), +and this can easily be increased using two simple global editing +commands. (In this case, increase the value of NMAX.) + +There are no DATA statements in PRAXIS, and it was not necessary +to use any SAVE statements. + +We have used DOUBLE PRECISION for all floating point computations, +as Brent did. We recommend using DOUBLE PRECISION on all computers +except possibly Cray computers, in which REAL is reasonably precise. +The value of "machine epsilon" is computed in subroutine PRASET +using bisection, and is called EPSMCH. +Brent computes EPSMCH**4 and 1/EPSMCH**4 in PRAXIS, +and uses these quantities later. +Because EPSMCH in DOUBLE PRECISION is less than 1E-16, +these fourth powers of EPSMCH and 1/EPSMCH will underflow +and overflow on such machines as VAXs and PCs, +which have a range of only about 1E38, grossly insufficient +for scientific computation. For such machines, Brent recommends +increasing the value of EPSMCH. +EPSMCH=1E-9 or possibly even 1E-8 might be necessary. +A better solution would be to eliminate the explicit use of +these fourth powers, accomplishing the same result implicitly. + +A "bug bounty" of $10 U.S. will be paid by me for the first +notification of any error in PRAXIS. +The same bounty also applies to any substantive poor design +choice (having no redeeming advantages whatever) in the FORTRAN +package. (The patch for N=1 is not included, although any +suggested improvements in that will be considered carefully.) + +praxis.f includes test software to run any of the test problems +that Brent ran, and is set to run at least one case of each problem. +I have run these on an IBM 3090, essentially the same +architecture that Brent used, and obtained essentially the same +results that Brent shows on pages 140-155. The Hilbert problem with +N=12, for which Brent shows no termination results and for which +the results in Table 7.1 are correct but not relevant, +runs a long time; I cut it off at 3000 function evaluations. +I don't particularly like Brent's convergence criterion, +which allows this sort of extremely slow creeping progress, +but have not modified it. + +Please notify me of any problems with this software, +or of any suggested modifications. + +John Chandler +Computer Science Department +Oklahoma State University +Stillwater, Oklahoma 74078, U.S.A. +(405) 744-5676 +jpc@a.cs.okstate.edu + diff --git a/gnuradio-core/src/gen_interpolator_taps/simpson.c b/gnuradio-core/src/gen_interpolator_taps/simpson.c new file mode 100644 index 000000000..fc6dd6c27 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/simpson.c @@ -0,0 +1,76 @@ +/* -*- c -*- */ +#include <math.h> +#include <stdio.h> + +#define EPS (1.0e-5) +#define JMAX 16 + +/* + * Compute the Nth stage of refinement of an extended trapezoidal + * rule. FUNC is input as a pointer to a function to be integrated + * between limits A and B. When called with N = 1, the routine + * returns the crudest estimate of the integral from A to B of f(x) + * dx. Subsequent calls with N=2,3,... (in that sequential order) + * will improve the accuracy by adding 2**(N-2) additional interior + * points. + * + * N.B., this function contains static state and IS NEITHER RENTRANT + * NOR THREAD SAFE! + */ + +double +trapzd (double (*func)(double), + double a, double b, + int n) +{ + long double x, tnm, sum, del; + static long double s; + static int it; + int j; + + if (n == 1){ + it = 1; /* # of points to add on the next call */ + s = 0.5 * (b - a) * (func(a) + func(b)); + return s; + } + else { + tnm = it; + del = (b-a)/tnm; /* this is the spacing of the points to be added */ + x = a + 0.5*del; + for (sum = 0.0, j = 1; j <= it; j++, x += del) + sum += func(x); + it *= 2; + s = 0.5 * (s + (b-a) * sum/tnm); /* replace s by it's refined value */ + return s; + } +} + +/* + * Returns the integral of the function FUNC from A to B. The + * parameters EPS can be set to the desired fractional accuracy and + * JMAX so that 2**(JMAX-1) is the maximum allowed number of steps. + * Integration is performed by Simpson's rule. + */ + +double +qsimp (double (*func)(double), + double a, /* lower limit */ + double b) /* upper limit */ +{ + int j; + long double s, st, ost, os; + + ost = os = -1.0e30; + for (j = 1; j <= JMAX; j++){ + st = trapzd (func, a, b, j); + s = (4.0 * st - ost)/3.0; + if (fabs (s - os) < EPS * fabs(os)) + return s; + os = s; + ost = st; + } + fprintf (stderr, "Too many steps in routine QSIMP\n"); + // exit (1); + return s; +} + diff --git a/gnuradio-core/src/gen_interpolator_taps/simpson.h b/gnuradio-core/src/gen_interpolator_taps/simpson.h new file mode 100644 index 000000000..68774f9a2 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/simpson.h @@ -0,0 +1,3 @@ +double qsimp (double (*func)(double), + double a, double b); + |