#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define MAXYR 200
#define MAXEST 100
#define MSIZE (MAXEST * (MAXEST + 1) / 2)
#define MAXSIM 600000
#define MAXSTP 500
#define CLCPAR "CLC.PAR"
#define CLCDAT "CLC.DAT"
#define CLCOUT "CLC.OUT"
void RDPARS(void);
void PHOUT(double *CL, double RAWCL, int ILAST, int IY);
double CLIMIT(double *CATCH, double *SIGHT, double *FMATRX, int *ISYR, int *IZYR,
double *ZMULT,double *POP, double *G);
double CONTRL(double D, double Y, double PLEVEL, double PSLOPE);
void DEVIAN(double *SS0, double *SS1, double *SS2, double *SS3, double *SIGHT, double *FMATRX,
int *ISYR, int *IZYR, double *ZMULT, double *POP, double *G);
double STKSIM(double RK, double R, double *POP, double *CATCH);
void SORT(double *ARRAY, double *ARRAY2, int N);
int _getline(char *buff, size_t size, FILE *fp);
/* from Fortran COMMON VARIABLE */
struct MANPAR {
double PPROB; /* Probability level */
double PYMAX; /* Maximum value of the productivity parameter (Y) for integration */
double PNYSTP; /* Number of step in integration over Y */
double PKSTEP; /* Maximum relative step size in integration over K */
double PDSTEP; /* Target step size for integration over depletion */
double PNBSTP; /* Number of steps for integration over the bias parameter */
double PBMIN; /* Minimum multiplicative bias eg 0.5 means 50% downward bias */
double PBMAX; /* Maximum multiplicative bias eg 1.5 means 50% upward bias */
double PSCALE; /* Raw deviance scaling factor S = 1/PSCALE**2 */
double PHASET; /* Number of years without surveys before phaseout invoked */
double PHASEP; /* Phaseout: anual reduction proportion */
double PCYCLE; /* Maximum number of years before a new CLC = number of years a CLC is valid */
double PLEVEL; /* Internal protection level */
double PSLOPE; /* 'Slope' of catch control law */
} mp;
/* All years are scaled so 0 = a year prior to the 1st input data */
struct MANDAT {
int ISTART; /* Year of first input data (catch or abundance data) */
int IYEAR; /* Year for which to set first catch limit */
int NS; /* Number of non-zero estimates */
int NZ; /* Number of zero estimates */
double RKLO; /* Lower bound used in integration over K */
double RKHI; /* Upper bound used in integration over K */
} md;
int main(void)
{
/* ***** LOCAL VARIABLES */
/*
CHARACTER STOCK*30, FORMT*50
INTEGER IY, INITYR, I, IS, IYRCL, ILAST, N, IN, IOUT
*/
double CATCH[MAXYR + 1], /* Catch array, indexed by year */
SIGHT[MAXEST + 1], /* Abundance estimate array, indexed by estimate number */
FMATRX[MSIZE + 1], /* Information matrix (H) of the log sightings estimates */
/* (excludeing zero estimates, stored as a lower triangle */
ZMULT[MAXEST + 1], /* Poisson multiplier for Nth zero estimate */
POP[MAXYR + 1], /* Modelled population size in year I (set in STKSIM) */
G[MAXYR + 1], /* set & used in DEVIAN */
RAWCL, /* Nominal catch limit i.e. output from the Catch Limit Algorithm */
CL; /* The catch limit for the area considerd */
int ISYR[MAXEST + 1], /* Year of Nth abundance estimate SIGHT(N). N=0, NS-1 */
IZYR[MAXEST + 1], /* Year of Nth zero estimate. N=0, NZ-1 */
POUT; /* Parameter determing whether phaseout may be applied if */
/* necessary. Test for phaseout if POUT=1. (Phaseout is not */
/* applied to Medium of Large area nominal catch limits) */
int INITYR, /* Year in which first premanagement catch taken */
ILAST, /* Year of the most recent abundance estimate */
IY, I, IS, IYRCL, N, J, N1;
double C, TOTALC;
int numlen, len, ret = 0;
char /* STOCK[30], FORMT[50],*/ buff[300];
/* ***** Read in the data required for application of the CLA */
/* DATA IN/2/, IOUT/3/ */
FILE *IN = NULL, *IOUT = NULL;
/* OPEN (IN, FILE = 'CLC.DAT') */
if ((IN
= fopen(CLCDAT
, "rt")) == NULL
) { fprintf(stderr
, "Can't open " CLCDAT
"\n"); ret = 1;
}
/* OPEN (IOUT, FILE = 'CLC.OUT') */
if ((IOUT
= fopen(CLCOUT
, "w")) == NULL
) { fprintf(stderr
, "Can't open " CLCOUT
"\n"); ret = 1;
}
RDPARS();
/* READ (IN, '(A30/)') STOCK */
_getline(buff, sizeof(buff), IN);
/* WRITE (IOUT, '(A30/)') STOCK */
fprintf(IOUT
, "%s by C\n\n", buff
); fprintf(stdout
, "%s by C\n", buff
); _getline(buff, sizeof(buff), IN); /* Discard empty lines */
/* Read the year of the first catch, the first year for which catch */
/* limits are to be set & the phaseout option */
/* READ (IN, '(T30,I4)') INITYR */
_getline(buff, sizeof(buff), IN);
numlen
= 4; len
= strlen(buff
); INITYR
= atoi(&buff
[len
-numlen
]);
/* WRITE (IOUT, '(A,T30,I4)') 'Year of first input data', INITYR */
fprintf(IOUT
, "%.*s %4d\n", len
- numlen
, buff
, INITYR
); fprintf(stdout
, "%.*s %4d\n", len
- numlen
, buff
, INITYR
);
/* READ (IN, '(T30,I4)') IYRCL */
_getline(buff, sizeof(buff), IN);
numlen
= 4; len
= strlen(buff
); IYRCL
= atoi(&buff
[len
-numlen
]);
/* WRITE (IOUT, '(A, T30, I4)') 'Year of first catch limit', IYRCL */
fprintf(IOUT
, "%.*s %4d\n", len
- numlen
, buff
, IYRCL
); fprintf(stdout
, "%.*s %4d\n", len
- numlen
, buff
, IYRCL
);
/* READ (IN, '(T30, I4)') POUT */
_getline(buff, sizeof(buff), IN);
numlen
= 4; len
= strlen(buff
); POUT
= atoi(&buff
[len
-numlen
]); if (POUT == 1) {
/* WRITE (IOUT, '(A, T30,A4)') 'Apply phaseout if necessary', 'YES' */
fprintf(IOUT
, "Apply phaseout if necessary YES\n"); fprintf(stdout
, "Apply phaseout if necessary YES\n"); } else {
/* WRITE (IOUT, '(A, T30,A4)') 'Apply phaseout', 'No' */
fprintf(IOUT
, "Apply phaseout No\n"); fprintf(stdout
, "Apply phaseout No\n"); }
/* Re-scale IYRCL such that 0 is the year prior to the first input data */
md.ISTART = 0;
md.IYEAR = IYRCL - INITYR;
/* IF (IYEAR .LE. 0 .OR. IYEAR .GT. MAXYR) STOP 'INVALID YEAR' */
if ((md.IYEAR <= 0) || (md.IYEAR > MAXYR)) {
ret = 1;
}
/* Initialize the catch array */
/* DO 10 I = 0, MAXYR */
for (I = 0; I <= MAXYR; I++) {
CATCH[I] = 0.0;
} /* 10 CONTINUE */
/* Read in the catch data, scaling each year to the initial year */
/* READ (IN, '(// A)') FORMT (I4,F8.0) */
_getline(buff, sizeof(buff), IN); /* Discard empty lines */
_getline(buff, sizeof(buff), IN); /* Discard empty lines */
_getline(buff, sizeof(buff), IN); /* Discard empty lines */
/* WRITE (IOUT, '(/A)') 'Historic catches:' */
fprintf(IOUT
, "\nHistoric catches:\n"); fprintf(stdout
, "\nHistoric catches:\n"); TOTALC = 0;
/* DO 20 I = 0, MAXYR */
for (I = 0; I <= MAXYR; I++) {
/* READ (IN, FORMT) IY, C */
_getline(buff, sizeof(buff), IN);
sscanf(buff
,"%4d%7lf", &IY
, &C
); /* IF (IY .LT. 0) GO TO 25 */
if (IY < 0) break; /* EOD */
/* WRITE (IOUT, FORMT) IY, C */
fprintf(stdout
, "%4d%6.f\n", IY
, C
); IY = IY - INITYR;
/* IF (IY .LT. 0 .OR. IY .GE. IYEAR) STOP */
if (IY < 0 || IY > md.IYEAR) {
fprintf(stderr
, " ERROR: IY is out of range(%d)\n", IY
); ret = 1;
}
CATCH[IY] = C;
TOTALC = TOTALC + C;
} /* 20 CONTINUE */
/* 25 IF (TOTALC .LT. 0) STOP ' ERROR: No historic catch input' */
if (TOTALC < 0) {
fprintf(stderr
, " ERROR: No historic catch input\n"); ret = 1;
}
/* Read in the non-zero sightings estimates and information matrix */
/* READ (IN, '(//T30, I4 / A)') NS, FORMT (I4,F10.0,10F8.0) */
_getline(buff, sizeof(buff), IN); /* Discard empty lines */
_getline(buff, sizeof(buff), IN); /* Discard empty lines */
_getline(buff, sizeof(buff), IN);
numlen
= 4; len
= strlen(buff
); md.
NS = atoi(&buff
[len
-numlen
]);
/* WRITE (IOUT, '(/A)') 'Abundance estimates:' */
fprintf(IOUT
, "\nAbundance estimates:\n"); fprintf(stdout
, "\nAbundance estimates:\n"); /* IF (NS .GT. MAXEST) STOP 'ERROR: Abundance year out of range' */
if (md.NS > MAXEST) {
fprintf(stderr
, "ERROR: Abundance year out of range\n"); ret = 1;
}
_getline(buff, sizeof(buff), IN);
/* DO 30 N=0, NS-1 */
for (N = 0; N <= md.NS - 1; N++) {
N1 = (N * (N + 1)) / 2;
/* READ (IN, FORMT) ISYR(N), SIGHT(N), (FMATRX(N1 + J), J = 0, N) */
_getline(buff, sizeof(buff), IN);
sscanf(buff
, "%4d%10lf", &ISYR
[N
], &SIGHT
[N
]); fprintf(IOUT
, "%4d %8.f", ISYR
[N
], SIGHT
[N
]); fprintf(stdout
, "%4d %8.f", ISYR
[N
], SIGHT
[N
]); for (J = 0; J < N + 1; J++) {
if (len > J * 7 + 14) {
sscanf(&buff
[0] + J
* 7 + 14,"%7lf", &FMATRX
[N1
+ J
]); } else {
FMATRX[N1 + J] = 0.0;
}
fprintf(IOUT
, "%7.f", FMATRX
[N1
+ J
]); fprintf(stdout
, "%7.f", FMATRX
[N1
+ J
]); }
/* WRITE (IOUT, FORMT) ISYR(N), SIGHT(N), (FMATRX (N1 + J), J = 0, N) */
ISYR[N] = ISYR[N] - INITYR;
if (ISYR[N] < 0 || ISYR[N] >= md.IYEAR) {
/*STOP 'ERROR: Sight year out of range'*/
fprintf(stderr
, "ERROR: Sight year out of range\n"); ret = 1;
}
if (SIGHT[N] <= 0.0) {
/* STOP ' ERROR: Estimate not positive' */
fprintf(stderr
, "ERROR: Estimate not positive\n"); ret = 1;
}
} /* 30 CONTINUE */
/* Read in the Poisson multipliers for any zero sightings estimates */
/* READ (IN, '(/T30, I3, /A)') NZ, FORMAT */
_getline(buff, sizeof(buff), IN);
_getline(buff, sizeof(buff), IN);
numlen
= 3; len
= strlen(buff
); md.
NZ = atoi(&buff
[len
-numlen
]); if (md.NZ > 0) {
/* WRITE (IOUT, '(/A)') 'Zero abundance estimates:' */
fprintf(IOUT
, "\nZero abundance estimates:\n"); fprintf(stdout
, "\nZero abundance estimates:\n"); }
if (md.NZ > MAXEST) {
/* STOP ' ERROR: Zero estimate array too small' */
fprintf(stderr
, "ERROR: Zero estimate array too small\n"); ret = 1;
}
_getline(buff, sizeof(buff), IN);
/* DO 40 N = 0, NZ - 1 */
for (N = 0; N <= md.NZ - 1; N++) {
N1 = (N * (N + 1)) / 2;
/*READ (IN, FORMT) IZYR(N), ZMULT(N)*/
_getline(buff, sizeof(buff), IN);
sscanf(buff
, "%4d%10lf", &IZYR
[N
], &ZMULT
[N
]); /* WRITE (IOUT, FORMT) IZYR(N), ZMULT(N) */
fprintf(IOUT
, "%4d%7.f\n", IZYR
[N
], ZMULT
[N
]); fprintf(stdout
, "%4d%7.f\n", IZYR
[N
], ZMULT
[N
]); IZYR[N] = IZYR[N] - INITYR;
if (IZYR[N] < 0 || IZYR[N] >= md.IYEAR) {
/* STOP ' Sight year out of range' */
fprintf(stderr
, "Sight year out of range\n"); ret = 1;
}
if (ZMULT[N] <= 0.0) {
/* STOP ' ERROR: Multiplier not positive' */
fprintf(stderr
, "ERROR: Multiplier not positive\n"); ret = 1;
}
} /* 40 CONTINUE */
/*WRITE (IOUT, '()')*/
/* Bound the range for the integration over K */
md.RKHI = 1.0E7;
md.RKLO = 0.0;
IS = 0; /* orignal not initialized bug? */
/* ****** */
/* ****** Run the CLA to obtain the nominal catch limit */
/* ****** */
RAWCL = CLIMIT(CATCH, SIGHT, FMATRX, ISYR, IZYR, ZMULT, POP, G);
/* Set the catch limits for PCYCLE years. If the catch limit may be */
/* subject to phaseout, call POUT to apply the phaseout rule. */
/* First set ILAST = year of the most recent abundance estimate */
if (md.NS > 0) ILAST = ISYR[md.NS - 1];
/* IF (NZ .GT. 0) ILAST = MAX(IS, IZYR(md.NZ - 1)) */
if (md.NZ > 0) ILAST = (IS > IZYR[md.NZ - 1])? IS: IZYR[md.NZ - 1];
/* DO 100 IY = IYEAR, IYEAR + mp.PCYCLE - f1 */
for (IY = md.IYEAR; IY <= md.IYEAR + mp.PCYCLE - 1; IY++) {
if (POUT == 1) {
PHOUT(&CL, RAWCL, ILAST, IY);
} else {
CL = RAWCL;
}
/* WRITE (IOUT, '(A6, I5, A17, I6)') 'Year:', IY + INITYR,'Catch limit:', NINT(CL) */
fprintf(IOUT
, "Year: %4d Catch limit:%6d\n", IY
+ INITYR
, (int)(CL
+ 0.5)); fprintf(stdout
, "Year: %4d Catch limit:%6d\n", IY
+ INITYR
, (int)(CL
+ 0.5));
} /* 100 CONTINUE */
if (IOUT
!= NULL
) fclose(IOUT
); return ret;
/* STOP */
/* END */
}
/*
C **************************************************************************************
C
C CLC version 6
C
C **************************************************************************************
C
C 31 January 1994
C
C **************************************************************************************
*/
/*
SUBROUTINE RDPARS
Read the file of input parameters
*/
void RDPARS(void)
{
double *p[] = {
&mp.PPROB, &mp.PYMAX, &mp.PNYSTP,&mp.PKSTEP, &mp.PDSTEP, &mp.PBMIN, &mp.PBMAX,
&mp.PNBSTP, &mp.PSCALE, &mp.PHASET, &mp.PHASEP, &mp.PCYCLE, &mp.PLEVEL, &mp.PSLOPE
};
FILE *IFILE;
char buff[80];
int count;
/* Open the input file (only read once) */
IFILE
= fopen(CLCPAR
, "rt"); if (IFILE == NULL) {
fprintf(stderr
,"Can't open " CLCPAR
"\n"); }
count = 0;
while (_getline(buff, sizeof(buff), IFILE) != 0) {
/* READ (IFILE, '(T30, F10.0)') PPROB, PYMAX, PNYSTP, PKSTEP, PDSTEP, PBMIN, PBMAX,
PNBSTP, PSCALE, PHASET, PHASEP, PCYCLE, PLEVEL, PSLOPE */
sscanf(buff
,"%*28c%lf", p
[count
]); count++;
}
/* CLOSE (IFILE) */
return;
/* RETURN
END */
}
/*
SUBROUTINE PHOUT (CL, RAWCL, ILAST, IY)
*/
void PHOUT(double *CL, double RAWCL, int ILAST, int IY)
{
/*
PHASET Number of years without surveys before phaseout invoked
PHASEP Phaseout annual reduction proportion
Phaseout: Reduce catch limit if there is no survey data in the
last PHASET years
*/
if (IY >= ILAST + mp.PHASET) {
*CL = RAWCL * (1.0 - mp.PHASEP * (IY - ILAST - mp.PHASET));
if (*CL < 0.0) *CL = 0.0;
} else {
*CL = RAWCL;
}
/* RETURN
END */
}
/*
REAL FUNCTION CLIMIT (CATCH,SIGHT,FMATRX,ISYR,IZYR,ZMULT,POP,G)
Run the CLA to obtain to nominal catch limit
*/
double CLIMIT(double *CATCH, double *SIGHT, double *FMATRX, int *ISYR, int *IZYR, double *ZMULT,double *POP, double *G)
{
/*
Local variables:
REAL PRES(0:MAXSIM), QRES(0:MAXSIM), SS0, SS1, SS2, SS3
REAL SF, Y(0:MAXSTP), B(0:MAXSTP), RLGB(0:MAXSTP)
INTEGER NB, NR
NB Number of bias steps
NR Number of steps for Y (the productivity parameter)
SF Deviance scale factor (SF = .5 / PSCALE**2)
*/
double SF, SS0, SS1, SS2, SS3;
double Y[MAXSTP + 1], B[MAXSTP + 1], RLGB[MAXSTP + 1];
double *PRES = NULL, *QRES = NULL;
int NB, NR;
double BINC, YINC, DK, R, RK, D, DD, P, Q, PTOT;
int I, J, N, N2;
double _CLIMIT = 0.0;
if (md.NS <= 0) return _CLIMIT;
PRES
= (double *) malloc(sizeof(double) * (MAXSIM
+ 1)); if (PRES == NULL) {
fprintf(stderr
, "Can't Allocate memory (PRES)\n"); goto err_exit;
}
memset(PRES
, 0, sizeof(double) * (MAXSTP
+ 1));
QRES
= (double *) malloc(sizeof(double) * (MAXSIM
+ 1)); if (QRES == NULL) {
fprintf(stderr
, "Can't Allocate memory (QRES)\n"); goto err_exit;
}
memset(QRES
, 0, sizeof(double) * (MAXSTP
+ 1));
/* Set deviance scale factor S = 1/PSCALE**2 */
SF = 0.5 / (mp.PSCALE * mp.PSCALE);
/* Check the sizes of the Y and B arrays are large enough */
if (mp.PNBSTP > MAXSTP || mp.PNYSTP > MAXSTP) {
fprintf(stderr
, "Y &/or b array sizes too small\n"); goto err_exit;
}
/* Set sightings bias step sizes & their log values. BINC = Bias increment */
NB = (int)mp.PNBSTP;
BINC = (mp.PBMAX - mp.PBMIN) / NB;
/* DO 10 I = 0, NB - 1 */
for (I = 0; I <= NB - 1; I++) {
*(B + I) = mp.PBMIN + (I + 0.5) * BINC;
*(RLGB
+ I
) = -log(*(B
+ I
)); } /* 10 CONTINUE */
/* Set productivity parameter step sizes (midpoints) */
NR = (int)mp.PNYSTP;
YINC = mp.PYMAX / NR;
/* DO 20 I = 0, NR - 1 */
for (I = 0; I <= NR - 1; I++) {
*(Y + I) = (I + 0.5) * YINC;
}/* 20 CONTINUE */
PTOT = 0;
N = 0;
/* DO 50 I = 0, NR - 1 */
for (I = 0; I <= NR - 1; I++) {
/* Set R from the productivity parameter, Y */
R = 1.4184 * *(Y + I);
/* Step size for K */
DK = mp.PKSTEP;
D = 1.0;
RK = md.RKHI;
/* Use function STKSIM to set up the Nth population trajectory */
/* i.e. set up the pop array */
while (1) {
/* 30 IF (RK .LE. RKLO .OR. STKSIM (RK, R, POP, CATCH) .LE. 0.) GOTO 40 */
if ((RK <= md.RKLO) || (STKSIM(RK, R, POP, CATCH) <= 0.0)) break;
/* IF (N .GE. MAXSIM) STOP 'ERROR: TOO MANY SIMULATIONS' */
if (N >= MAXSIM) {
fprintf(stderr
, "ERROR: TOO MANY SIMULATIONS"); goto err_exit;
}
/* How much depletion covered? */
DD = D - POP[md.IYEAR] / RK;
D = POP[md.IYEAR] / RK;
P = 0.0;
if (DD > 0.0) {
/* Compute the internal catch limit corresponding to D and Y(I) */
QRES[N] = CONTRL(D, Y[I], mp.PLEVEL, mp.PSLOPE) * POP[md.IYEAR];
/* Calculate deviance */
DEVIAN(&SS0, &SS1, &SS2, &SS3, SIGHT, FMATRX, ISYR,IZYR, ZMULT, POP, G);
/* Scale likelihood and integrate over values for the bias parameter */
/* DO 35 J = 0, NB - 1 */
for (J = 0; J <= NB - 1; J++) {
P
= P
+ exp(-SF
* (SS0
+ *(RLGB
+ J
) * (SS1
+ *(RLGB
+ J
) * SS2
) + SS3
* *(B
+ J
))); } /* 35 CONTINUE */
/* Calculate the weight for this point (& total area under likelihood) */
PRES[N] = P * DD;
PTOT = PTOT + PRES[N];
/* Update counter */
N = N + 1;
/* Find the next K */
DK = DK * mp.PDSTEP / DD;
/* IF (DK .GT. PKSTEP) DK = PKSTEP */
if (DK > mp.PKSTEP) DK = mp.PKSTEP;
} else {
/* IF DD = 0 change the step size only */
DK = mp.PKSTEP;
}
/* Set the new value of K */
RK = RK / (1.0 + DK);
} /* GOTO 30 */ /* 40 CONTINUE */
} /* 50 CONTINUE */
/* IF (PTOT .LE. 0.) STOP 'ERROR: PROB INTEGRATES TO ZERO' */
if (PTOT < 0.0) {
fprintf(stderr
,"ERROR: PROB INTEGRATES TO ZERO"); goto err_exit;
}
/* Sort the QRES and PRES arrays in ascending order of QRES */
N2 = N;
SORT(QRES, PRES, N2);
/* Normalize the relative likelihoods */
/* DO 60 I = 0, N - 1 */
for (I = 0; I <= N - 1; I++) {
PRES[I] = PRES[I] / PTOT;
} /* 60 CONTINUE */
/* Extract the desired probability level: the nominal catch limit (NCL) */
/* is the lower PROB% of the distribution. */
/* First calculate PRES(I), the probability that the NCL is between */
/* QRES(I) & QRES(I + 1). */
P = 0;
/* DO 70 I = 0, N - 1 */
for (I = 0; I <= N - 1; I++) {
P = P + PRES[I];
/* IF (P .GT. PPROB) GOTO 80 */
if (P > mp.PPROB) break;
} /* 70 CONTINUE */
/* Interpolate to set the nominal catch limit */
/* 80 IF (I .GE. N - 1) THEN */
if (I >= N - 1) {
Q = QRES[N - 1];
} else {
Q = (QRES[I + 1] * (mp.PPROB - P + PRES[I]) + QRES[I] * (P - mp.PPROB)) / PRES[I];
}
_CLIMIT = Q;
if (QRES
!= NULL
) free(QRES
); if (PRES
!= NULL
) free(PRES
); /* if (Y != NULL) free(Y);
if (B != NULL) free(B);
if (RLGB != NULL) free(RLGB);*/
return _CLIMIT;
err_exit:
if (QRES
!= NULL
) free(QRES
); if (PRES
!= NULL
) free(PRES
); /* if (Y != NULL) free(Y);
if (B != NULL) free(B);
if (RLGB != NULL) free(RLGB);*/
return 0.0; /* not reached */
/* RETURN */
/* END */
}
/*
FUNCTION CONTRL (D, Y, PLEVEL, PSLOPE)
Catch control law
*/
double CONTRL(double D, double Y, double PLEVEL, double PSLOPE)
{
double ret;
if (D < PLEVEL) {
ret = 0.0;
} else if (D < 1.0) {
ret = PSLOPE * Y * (D - PLEVEL);
} else {
ret = PSLOPE * Y * (1.0 - PLEVEL);
}
return ret;
/* END */
}
/*
SUBROUTINE DEVIAN (SS0, SS1, SS2, SS3, SIGHT, FMATRX, ISYR,
Calculate deviance (-2 log likelihood) in terms of coefficients for
the bias and log bias parameters
*/
void DEVIAN(double *SS0, double *SS1, double *SS2, double *SS3, double *SIGHT,
double *FMATRX, int *ISYR, int *IZYR, double *ZMULT, double *POP, double *G)
{
/* REAL SS0,SS1,SS2,SIGHT(0:*),FMATRX(0:*),ZMULT(0:*),POP(0:*),G(0:*) */
/* INTEGER ISYR(0:*), IZYR(0:*) */
int N, J, K;
*SS0 = 0.0;
*SS1 = 0.0;
*SS2 = 0.0;
*SS3 = 0.0;
/* DO 100 N = 0, NS - 1 */
for (N = 0; N <= md.NS - 1; N++) {
*(G
+ N
) = log(*(SIGHT
+ N
) / *(POP
+*(ISYR
+ N
))); K = N * (N + 1) / 2;
/* DO 10 J = 0, N - 1 */
for (J = 0; J <= N - 1; J++) {
/*1st add non diagonal contributions (which are doubled up)*/
*SS0 = *SS0 + 2.0 * *(G + J) * *(G + N) * *(FMATRX + K);
*SS1 = *SS1 + 2.0 * (*(G + J) + *(G + N)) * *(FMATRX + K);
*SS2 = *SS2 + *(FMATRX + K) + *(FMATRX + K);
K = K + 1;
} /* 10 CONTINUE*/
/* Now add diagnoal contribution */
*SS0 = *SS0 + *(G + N) * *(G + N) * *(FMATRX + K);
*SS1 = *SS1 + 2.0 * *(G + N) * *(FMATRX + K);
*SS2 = *SS2 + *(FMATRX + K);
} /* 100 CONTINUE */
/* Now do the zero estimates */
/* DO 200 N = 0, NZ - 1 */
for (N =0; N <= md.NZ - 1; N++) {
*SS3 = *SS3 + 2.0 * *(POP + *(IZYR + N)) / *(ZMULT + N);
} /* 200 CONTINUE */
/* RETURN */
/* END */
return;
}
/*
FUNCTION STKSIM (RK, R, POP, CATCH)
Calculate the stock trajectory with parameter RK and R: return
the current stock size
RK = notional carrying capacity; R = productivity parameter * 1.4184
*/
double STKSIM(double RK, double R, double *POP, double *CATCH)
{
/*INTEGER ISTART, IYEAR, NS, NZ, RKLO, RKHI */
/* REAL CATCH(0:*), POP(0:*) */
int I;
double D;
*(POP+md.ISTART) = RK;
/*DO 10 I = md.ISTART + 1, md.IYEAR*/
for (I = md.ISTART + 1; I <= md.IYEAR; I++) {
D = *(POP + I - 1) / RK;
*(POP + I) = *(POP + I - 1) * (1.0 + R * (1.0 - D * D)) - *(CATCH + I -1);
if (*(POP + I) <= 0) { /*GOTO 20*/
return 0.0;
/* 20 STKSIM = 0. */
}
} /* 10 CONTINUE */
/* STKSIM = POP(md.IYEAR) */
return *(POP + md.IYEAR);
/* RETURN */
/* END */
}
/*
SUBROUTINE SORT (ARRAY, ARRAY2, N)
SORT sorts a pair of arrays in ascending order of the first array
(using the heapsort algorithm)
*/
void SORT(double *ARRAY, double *ARRAY2, int N)
{
double /*ARRAY(0:*), ARRAY2(0:*),*/ TEMP, TEMP2;
int /*N,*/ K, IR, I, J;
if (N < 2) return;
K = N / 2;
IR = N - 1;
while (1) { /*10*/
if (K != 0) {
K = K - 1;
TEMP = *(ARRAY + K);
TEMP2 = *(ARRAY2 + K);
} else {
TEMP = *(ARRAY + IR);
TEMP2 = *(ARRAY2 + IR);
*(ARRAY + IR) = *ARRAY;
*(ARRAY2 + IR) = *ARRAY2;
IR = IR - 1;
if (IR == 0) {
*ARRAY = TEMP;
*ARRAY2 = TEMP2;
return;
}
}
I = K;
J = K + K + 1;
while (1) {/*20*/
if (J > IR) break;
if ((J < IR) && (*(ARRAY + J) < *(ARRAY+ J + 1))) J = J + 1;
if (TEMP < *(ARRAY + J)) {
*(ARRAY + I) = *(ARRAY + J);
*(ARRAY2 + I) = *(ARRAY2 + J);
I = J;
J = J + I + 1;
} else {
J = IR + 1;
}
} /*GOTO 20*/
*(ARRAY + I) = TEMP;
*(ARRAY2 + I) = TEMP2;
}/*GOTO 10*/
/*END*/
}
int _getline(char *buff, size_t size, FILE *fp){
char *ret;
ret
= fgets(buff
, size
, fp
); if (ret != NULL) {
if (buff
[strlen(buff
) - 1] == '\n') if (buff
[strlen(buff
) - 1] == '\r') }
return (ret != NULL);
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8bWF0aC5oPgoKI2RlZmluZSBNQVhZUiAgMjAwCiNkZWZpbmUgTUFYRVNUIDEwMAojZGVmaW5lIE1TSVpFICAoTUFYRVNUICogKE1BWEVTVCArIDEpIC8gMikKCiNkZWZpbmUgTUFYU0lNICA2MDAwMDAKI2RlZmluZSBNQVhTVFAgIDUwMAojZGVmaW5lIENMQ1BBUiAgIkNMQy5QQVIiCiNkZWZpbmUgQ0xDREFUICAiQ0xDLkRBVCIKI2RlZmluZSBDTENPVVQgICJDTEMuT1VUIgoKdm9pZCBSRFBBUlModm9pZCk7CnZvaWQgUEhPVVQoZG91YmxlICpDTCwgZG91YmxlIFJBV0NMLCBpbnQgSUxBU1QsIGludCBJWSk7CmRvdWJsZSBDTElNSVQoZG91YmxlICpDQVRDSCwgZG91YmxlICpTSUdIVCwgZG91YmxlICpGTUFUUlgsIGludCAqSVNZUiwgaW50ICpJWllSLAogICAgICAgICAgICAgIGRvdWJsZSAqWk1VTFQsZG91YmxlICpQT1AsIGRvdWJsZSAqRyk7CmRvdWJsZSBDT05UUkwoZG91YmxlIEQsIGRvdWJsZSBZLCBkb3VibGUgUExFVkVMLCBkb3VibGUgUFNMT1BFKTsKdm9pZCBERVZJQU4oZG91YmxlICpTUzAsIGRvdWJsZSAqU1MxLCBkb3VibGUgKlNTMiwgZG91YmxlICpTUzMsIGRvdWJsZSAqU0lHSFQsIGRvdWJsZSAqRk1BVFJYLCAKICAgICAgICAgICAgaW50ICpJU1lSLCBpbnQgKklaWVIsIGRvdWJsZSAqWk1VTFQsIGRvdWJsZSAqUE9QLCBkb3VibGUgKkcpOwpkb3VibGUgU1RLU0lNKGRvdWJsZSBSSywgZG91YmxlIFIsIGRvdWJsZSAqUE9QLCBkb3VibGUgKkNBVENIKTsKdm9pZCBTT1JUKGRvdWJsZSAqQVJSQVksIGRvdWJsZSAqQVJSQVkyLCBpbnQgTik7CmludCAgX2dldGxpbmUoY2hhciAqYnVmZiwgc2l6ZV90IHNpemUsIEZJTEUgKmZwKTsKCi8qIGZyb20gRm9ydHJhbiBDT01NT04gVkFSSUFCTEUgKi8Kc3RydWN0IE1BTlBBUiB7Cglkb3VibGUgUFBST0I7ICAvKiBQcm9iYWJpbGl0eSBsZXZlbCAqLwoJZG91YmxlIFBZTUFYOyAgLyogTWF4aW11bSB2YWx1ZSBvZiB0aGUgcHJvZHVjdGl2aXR5IHBhcmFtZXRlciAoWSkgZm9yIGludGVncmF0aW9uICovCglkb3VibGUgUE5ZU1RQOyAvKiBOdW1iZXIgb2Ygc3RlcCBpbiBpbnRlZ3JhdGlvbiBvdmVyIFkgKi8KCWRvdWJsZSBQS1NURVA7IC8qIE1heGltdW0gcmVsYXRpdmUgc3RlcCBzaXplIGluIGludGVncmF0aW9uIG92ZXIgSyAqLwoJZG91YmxlIFBEU1RFUDsgLyogVGFyZ2V0IHN0ZXAgc2l6ZSBmb3IgaW50ZWdyYXRpb24gb3ZlciBkZXBsZXRpb24gKi8KCWRvdWJsZSBQTkJTVFA7IC8qIE51bWJlciBvZiBzdGVwcyBmb3IgaW50ZWdyYXRpb24gb3ZlciB0aGUgYmlhcyBwYXJhbWV0ZXIgKi8KCWRvdWJsZSBQQk1JTjsgIC8qIE1pbmltdW0gbXVsdGlwbGljYXRpdmUgYmlhcyBlZyAwLjUgbWVhbnMgNTAlIGRvd253YXJkIGJpYXMgKi8KCWRvdWJsZSBQQk1BWDsgIC8qIE1heGltdW0gbXVsdGlwbGljYXRpdmUgYmlhcyBlZyAxLjUgbWVhbnMgNTAlIHVwd2FyZCBiaWFzICovCglkb3VibGUgUFNDQUxFOyAvKiBSYXcgZGV2aWFuY2Ugc2NhbGluZyBmYWN0b3IgUyA9IDEvUFNDQUxFKioyICovCglkb3VibGUgUEhBU0VUOyAvKiBOdW1iZXIgb2YgeWVhcnMgd2l0aG91dCBzdXJ2ZXlzIGJlZm9yZSBwaGFzZW91dCBpbnZva2VkICovCglkb3VibGUgUEhBU0VQOyAvKiBQaGFzZW91dDogYW51YWwgcmVkdWN0aW9uIHByb3BvcnRpb24gKi8KCWRvdWJsZSBQQ1lDTEU7IC8qIE1heGltdW0gbnVtYmVyIG9mIHllYXJzIGJlZm9yZSBhIG5ldyBDTEMgPSBudW1iZXIgb2YgeWVhcnMgYSBDTEMgaXMgdmFsaWQgKi8KCWRvdWJsZSBQTEVWRUw7IC8qIEludGVybmFsIHByb3RlY3Rpb24gbGV2ZWwgKi8KCWRvdWJsZSBQU0xPUEU7IC8qICdTbG9wZScgb2YgY2F0Y2ggY29udHJvbCBsYXcgKi8KfSBtcDsKCi8qIEFsbCB5ZWFycyBhcmUgc2NhbGVkIHNvIDAgPSBhIHllYXIgcHJpb3IgdG8gdGhlIDFzdCBpbnB1dCBkYXRhICovCnN0cnVjdCBNQU5EQVQgewoJaW50IElTVEFSVDsgICAgLyogWWVhciBvZiBmaXJzdCBpbnB1dCBkYXRhIChjYXRjaCBvciBhYnVuZGFuY2UgZGF0YSkgKi8KCWludCBJWUVBUjsgICAgIC8qIFllYXIgZm9yIHdoaWNoIHRvIHNldCBmaXJzdCBjYXRjaCBsaW1pdCAqLwoJaW50IE5TOyAgICAgICAgLyogTnVtYmVyIG9mIG5vbi16ZXJvIGVzdGltYXRlcyAqLwoJaW50IE5aOyAgICAgICAgLyogTnVtYmVyIG9mIHplcm8gZXN0aW1hdGVzICovCglkb3VibGUgUktMTzsgICAvKiBMb3dlciBib3VuZCB1c2VkIGluIGludGVncmF0aW9uIG92ZXIgSyAqLwoJZG91YmxlIFJLSEk7ICAgLyogVXBwZXIgYm91bmQgdXNlZCBpbiBpbnRlZ3JhdGlvbiBvdmVyIEsgKi8KfSBtZDsKCmludCBtYWluKHZvaWQpCnsKLyogKioqKiogTE9DQUwgVkFSSUFCTEVTICovCi8qCglDSEFSQUNURVIgU1RPQ0sqMzAsIEZPUk1UKjUwCglJTlRFR0VSIElZLCBJTklUWVIsIEksIElTLCBJWVJDTCwgSUxBU1QsIE4sIElOLCBJT1VUCiovCglkb3VibGUJQ0FUQ0hbTUFYWVIgKyAxXSwgIC8qIENhdGNoIGFycmF5LCBpbmRleGVkIGJ5IHllYXIgKi8KCQkJU0lHSFRbTUFYRVNUICsgMV0sIC8qIEFidW5kYW5jZSBlc3RpbWF0ZSBhcnJheSwgaW5kZXhlZCBieSBlc3RpbWF0ZSBudW1iZXIgKi8KCQkJRk1BVFJYW01TSVpFICsgMV0sIC8qIEluZm9ybWF0aW9uIG1hdHJpeCAoSCkgb2YgdGhlIGxvZyBzaWdodGluZ3MgZXN0aW1hdGVzICovCgkJCQkJCQkgLyogKGV4Y2x1ZGVpbmcgemVybyBlc3RpbWF0ZXMsIHN0b3JlZCBhcyBhIGxvd2VyIHRyaWFuZ2xlICovCgkJCVpNVUxUW01BWEVTVCArIDFdLCAvKiBQb2lzc29uIG11bHRpcGxpZXIgZm9yIE50aCB6ZXJvIGVzdGltYXRlICovCgkJCVBPUFtNQVhZUiArIDFdLCAgICAvKiBNb2RlbGxlZCBwb3B1bGF0aW9uIHNpemUgaW4geWVhciBJIChzZXQgaW4gU1RLU0lNKSAqLwoJCQlHW01BWFlSICsgMV0sICAgICAgLyogc2V0ICYgdXNlZCBpbiBERVZJQU4gKi8KCQkJUkFXQ0wsICAgICAgICAgICAvKiBOb21pbmFsIGNhdGNoIGxpbWl0IGkuZS4gb3V0cHV0IGZyb20gdGhlIENhdGNoIExpbWl0IEFsZ29yaXRobSAqLwoJCQlDTDsgICAgICAgICAgICAgIC8qIFRoZSBjYXRjaCBsaW1pdCBmb3IgdGhlIGFyZWEgY29uc2lkZXJkICovCglpbnQgCUlTWVJbTUFYRVNUICsgMV0sICAvKiBZZWFyIG9mIE50aCBhYnVuZGFuY2UgZXN0aW1hdGUgU0lHSFQoTikuIE49MCwgTlMtMSAqLwoJCQlJWllSW01BWEVTVCArIDFdLCAgLyogWWVhciBvZiBOdGggemVybyBlc3RpbWF0ZS4gTj0wLCBOWi0xICovCgkJCVBPVVQ7ICAgICAgICAgICAgLyogUGFyYW1ldGVyIGRldGVybWluZyB3aGV0aGVyIHBoYXNlb3V0IG1heSBiZSBhcHBsaWVkIGlmICovCgkJCQkJCQkgLyogbmVjZXNzYXJ5LiBUZXN0IGZvciBwaGFzZW91dCBpZiBQT1VUPTEuIChQaGFzZW91dCBpcyBub3QgKi8KCQkJCQkJCSAvKiBhcHBsaWVkIHRvIE1lZGl1bSBvZiBMYXJnZSBhcmVhIG5vbWluYWwgY2F0Y2ggbGltaXRzKSAqLwoJaW50IAlJTklUWVIsCQkJIC8qIFllYXIgaW4gd2hpY2ggZmlyc3QgcHJlbWFuYWdlbWVudCBjYXRjaCB0YWtlbiAqLwoJCQlJTEFTVCwJCQkgLyogWWVhciBvZiB0aGUgbW9zdCByZWNlbnQgYWJ1bmRhbmNlIGVzdGltYXRlICovCgkJCUlZLCBJLCBJUywgSVlSQ0wsIE4sIEosIE4xOwoJZG91YmxlCUMsIFRPVEFMQzsKCWludAkJbnVtbGVuLCBsZW4sIHJldCA9IDA7CgljaGFyIC8qIFNUT0NLWzMwXSwgRk9STVRbNTBdLCovIGJ1ZmZbMzAwXTsKCi8qICoqKioqIFJlYWQgaW4gdGhlIGRhdGEgcmVxdWlyZWQgZm9yIGFwcGxpY2F0aW9uIG9mIHRoZSBDTEEgKi8KCgkvKiBEQVRBIElOLzIvLCBJT1VULzMvICovCglGSUxFICpJTiA9IE5VTEwsICpJT1VUID0gTlVMTDsKCS8qIE9QRU4gKElOLCBGSUxFID0gJ0NMQy5EQVQnKSAqLwoJaWYgKChJTiA9IGZvcGVuKENMQ0RBVCwgInJ0IikpID09IE5VTEwpIHsKCQlmcHJpbnRmKHN0ZGVyciwgIkNhbid0IG9wZW4gIiBDTENEQVQgIlxuIik7CgkJcmV0ID0gMTsKCQlnb3RvIGV4aXQ7Cgl9CgkvKiBPUEVOIChJT1VULCBGSUxFID0gJ0NMQy5PVVQnKSAqLwoJaWYgKChJT1VUID0gZm9wZW4oQ0xDT1VULCAidyIpKSA9PSBOVUxMKSB7CgkJZnByaW50ZihzdGRlcnIsICJDYW4ndCBvcGVuICIgQ0xDT1VUICJcbiIpOwoJCXJldCA9IDE7CgkJZ290byBleGl0OwoJfQoKCVJEUEFSUygpOwoKCS8qIFJFQUQgKElOLCAnKEEzMC8pJykgU1RPQ0sgKi8KCV9nZXRsaW5lKGJ1ZmYsIHNpemVvZihidWZmKSwgSU4pOwoJLyogV1JJVEUgKElPVVQsICcoQTMwLyknKSBTVE9DSyAqLwoJZnByaW50ZihJT1VULCAiJXMgYnkgQ1xuXG4iLCBidWZmKTsKCWZwcmludGYoc3Rkb3V0LCAiJXMgYnkgQ1xuIiwgYnVmZik7CglfZ2V0bGluZShidWZmLCBzaXplb2YoYnVmZiksIElOKTsgLyogRGlzY2FyZCBlbXB0eSBsaW5lcyAqLwoKLyogCVJlYWQgdGhlIHllYXIgb2YgdGhlIGZpcnN0IGNhdGNoLCB0aGUgZmlyc3QgeWVhciBmb3Igd2hpY2ggY2F0Y2ggKi8KLyogbGltaXRzIGFyZSB0byBiZSBzZXQgJiB0aGUgcGhhc2VvdXQgb3B0aW9uICovCgoJLyogUkVBRCAoSU4sICcoVDMwLEk0KScpIElOSVRZUiAqLwoJX2dldGxpbmUoYnVmZiwgc2l6ZW9mKGJ1ZmYpLCBJTik7CgludW1sZW4gPSA0OyBsZW4gPSBzdHJsZW4oYnVmZik7CglJTklUWVIgPSBhdG9pKCZidWZmW2xlbi1udW1sZW5dKTsKCgkvKiBXUklURSAoSU9VVCwgJyhBLFQzMCxJNCknKSAnWWVhciBvZiBmaXJzdCBpbnB1dCBkYXRhJywgSU5JVFlSICovCglmcHJpbnRmKElPVVQsICAgIiUuKnMgJTRkXG4iLCBsZW4gLSBudW1sZW4sIGJ1ZmYsIElOSVRZUik7CglmcHJpbnRmKHN0ZG91dCwgIiUuKnMgJTRkXG4iLCBsZW4gLSBudW1sZW4sIGJ1ZmYsIElOSVRZUik7CgoJLyogUkVBRCAoSU4sICcoVDMwLEk0KScpIElZUkNMICovCglfZ2V0bGluZShidWZmLCBzaXplb2YoYnVmZiksIElOKTsKCW51bWxlbiA9IDQ7IGxlbiA9IHN0cmxlbihidWZmKTsKCUlZUkNMID0gYXRvaSgmYnVmZltsZW4tbnVtbGVuXSk7CgoJLyogV1JJVEUgKElPVVQsICcoQSwgVDMwLCBJNCknKSAnWWVhciBvZiBmaXJzdCBjYXRjaCBsaW1pdCcsIElZUkNMICovCglmcHJpbnRmKElPVVQsICAgIiUuKnMgJTRkXG4iLCBsZW4gLSBudW1sZW4sIGJ1ZmYsIElZUkNMKTsKCWZwcmludGYoc3Rkb3V0LCAiJS4qcyAlNGRcbiIsIGxlbiAtIG51bWxlbiwgYnVmZiwgSVlSQ0wpOwoKCS8qIFJFQUQgKElOLCAnKFQzMCwgSTQpJykgUE9VVCAqLwoJX2dldGxpbmUoYnVmZiwgc2l6ZW9mKGJ1ZmYpLCBJTik7CgludW1sZW4gPSA0OyBsZW4gPSBzdHJsZW4oYnVmZik7CglQT1VUID0gYXRvaSgmYnVmZltsZW4tbnVtbGVuXSk7CglpZiAoUE9VVCA9PSAxKSB7CgkJLyogV1JJVEUgKElPVVQsICcoQSwgVDMwLEE0KScpICdBcHBseSBwaGFzZW91dCBpZiBuZWNlc3NhcnknLCAnWUVTJyAqLwoJCWZwcmludGYoSU9VVCwgICAiQXBwbHkgcGhhc2VvdXQgaWYgbmVjZXNzYXJ5ICAgIFlFU1xuIik7CgkJZnByaW50ZihzdGRvdXQsICJBcHBseSBwaGFzZW91dCBpZiBuZWNlc3NhcnkgICAgWUVTXG4iKTsKCX0gZWxzZSB7CgkJLyogV1JJVEUgKElPVVQsICcoQSwgVDMwLEE0KScpICdBcHBseSBwaGFzZW91dCcsICdObycgKi8KCQlmcHJpbnRmKElPVVQsICAgIkFwcGx5IHBoYXNlb3V0ICAgICAgICAgICAgICAgICAgTm9cbiIpOwoJCWZwcmludGYoc3Rkb3V0LCAiQXBwbHkgcGhhc2VvdXQgICAgICAgICAgICAgICAgICBOb1xuIik7Cgl9CgovKiBSZS1zY2FsZSBJWVJDTCBzdWNoIHRoYXQgMCBpcyB0aGUgeWVhciBwcmlvciB0byB0aGUgZmlyc3QgaW5wdXQgZGF0YSAqLwoKCW1kLklTVEFSVCA9IDA7CgltZC5JWUVBUiA9IElZUkNMIC0gSU5JVFlSOwoJLyogSUYgKElZRUFSIC5MRS4gMCAuT1IuIElZRUFSIC5HVC4gTUFYWVIpIFNUT1AgJ0lOVkFMSUQgWUVBUicgKi8KCWlmICgobWQuSVlFQVIgPD0gMCkgfHwgKG1kLklZRUFSID4gTUFYWVIpKSB7CgkJZnByaW50ZihzdGRlcnIsICJJTlZBTElEIFlFQVIiKTsKCQlyZXQgPSAxOwoJCWdvdG8gZXhpdDsKCX0KCi8qIEluaXRpYWxpemUgdGhlIGNhdGNoIGFycmF5ICovCgoJLyogRE8gMTAgSSA9IDAsIE1BWFlSICovCglmb3IgKEkgPSAwOyBJIDw9IE1BWFlSOyBJKyspIHsKCQlDQVRDSFtJXSA9IDAuMDsKCX0gLyogMTAgICBDT05USU5VRSAqLwoKLyogUmVhZCBpbiB0aGUgY2F0Y2ggZGF0YSwgc2NhbGluZyBlYWNoIHllYXIgdG8gdGhlIGluaXRpYWwgeWVhciAqLwoJLyogUkVBRCAoSU4sICcoLy8gQSknKSBGT1JNVCAoSTQsRjguMCkgKi8KCV9nZXRsaW5lKGJ1ZmYsIHNpemVvZihidWZmKSwgSU4pOyAvKiBEaXNjYXJkIGVtcHR5IGxpbmVzICovCglfZ2V0bGluZShidWZmLCBzaXplb2YoYnVmZiksIElOKTsgLyogRGlzY2FyZCBlbXB0eSBsaW5lcyAqLwoJX2dldGxpbmUoYnVmZiwgc2l6ZW9mKGJ1ZmYpLCBJTik7IC8qIERpc2NhcmQgZW1wdHkgbGluZXMgKi8KCgkvKiBXUklURSAoSU9VVCwgJygvQSknKSAnSGlzdG9yaWMgY2F0Y2hlczonICovCglmcHJpbnRmKElPVVQsICJcbkhpc3RvcmljIGNhdGNoZXM6XG4iKTsKCWZwcmludGYoc3Rkb3V0LCAiXG5IaXN0b3JpYyBjYXRjaGVzOlxuIik7CglUT1RBTEMgPSAwOwoJLyogRE8gMjAgSSA9IDAsIE1BWFlSICovCglmb3IgKEkgPSAwOyBJIDw9IE1BWFlSOyBJKyspIHsKCQkvKiBSRUFEIChJTiwgRk9STVQpIElZLCBDICovIAoJCV9nZXRsaW5lKGJ1ZmYsIHNpemVvZihidWZmKSwgSU4pOwoJCXNzY2FuZihidWZmLCIlNGQlN2xmIiwgJklZLCAmQyk7CgkJLyogSUYgKElZIC5MVC4gMCkgR08gVE8gMjUgKi8KCQlpZiAoSVkgPCAwKSBicmVhazsgLyogRU9EICovCgoJCS8qIFdSSVRFIChJT1VULCBGT1JNVCkgSVksIEMgKi8KCQlmcHJpbnRmKHN0ZG91dCwgIiU0ZCU2LmZcbiIsIElZLCBDKTsKCQlmcHJpbnRmKElPVVQsICIlNGQlNi5mXG4iLCBJWSwgQyk7CgkJSVkgPSBJWSAtIElOSVRZUjsKCQkvKiBJRiAoSVkgLkxULiAwIC5PUi4gSVkgLkdFLiBJWUVBUikgU1RPUCAqLwoJCWlmIChJWSA8IDAgfHwgSVkgPiBtZC5JWUVBUikgewoJCQlmcHJpbnRmKHN0ZGVyciwgIiBFUlJPUjogSVkgaXMgb3V0IG9mIHJhbmdlKCVkKVxuIiwgSVkpOwoJCQlyZXQgPSAxOwoJCQlnb3RvIGV4aXQ7CgkJfQoJCUNBVENIW0lZXSA9IEM7CgkJVE9UQUxDID0gVE9UQUxDICsgQzsKCX0gLyogMjAgICBDT05USU5VRSAqLwoKLyogMjUgICBJRiAoVE9UQUxDIC5MVC4gMCkgU1RPUCAnIEVSUk9SOiBObyBoaXN0b3JpYyBjYXRjaCBpbnB1dCcgKi8KCWlmIChUT1RBTEMgPCAwKSB7CgkJZnByaW50ZihzdGRlcnIsICIgRVJST1I6IE5vIGhpc3RvcmljIGNhdGNoIGlucHV0XG4iKTsKCQlyZXQgPSAxOwoJCWdvdG8gZXhpdDsKCX0KCi8qIFJlYWQgaW4gdGhlIG5vbi16ZXJvIHNpZ2h0aW5ncyBlc3RpbWF0ZXMgYW5kIGluZm9ybWF0aW9uIG1hdHJpeCAqLwoKCS8qIFJFQUQgKElOLCAnKC8vVDMwLCBJNCAvIEEpJykgTlMsIEZPUk1UIChJNCxGMTAuMCwxMEY4LjApICovCglfZ2V0bGluZShidWZmLCBzaXplb2YoYnVmZiksIElOKTsgLyogRGlzY2FyZCBlbXB0eSBsaW5lcyAqLwoJX2dldGxpbmUoYnVmZiwgc2l6ZW9mKGJ1ZmYpLCBJTik7IC8qIERpc2NhcmQgZW1wdHkgbGluZXMgKi8KCV9nZXRsaW5lKGJ1ZmYsIHNpemVvZihidWZmKSwgSU4pOwoJbnVtbGVuID0gNDsgbGVuID0gc3RybGVuKGJ1ZmYpOwoJbWQuTlMgPSBhdG9pKCZidWZmW2xlbi1udW1sZW5dKTsKCgkvKiBXUklURSAoSU9VVCwgJygvQSknKSAnQWJ1bmRhbmNlIGVzdGltYXRlczonICovCglmcHJpbnRmKElPVVQsICAgIlxuQWJ1bmRhbmNlIGVzdGltYXRlczpcbiIpOwoJZnByaW50ZihzdGRvdXQsICJcbkFidW5kYW5jZSBlc3RpbWF0ZXM6XG4iKTsKCS8qIElGIChOUyAuR1QuIE1BWEVTVCkgU1RPUCAnRVJST1I6IEFidW5kYW5jZSB5ZWFyIG91dCBvZiByYW5nZScgKi8KCWlmIChtZC5OUyA+IE1BWEVTVCkgewoJCWZwcmludGYoc3RkZXJyLCAiRVJST1I6IEFidW5kYW5jZSB5ZWFyIG91dCBvZiByYW5nZVxuIik7CgkJcmV0ID0gMTsKCQlnb3RvIGV4aXQ7Cgl9CglfZ2V0bGluZShidWZmLCBzaXplb2YoYnVmZiksIElOKTsKCS8qIERPIDMwIE49MCwgTlMtMSAqLwoJZm9yIChOID0gMDsgTiA8PSBtZC5OUyAtIDE7IE4rKykgewoJCU4xID0gKE4gKiAoTiArIDEpKSAvIDI7CgkJLyogUkVBRCAoSU4sIEZPUk1UKSBJU1lSKE4pLCBTSUdIVChOKSwgKEZNQVRSWChOMSArIEopLCBKID0gMCwgTikgKi8KCQlfZ2V0bGluZShidWZmLCBzaXplb2YoYnVmZiksIElOKTsKCQlzc2NhbmYoYnVmZiwgIiU0ZCUxMGxmIiwgJklTWVJbTl0sICZTSUdIVFtOXSk7CgkJZnByaW50ZihJT1VULCAgICIlNGQgJTguZiIsIElTWVJbTl0sIFNJR0hUW05dKTsKCQlmcHJpbnRmKHN0ZG91dCwgIiU0ZCAlOC5mIiwgSVNZUltOXSwgU0lHSFRbTl0pOwoJCWxlbiA9IHN0cmxlbihidWZmKTsKCQlmb3IgKEogPSAwOyBKIDwgTiArIDE7IEorKykgewoJCQlpZiAobGVuID4gSiAqIDcgKyAxNCkgewoJCQkJc3NjYW5mKCZidWZmWzBdICsgSiAqIDcgKyAxNCwiJTdsZiIsICZGTUFUUlhbTjEgKyBKXSk7CgkJCX0gZWxzZSB7CgkJCQlGTUFUUlhbTjEgKyBKXSA9IDAuMDsKCQkJfQoJCQlmcHJpbnRmKElPVVQsICAgIiU3LmYiLCBGTUFUUlhbTjEgKyBKXSk7CgkJCWZwcmludGYoc3Rkb3V0LCAiJTcuZiIsIEZNQVRSWFtOMSArIEpdKTsKCQl9CgkJZnByaW50ZihJT1VULCAgICJcbiIpOwoJCWZwcmludGYoc3Rkb3V0LCAiXG4iKTsKCQkvKiBXUklURSAoSU9VVCwgRk9STVQpIElTWVIoTiksIFNJR0hUKE4pLCAoRk1BVFJYIChOMSArIEopLCBKID0gMCwgTikgKi8KCQlJU1lSW05dID0gSVNZUltOXSAtIElOSVRZUjsKCQlpZiAoSVNZUltOXSA8IDAgfHwgSVNZUltOXSA+PSBtZC5JWUVBUikgewoJCQkvKlNUT1AgJ0VSUk9SOiBTaWdodCB5ZWFyIG91dCBvZiByYW5nZScqLwoJCQlmcHJpbnRmKHN0ZGVyciwgIkVSUk9SOiBTaWdodCB5ZWFyIG91dCBvZiByYW5nZVxuIik7CgkJCXJldCA9IDE7CgkJCWdvdG8gZXhpdDsKCQl9CgkJaWYgKFNJR0hUW05dIDw9IDAuMCkgewoJCQkvKiBTVE9QICcgRVJST1I6IEVzdGltYXRlIG5vdCBwb3NpdGl2ZScgKi8KCQkJZnByaW50ZihzdGRlcnIsICJFUlJPUjogRXN0aW1hdGUgbm90IHBvc2l0aXZlXG4iKTsKCQkJcmV0ID0gMTsKCQkJZ290byBleGl0OwoJCX0KCX0gLyogMzAgICBDT05USU5VRSAqLwoKLyogUmVhZCBpbiB0aGUgUG9pc3NvbiBtdWx0aXBsaWVycyBmb3IgYW55IHplcm8gc2lnaHRpbmdzIGVzdGltYXRlcyAqLwoKCS8qIFJFQUQgKElOLCAnKC9UMzAsIEkzLCAvQSknKSBOWiwgRk9STUFUICovCglfZ2V0bGluZShidWZmLCBzaXplb2YoYnVmZiksIElOKTsKCV9nZXRsaW5lKGJ1ZmYsIHNpemVvZihidWZmKSwgSU4pOwoJbnVtbGVuID0gMzsgbGVuID0gc3RybGVuKGJ1ZmYpOwoJbWQuTlogPSBhdG9pKCZidWZmW2xlbi1udW1sZW5dKTsKCWlmIChtZC5OWiA+IDApIHsKCQkvKiBXUklURSAoSU9VVCwgJygvQSknKSAnWmVybyBhYnVuZGFuY2UgZXN0aW1hdGVzOicgKi8KCQlmcHJpbnRmKElPVVQsICAgIlxuWmVybyBhYnVuZGFuY2UgZXN0aW1hdGVzOlxuIik7CgkJZnByaW50ZihzdGRvdXQsICJcblplcm8gYWJ1bmRhbmNlIGVzdGltYXRlczpcbiIpOwoJfQoJaWYgKG1kLk5aID4gTUFYRVNUKSB7CgkJLyogU1RPUCAnIEVSUk9SOiBaZXJvIGVzdGltYXRlIGFycmF5IHRvbyBzbWFsbCcgKi8KCQlmcHJpbnRmKHN0ZGVyciwgIkVSUk9SOiBaZXJvIGVzdGltYXRlIGFycmF5IHRvbyBzbWFsbFxuIik7CgkJcmV0ID0gMTsKCQlnb3RvIGV4aXQ7Cgl9CglfZ2V0bGluZShidWZmLCBzaXplb2YoYnVmZiksIElOKTsKCS8qIERPIDQwIE4gPSAwLCBOWiAtIDEgKi8KCWZvciAoTiA9IDA7IE4gPD0gbWQuTlogLSAxOyBOKyspIHsKCQlOMSA9IChOICogKE4gKyAxKSkgLyAyOwoJCS8qUkVBRCAoSU4sIEZPUk1UKSBJWllSKE4pLCBaTVVMVChOKSovCgkJX2dldGxpbmUoYnVmZiwgc2l6ZW9mKGJ1ZmYpLCBJTik7CgkJc3NjYW5mKGJ1ZmYsICIlNGQlMTBsZiIsICZJWllSW05dLCAmWk1VTFRbTl0pOwoJCS8qIFdSSVRFIChJT1VULCBGT1JNVCkgSVpZUihOKSwgWk1VTFQoTikgKi8KCQlmcHJpbnRmKElPVVQsICAgIiU0ZCU3LmZcbiIsIElaWVJbTl0sIFpNVUxUW05dKTsKCQlmcHJpbnRmKHN0ZG91dCwgIiU0ZCU3LmZcbiIsIElaWVJbTl0sIFpNVUxUW05dKTsKCQlJWllSW05dID0gSVpZUltOXSAtIElOSVRZUjsKCQlpZiAoSVpZUltOXSA8IDAgfHwgSVpZUltOXSA+PSBtZC5JWUVBUikgewoJCQkvKiBTVE9QICcgU2lnaHQgeWVhciBvdXQgb2YgcmFuZ2UnICovCgkJCWZwcmludGYoc3RkZXJyLCAiU2lnaHQgeWVhciBvdXQgb2YgcmFuZ2VcbiIpOwoJCQlyZXQgPSAxOwoJCQlnb3RvIGV4aXQ7CgkJfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKCQlpZiAoWk1VTFRbTl0gPD0gMC4wKSB7CgkJCS8qIFNUT1AgJyBFUlJPUjogTXVsdGlwbGllciBub3QgcG9zaXRpdmUnICovCgkJCWZwcmludGYoc3RkZXJyLCAiRVJST1I6IE11bHRpcGxpZXIgbm90IHBvc2l0aXZlXG4iKTsKCQkJcmV0ID0gMTsKCQkJZ290byBleGl0OwoJCX0KCX0gLyogNDAgICBDT05USU5VRSAqLwoJLypXUklURSAoSU9VVCwgJygpJykqLwoJZnByaW50ZihJT1VULCJcbiIpOwoJZnByaW50ZihzdGRvdXQsIlxuIik7Ci8qIEJvdW5kIHRoZSByYW5nZSBmb3IgdGhlIGludGVncmF0aW9uIG92ZXIgSyAqLwoKCW1kLlJLSEkgPSAxLjBFNzsKCW1kLlJLTE8gPSAwLjA7CglJUyA9IDA7IC8qIG9yaWduYWwgbm90IGluaXRpYWxpemVkIGJ1Zz8gKi8KLyogKioqKioqICovCi8qICoqKioqKiBSdW4gdGhlIENMQSB0byBvYnRhaW4gdGhlIG5vbWluYWwgY2F0Y2ggbGltaXQgKi8KLyogKioqKioqICovCglSQVdDTCA9IENMSU1JVChDQVRDSCwgU0lHSFQsIEZNQVRSWCwgSVNZUiwgSVpZUiwgWk1VTFQsIFBPUCwgRyk7Ci8qIFNldCB0aGUgY2F0Y2ggbGltaXRzIGZvciBQQ1lDTEUgeWVhcnMuIElmIHRoZSBjYXRjaCBsaW1pdCBtYXkgYmUgKi8KLyogc3ViamVjdCB0byBwaGFzZW91dCwgY2FsbCBQT1VUIHRvIGFwcGx5IHRoZSBwaGFzZW91dCBydWxlLiAqLwoKLyogRmlyc3Qgc2V0IElMQVNUID0geWVhciBvZiB0aGUgbW9zdCByZWNlbnQgYWJ1bmRhbmNlIGVzdGltYXRlICovCgoJaWYgKG1kLk5TID4gMCkgSUxBU1QgPSBJU1lSW21kLk5TIC0gMV07CgkvKiBJRiAoTlogLkdULiAwKSBJTEFTVCA9IE1BWChJUywgSVpZUihtZC5OWiAtIDEpKSAqLwoJaWYgKG1kLk5aID4gMCkgSUxBU1QgPSAoSVMgPiBJWllSW21kLk5aIC0gMV0pPyBJUzogSVpZUlttZC5OWiAtIDFdOwoKCS8qIERPIDEwMCBJWSA9IElZRUFSLCBJWUVBUiArIG1wLlBDWUNMRSAtIGYxICovCglmb3IgKElZID0gbWQuSVlFQVI7IElZIDw9IG1kLklZRUFSICsgbXAuUENZQ0xFIC0gMTsgSVkrKykgewoJCWlmIChQT1VUID09IDEpIHsKCQkJUEhPVVQoJkNMLCBSQVdDTCwgSUxBU1QsIElZKTsKCQl9IGVsc2UgewoJCQlDTCA9IFJBV0NMOwoJCX0KCQkvKiBXUklURSAoSU9VVCwgJyhBNiwgSTUsIEExNywgSTYpJykgJ1llYXI6JywgSVkgKyBJTklUWVIsJ0NhdGNoIGxpbWl0OicsIE5JTlQoQ0wpICovCgkJZnByaW50ZihJT1VULCAgICJZZWFyOiAlNGQgICAgIENhdGNoIGxpbWl0OiU2ZFxuIiwgSVkgKyBJTklUWVIsIChpbnQpKENMICsgMC41KSk7CgkJZnByaW50ZihzdGRvdXQsICJZZWFyOiAlNGQgICAgIENhdGNoIGxpbWl0OiU2ZFxuIiwgSVkgKyBJTklUWVIsIChpbnQpKENMICsgMC41KSk7CgoJfSAvKiAxMDAgIENPTlRJTlVFICovCgpleGl0OgoJaWYgKElOICE9IE5VTEwpICAgZmNsb3NlKElOKTsKCWlmIChJT1VUICE9IE5VTEwpIGZjbG9zZShJT1VUKTsKCXJldHVybiByZXQ7CgkvKglTVE9QICovCgkvKglFTkQgICovCn0KCi8qCkMgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKQwpDCUNMQyB2ZXJzaW9uIDYKQwpDICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCkMKQwkzMSBKYW51YXJ5IDE5OTQKQwpDICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiovCi8qCglTVUJST1VUSU5FIFJEUEFSUwoJUmVhZCB0aGUgZmlsZSBvZiBpbnB1dCBwYXJhbWV0ZXJzCiovCnZvaWQgUkRQQVJTKHZvaWQpCnsKCWRvdWJsZSAqcFtdID0gewoJCSZtcC5QUFJPQiwgJm1wLlBZTUFYLCAmbXAuUE5ZU1RQLCZtcC5QS1NURVAsICZtcC5QRFNURVAsICZtcC5QQk1JTiwgJm1wLlBCTUFYLAoJCSZtcC5QTkJTVFAsICZtcC5QU0NBTEUsICZtcC5QSEFTRVQsICZtcC5QSEFTRVAsICZtcC5QQ1lDTEUsICZtcC5QTEVWRUwsICZtcC5QU0xPUEUKCX07CglGSUxFICpJRklMRTsKCWNoYXIgYnVmZls4MF07CglpbnQgY291bnQ7CgkKCS8qIE9wZW4gdGhlIGlucHV0IGZpbGUgKG9ubHkgcmVhZCBvbmNlKSAqLwoJSUZJTEUgPSBmb3BlbihDTENQQVIsICJydCIpOwoJaWYgKElGSUxFID09IE5VTEwpIHsKCQlmcHJpbnRmKHN0ZGVyciwiQ2FuJ3Qgb3BlbiAiIENMQ1BBUiAiXG4iKTsKCQlleGl0KDEpOwoJfQoJY291bnQgPSAwOwoJd2hpbGUgKF9nZXRsaW5lKGJ1ZmYsIHNpemVvZihidWZmKSwgSUZJTEUpICE9IDApIHsKCQkvKiBSRUFEIChJRklMRSwgJyhUMzAsIEYxMC4wKScpIFBQUk9CLCBQWU1BWCwgUE5ZU1RQLCBQS1NURVAsIFBEU1RFUCwgUEJNSU4sIFBCTUFYLAoJCQkJCQkJCSBQTkJTVFAsIFBTQ0FMRSwgUEhBU0VULCBQSEFTRVAsIFBDWUNMRSwgUExFVkVMLCBQU0xPUEUgKi8KCQlzc2NhbmYoYnVmZiwiJSoyOGMlbGYiLCBwW2NvdW50XSk7CgkJY291bnQrKzsKCX0KCS8qIENMT1NFIChJRklMRSkgKi8KCWZjbG9zZShJRklMRSk7CglyZXR1cm47CgkvKiBSRVRVUk4KCSAgIEVORCAqLwp9CgovKgoJU1VCUk9VVElORSBQSE9VVCAoQ0wsIFJBV0NMLCBJTEFTVCwgSVkpCiovCnZvaWQgUEhPVVQoZG91YmxlICpDTCwgZG91YmxlIFJBV0NMLCBpbnQgSUxBU1QsIGludCBJWSkKewovKgoJUEhBU0VUIE51bWJlciBvZiB5ZWFycyB3aXRob3V0IHN1cnZleXMgYmVmb3JlIHBoYXNlb3V0IGludm9rZWQKCVBIQVNFUCBQaGFzZW91dCBhbm51YWwgcmVkdWN0aW9uIHByb3BvcnRpb24KCVBoYXNlb3V0OiBSZWR1Y2UgY2F0Y2ggbGltaXQgaWYgdGhlcmUgaXMgbm8gc3VydmV5IGRhdGEgaW4gdGhlCglsYXN0IFBIQVNFVCB5ZWFycwoqLwoJaWYgKElZID49IElMQVNUICsgbXAuUEhBU0VUKSB7CgkJKkNMID0gUkFXQ0wgKiAoMS4wIC0gbXAuUEhBU0VQICogKElZIC0gSUxBU1QgLSBtcC5QSEFTRVQpKTsKCQlpZiAoKkNMIDwgMC4wKSAqQ0wgPSAwLjA7Cgl9IGVsc2UgewoJCSpDTCA9IFJBV0NMOwoJfQoJLyogUkVUVVJOCgkgICBFTkQgKi8KfQoKLyoKCVJFQUwgRlVOQ1RJT04gQ0xJTUlUIChDQVRDSCxTSUdIVCxGTUFUUlgsSVNZUixJWllSLFpNVUxULFBPUCxHKQoJUnVuIHRoZSBDTEEgdG8gb2J0YWluIHRvIG5vbWluYWwgY2F0Y2ggbGltaXQKKi8KZG91YmxlIENMSU1JVChkb3VibGUgKkNBVENILCBkb3VibGUgKlNJR0hULCBkb3VibGUgKkZNQVRSWCwgaW50ICpJU1lSLCBpbnQgKklaWVIsIGRvdWJsZSAqWk1VTFQsZG91YmxlICpQT1AsIGRvdWJsZSAqRykKewovKgoJTG9jYWwgdmFyaWFibGVzOiAKCglSRUFMIFBSRVMoMDpNQVhTSU0pLCBRUkVTKDA6TUFYU0lNKSwgU1MwLCBTUzEsIFNTMiwgU1MzCglSRUFMIFNGLCBZKDA6TUFYU1RQKSwgQigwOk1BWFNUUCksIFJMR0IoMDpNQVhTVFApCglJTlRFR0VSIE5CLCBOUgoJTkIJTnVtYmVyIG9mIGJpYXMgc3RlcHMKCU5SCU51bWJlciBvZiBzdGVwcyBmb3IgWSAodGhlIHByb2R1Y3Rpdml0eSBwYXJhbWV0ZXIpCglTRglEZXZpYW5jZSBzY2FsZSBmYWN0b3IgKFNGID0gLjUgLyBQU0NBTEUqKjIpCiovCglkb3VibGUgU0YsIFNTMCwgU1MxLCBTUzIsIFNTMzsKCWRvdWJsZSBZW01BWFNUUCArIDFdLCBCW01BWFNUUCArIDFdLCBSTEdCW01BWFNUUCArIDFdOwoJZG91YmxlICpQUkVTID0gTlVMTCwgKlFSRVMgPSBOVUxMOwoKCWludCBOQiwgTlI7Cglkb3VibGUgQklOQywgWUlOQywgREssIFIsIFJLLCBELCBERCwgUCwgUSwgUFRPVDsKCWludCBJLCBKLCBOLCBOMjsKCglkb3VibGUgX0NMSU1JVCA9IDAuMDsKCWlmIChtZC5OUyA8PSAwKSByZXR1cm4gX0NMSU1JVDsKCglQUkVTID0gKGRvdWJsZSAqKSBtYWxsb2Moc2l6ZW9mKGRvdWJsZSkgKiAoTUFYU0lNICsgMSkpOwoJaWYgKFBSRVMgPT0gTlVMTCkgewoJCWZwcmludGYoc3RkZXJyLCAiQ2FuJ3QgQWxsb2NhdGUgbWVtb3J5IChQUkVTKVxuIik7CgkJZ290byBlcnJfZXhpdDsKCX0KCW1lbXNldChQUkVTLCAwLCBzaXplb2YoZG91YmxlKSAqIChNQVhTVFAgKyAxKSk7CgoJUVJFUyA9IChkb3VibGUgKikgbWFsbG9jKHNpemVvZihkb3VibGUpICogKE1BWFNJTSArIDEpKTsKCWlmIChRUkVTID09IE5VTEwpIHsKCQlmcHJpbnRmKHN0ZGVyciwgIkNhbid0IEFsbG9jYXRlIG1lbW9yeSAoUVJFUylcbiIpOwoJCWdvdG8gZXJyX2V4aXQ7Cgl9CgltZW1zZXQoUVJFUywgMCwgc2l6ZW9mKGRvdWJsZSkgKiAoTUFYU1RQICsgMSkpOwoKCS8qIFNldCBkZXZpYW5jZSBzY2FsZSBmYWN0b3IgUyA9IDEvUFNDQUxFKioyICovCglTRiA9IDAuNSAvIChtcC5QU0NBTEUgKiBtcC5QU0NBTEUpOwoKCS8qIENoZWNrIHRoZSBzaXplcyBvZiB0aGUgWSBhbmQgQiBhcnJheXMgYXJlIGxhcmdlIGVub3VnaCAqLwoJaWYgKG1wLlBOQlNUUCA+IE1BWFNUUCB8fCBtcC5QTllTVFAgPiBNQVhTVFApIHsKCQlmcHJpbnRmKHN0ZGVyciwgIlkgJi9vciBiIGFycmF5IHNpemVzIHRvbyBzbWFsbFxuIik7CgkJZ290byBlcnJfZXhpdDsKCX0KCS8qIFNldCBzaWdodGluZ3MgYmlhcyBzdGVwIHNpemVzICYgdGhlaXIgbG9nIHZhbHVlcy4gQklOQyA9IEJpYXMgaW5jcmVtZW50ICovCglOQiA9IChpbnQpbXAuUE5CU1RQOwoJQklOQyA9IChtcC5QQk1BWCAtIG1wLlBCTUlOKSAvIE5COwoJLyogRE8gMTAgSSA9IDAsIE5CIC0gMSAqLwoJZm9yIChJID0gMDsgSSA8PSBOQiAtIDE7IEkrKykgewogICAgICAgICooQiArIEkpID0gbXAuUEJNSU4gKyAoSSArIDAuNSkgKiBCSU5DOwogICAgICAgICooUkxHQiArIEkpID0gLWxvZygqKEIgKyBJKSk7Cgl9IC8qIDEwICAgQ09OVElOVUUgKi8KCgkvKiBTZXQgcHJvZHVjdGl2aXR5IHBhcmFtZXRlciBzdGVwIHNpemVzIChtaWRwb2ludHMpICovCglOUiA9IChpbnQpbXAuUE5ZU1RQOwoJWUlOQyA9IG1wLlBZTUFYIC8gTlI7CgkvKiBETyAyMCBJID0gMCwgTlIgLSAxICovCglmb3IgKEkgPSAwOyBJIDw9IE5SIC0gMTsgSSsrKSB7CgkJKihZICsgSSkgPSAoSSArIDAuNSkgKiBZSU5DOwoJfS8qIDIwICAgQ09OVElOVUUgKi8KCglQVE9UID0gMDsKCU4gPSAwOwoJLyogRE8gNTAgSSA9IDAsIE5SIC0gMSAqLwoJZm9yIChJID0gMDsgSSA8PSBOUiAtIDE7IEkrKykgewoJCS8qIFNldCBSIGZyb20gdGhlIHByb2R1Y3Rpdml0eSBwYXJhbWV0ZXIsIFkgKi8KCQlSID0gMS40MTg0ICogKihZICsgSSk7CgoJCS8qIFN0ZXAgc2l6ZSBmb3IgSyAqLwogICAgICAgIERLID0gbXAuUEtTVEVQOwogICAgICAgIEQgPSAxLjA7CiAgICAgICAgUksgPSBtZC5SS0hJOwoKCQkvKiBVc2UgZnVuY3Rpb24gU1RLU0lNIHRvIHNldCB1cCB0aGUgTnRoIHBvcHVsYXRpb24gdHJhamVjdG9yeSAqLwoJCS8qIGkuZS4gc2V0IHVwIHRoZSBwb3AgYXJyYXkgKi8KCgkJd2hpbGUgKDEpIHsKCQkvKiAzMCAgICAgSUYgKFJLIC5MRS4gUktMTyAuT1IuIFNUS1NJTSAoUkssIFIsIFBPUCwgQ0FUQ0gpIC5MRS4gMC4pIEdPVE8gNDAgKi8KCQkJaWYgKChSSyA8PSBtZC5SS0xPKSB8fCAoU1RLU0lNKFJLLCBSLCBQT1AsIENBVENIKSA8PSAwLjApKSBicmVhazsKCQkJLyogSUYgKE4gLkdFLiBNQVhTSU0pIFNUT1AgJ0VSUk9SOiBUT08gTUFOWSBTSU1VTEFUSU9OUycgKi8KCQkJaWYgKE4gPj0gTUFYU0lNKSB7CgkJCQlmcHJpbnRmKHN0ZGVyciwgIkVSUk9SOiBUT08gTUFOWSBTSU1VTEFUSU9OUyIpOwoJCQkJZ290byBlcnJfZXhpdDsKCQkJfQoJCQkvKiBIb3cgbXVjaCBkZXBsZXRpb24gY292ZXJlZD8gKi8KCQkJREQgPSBEIC0gUE9QW21kLklZRUFSXSAvIFJLOwoJCQlEID0gUE9QW21kLklZRUFSXSAvIFJLOwoJCQlQID0gMC4wOwoKCQkJaWYgKEREID4gMC4wKSB7CgkJCQkvKiBDb21wdXRlIHRoZSBpbnRlcm5hbCBjYXRjaCBsaW1pdCBjb3JyZXNwb25kaW5nIHRvIEQgYW5kIFkoSSkgKi8KCQkJCVFSRVNbTl0gPSBDT05UUkwoRCwgWVtJXSwgbXAuUExFVkVMLCBtcC5QU0xPUEUpICogUE9QW21kLklZRUFSXTsKCgkJCQkvKiBDYWxjdWxhdGUgZGV2aWFuY2UgKi8KICAgICAgICAgICAgCURFVklBTigmU1MwLCAmU1MxLCAmU1MyLCAmU1MzLCBTSUdIVCwgRk1BVFJYLCBJU1lSLElaWVIsIFpNVUxULCBQT1AsIEcpOwoKCQkJCS8qIFNjYWxlIGxpa2VsaWhvb2QgYW5kIGludGVncmF0ZSBvdmVyIHZhbHVlcyBmb3IgdGhlIGJpYXMgcGFyYW1ldGVyICovCgkJCQkvKiBETyAzNSBKID0gMCwgTkIgLSAxICovCgkJCQlmb3IgKEogPSAwOyBKIDw9IE5CIC0gMTsgSisrKSB7CgkJCQkJUCA9IFAgKyBleHAoLVNGICogKFNTMCArICooUkxHQiArIEopICogKFNTMSArICooUkxHQiArIEopICogU1MyKSArIFNTMyAqICooQiArIEopKSk7CgkJCQl9IC8qIDM1ICAgICAgICAgQ09OVElOVUUgKi8KCgkJCQkvKiBDYWxjdWxhdGUgdGhlIHdlaWdodCBmb3IgdGhpcyBwb2ludCAoJiB0b3RhbCBhcmVhIHVuZGVyIGxpa2VsaWhvb2QpICovCgkJCQlQUkVTW05dID0gUCAqIEREOwoJCQkJUFRPVCA9IFBUT1QgKyBQUkVTW05dOwoKCQkJCS8qIFVwZGF0ZSBjb3VudGVyICovCgkJCQlOID0gTiArIDE7CgoJCQkJLyogRmluZCB0aGUgbmV4dCBLICovCgkJCQlESyA9IERLICogbXAuUERTVEVQIC8gREQ7CgkJCQkvKiBJRiAoREsgLkdULiBQS1NURVApIERLID0gUEtTVEVQICovCgkJCQlpZiAoREsgPiBtcC5QS1NURVApIERLID0gbXAuUEtTVEVQOwoKCQkJfSBlbHNlIHsKCQkJCS8qIElGIEREID0gMCBjaGFuZ2UgdGhlIHN0ZXAgc2l6ZSBvbmx5ICovCgkJCQlESyA9IG1wLlBLU1RFUDsKCQkJfQoJCQkvKiBTZXQgdGhlIG5ldyB2YWx1ZSBvZiBLICovCgkJCVJLID0gUksgLyAoMS4wICsgREspOwoJCX0gLyogR09UTyAzMCAqLyAvKiA0MCAgICAgQ09OVElOVUUgKi8KCX0gLyogNTAgICBDT05USU5VRSAqLwoJLyogSUYgKFBUT1QgLkxFLiAwLikgU1RPUCAnRVJST1I6IFBST0IgSU5URUdSQVRFUyBUTyBaRVJPJyAqLwoJaWYgKFBUT1QgPCAwLjApIHsKCQlmcHJpbnRmKHN0ZGVyciwiRVJST1I6IFBST0IgSU5URUdSQVRFUyBUTyBaRVJPIik7CgkJZ290byBlcnJfZXhpdDsKCX0KCgkvKiBTb3J0IHRoZSBRUkVTIGFuZCBQUkVTIGFycmF5cyBpbiBhc2NlbmRpbmcgb3JkZXIgb2YgUVJFUyAqLwoJTjIgPSBOOwoJU09SVChRUkVTLCBQUkVTLCBOMik7CgoJLyogTm9ybWFsaXplIHRoZSByZWxhdGl2ZSBsaWtlbGlob29kcyAqLwoJLyogRE8gNjAgSSA9IDAsIE4gLSAxICovCglmb3IgKEkgPSAwOyBJIDw9IE4gLSAxOyBJKyspIHsKCQlQUkVTW0ldID0gUFJFU1tJXSAvIFBUT1Q7Cgl9IC8qIDYwICAgQ09OVElOVUUgKi8KCgkvKiBFeHRyYWN0IHRoZSBkZXNpcmVkIHByb2JhYmlsaXR5IGxldmVsOiB0aGUgbm9taW5hbCBjYXRjaCBsaW1pdCAoTkNMKSAqLwoJLyogaXMgdGhlIGxvd2VyIFBST0IlIG9mIHRoZSBkaXN0cmlidXRpb24uICovCgkvKiBGaXJzdCBjYWxjdWxhdGUgUFJFUyhJKSwgdGhlIHByb2JhYmlsaXR5IHRoYXQgdGhlIE5DTCBpcyBiZXR3ZWVuICovCgkvKiBRUkVTKEkpICYgUVJFUyhJICsgMSkuICovCgoJUCA9IDA7CgkvKiBETyA3MCBJID0gMCwgTiAtIDEgKi8KCWZvciAoSSA9IDA7IEkgPD0gTiAtIDE7IEkrKykgewoJCVAgPSBQICsgUFJFU1tJXTsKCQkvKiBJRiAoUCAuR1QuIFBQUk9CKSBHT1RPIDgwICovCgkJaWYgKFAgPiBtcC5QUFJPQikgYnJlYWs7Cgl9IC8qIDcwICAgQ09OVElOVUUgKi8KCgkvKiBJbnRlcnBvbGF0ZSB0byBzZXQgdGhlIG5vbWluYWwgY2F0Y2ggbGltaXQgKi8KCS8qIDgwICAgSUYgKEkgLkdFLiBOIC0gMSkgVEhFTiAqLwoJaWYgIChJID49IE4gLSAxKSB7CiAgICAgICAgUSA9IFFSRVNbTiAtIDFdOwoJfSBlbHNlIHsKICAgICAgICBRID0gKFFSRVNbSSArIDFdICogKG1wLlBQUk9CIC0gUCArIFBSRVNbSV0pICsgUVJFU1tJXSAqIChQIC0gbXAuUFBST0IpKSAvIFBSRVNbSV07Cgl9CgoJX0NMSU1JVCA9IFE7CgoJaWYgKFFSRVMgIT0gTlVMTCkgZnJlZShRUkVTKTsKCWlmIChQUkVTICE9IE5VTEwpIGZyZWUoUFJFUyk7Ci8qCWlmIChZICE9IE5VTEwpIGZyZWUoWSk7CglpZiAoQiAhPSBOVUxMKSBmcmVlKEIpOwoJaWYgKFJMR0IgIT0gTlVMTCkgZnJlZShSTEdCKTsqLwoJcmV0dXJuIF9DTElNSVQ7CgplcnJfZXhpdDoKCWlmIChRUkVTICE9IE5VTEwpIGZyZWUoUVJFUyk7CglpZiAoUFJFUyAhPSBOVUxMKSBmcmVlKFBSRVMpOwovKglpZiAoWSAhPSBOVUxMKSBmcmVlKFkpOwoJaWYgKEIgIT0gTlVMTCkgZnJlZShCKTsKCWlmIChSTEdCICE9IE5VTEwpIGZyZWUoUkxHQik7Ki8KCWV4aXQoMSk7CglyZXR1cm4gMC4wOyAvKiBub3QgcmVhY2hlZCAqLwoJLyogUkVUVVJOICovCgkvKiBFTkQgKi8KfQoKLyoKCUZVTkNUSU9OIENPTlRSTCAoRCwgWSwgUExFVkVMLCBQU0xPUEUpCglDYXRjaCBjb250cm9sIGxhdwoqLwpkb3VibGUgQ09OVFJMKGRvdWJsZSBELCBkb3VibGUgWSwgZG91YmxlIFBMRVZFTCwgZG91YmxlIFBTTE9QRSkKewoJZG91YmxlIHJldDsKCWlmIChEIDwgUExFVkVMKSB7CgkJcmV0ID0gMC4wOwoJfSBlbHNlIGlmIChEIDwgMS4wKSB7CgkJcmV0ID0gUFNMT1BFICogWSAqIChEIC0gUExFVkVMKTsKCX0gZWxzZSB7CgkJcmV0ID0gUFNMT1BFICogWSAqICgxLjAgLSBQTEVWRUwpOwoJfQoJcmV0dXJuIHJldDsKCS8qIEVORCAqLwp9CgovKgoJU1VCUk9VVElORSBERVZJQU4gKFNTMCwgU1MxLCBTUzIsIFNTMywgU0lHSFQsIEZNQVRSWCwgSVNZUiwKCUNhbGN1bGF0ZSBkZXZpYW5jZSAoLTIgbG9nIGxpa2VsaWhvb2QpIGluIHRlcm1zIG9mIGNvZWZmaWNpZW50cyBmb3IgCgl0aGUgYmlhcyBhbmQgbG9nIGJpYXMgcGFyYW1ldGVycwoqLwp2b2lkIERFVklBTihkb3VibGUgKlNTMCwgZG91YmxlICpTUzEsIGRvdWJsZSAqU1MyLCBkb3VibGUgKlNTMywgZG91YmxlICpTSUdIVCwKICAgICAgICAgICAgZG91YmxlICpGTUFUUlgsIGludCAqSVNZUiwgaW50ICpJWllSLCBkb3VibGUgKlpNVUxULCBkb3VibGUgKlBPUCwgZG91YmxlICpHKQp7CgkvKiBSRUFMIFNTMCxTUzEsU1MyLFNJR0hUKDA6KiksRk1BVFJYKDA6KiksWk1VTFQoMDoqKSxQT1AoMDoqKSxHKDA6KikgKi8KCS8qIElOVEVHRVIgSVNZUigwOiopLCBJWllSKDA6KikgKi8KCWludCBOLCBKLCBLOwoKCSpTUzAgPSAwLjA7CgkqU1MxID0gMC4wOwoJKlNTMiA9IDAuMDsKCSpTUzMgPSAwLjA7CgoJLyogRE8gMTAwIE4gPSAwLCBOUyAtIDEgKi8KCWZvciAoTiA9IDA7IE4gPD0gbWQuTlMgLSAxOyBOKyspIHsgCgoJCSooRyArIE4pID0gbG9nKCooU0lHSFQgKyBOKSAvICooUE9QKyooSVNZUiArIE4pKSk7CgkJSyA9IE4gKiAoTiArIDEpIC8gMjsKCgkJLyogRE8gMTAgSiA9IDAsIE4gLSAxICovCgkJZm9yIChKID0gMDsgSiA8PSBOIC0gMTsgSisrKSB7CgkJCS8qMXN0IGFkZCBub24gZGlhZ29uYWwgY29udHJpYnV0aW9ucyAod2hpY2ggYXJlIGRvdWJsZWQgdXApKi8KCQkJKlNTMCA9ICpTUzAgKyAyLjAgKiAqKEcgKyBKKSAqICooRyArIE4pICogKihGTUFUUlggKyBLKTsKCQkJKlNTMSA9ICpTUzEgKyAyLjAgKiAoKihHICsgSikgKyAqKEcgKyBOKSkgKiAqKEZNQVRSWCArIEspOwoJCQkqU1MyID0gKlNTMiArICooRk1BVFJYICsgSykgKyAqKEZNQVRSWCArIEspOwoJCQlLID0gSyArIDE7CgkJfSAvKiAxMCAgICAgQ09OVElOVUUqLwoKCQkvKiBOb3cgYWRkIGRpYWdub2FsIGNvbnRyaWJ1dGlvbiAqLwogICAgICAgICpTUzAgPSAqU1MwICsgKihHICsgTikgKiAqKEcgKyBOKSAqICooRk1BVFJYICsgSyk7CiAgICAgICAgKlNTMSA9ICpTUzEgKyAyLjAgKiAqKEcgKyBOKSAqICooRk1BVFJYICsgSyk7CiAgICAgICAgKlNTMiA9ICpTUzIgKyAqKEZNQVRSWCArIEspOwoKCX0gLyogMTAwICBDT05USU5VRSAqLwoKCS8qIE5vdyBkbyB0aGUgemVybyBlc3RpbWF0ZXMgKi8KCS8qIERPIDIwMCBOID0gMCwgTlogLSAxICovCglmb3IgKE4gPTA7IE4gPD0gbWQuTlogLSAxOyBOKyspIHsKCQkqU1MzID0gKlNTMyArIDIuMCAqICooUE9QICsgKihJWllSICsgTikpIC8gKihaTVVMVCArIE4pOwogCX0gLyogMjAwICBDT05USU5VRSAqLwoKCS8qIFJFVFVSTiAqLwoJLyogRU5EICAgICovCglyZXR1cm47Cn0KLyoKCUZVTkNUSU9OIFNUS1NJTSAoUkssIFIsIFBPUCwgQ0FUQ0gpCglDYWxjdWxhdGUgdGhlIHN0b2NrIHRyYWplY3Rvcnkgd2l0aCBwYXJhbWV0ZXIgUksgYW5kIFI6IHJldHVybgoJdGhlIGN1cnJlbnQgc3RvY2sgc2l6ZQoJUksgPSBub3Rpb25hbCBjYXJyeWluZyBjYXBhY2l0eTsgUiA9IHByb2R1Y3Rpdml0eSBwYXJhbWV0ZXIgKiAxLjQxODQgCiovCmRvdWJsZSBTVEtTSU0oZG91YmxlIFJLLCBkb3VibGUgUiwgZG91YmxlICpQT1AsIGRvdWJsZSAqQ0FUQ0gpCnsKCS8qSU5URUdFUiBJU1RBUlQsIElZRUFSLCBOUywgTlosIFJLTE8sIFJLSEkgKi8KCS8qIFJFQUwgQ0FUQ0goMDoqKSwgUE9QKDA6KikgKi8KCWludCBJOwoJZG91YmxlIEQ7CgkqKFBPUCttZC5JU1RBUlQpID0gUks7CgkvKkRPIDEwIEkgPSBtZC5JU1RBUlQgKyAxLCBtZC5JWUVBUiovCglmb3IgKEkgPSBtZC5JU1RBUlQgKyAxOyBJIDw9IG1kLklZRUFSOyBJKyspIHsKCQlEID0gKihQT1AgKyBJIC0gMSkgLyBSSzsKCQkqKFBPUCArIEkpID0gKihQT1AgKyBJIC0gMSkgKiAoMS4wICsgUiAqICgxLjAgLSBEICogRCkpIC0gKihDQVRDSCArIEkgLTEpOwoJCWlmICgqKFBPUCArIEkpIDw9IDApIHsJLypHT1RPIDIwKi8KCQkJcmV0dXJuIDAuMDsKCQkJLyogMjAgU1RLU0lNID0gMC4gKi8KCQl9Cgl9IC8qIDEwICAgQ09OVElOVUUgKi8KCS8qIFNUS1NJTSA9IFBPUChtZC5JWUVBUikgKi8KCXJldHVybiAqKFBPUCArIG1kLklZRUFSKTsKCS8qIFJFVFVSTiAqLwogICAgLyogRU5EICovCn0KLyogCglTVUJST1VUSU5FIFNPUlQgKEFSUkFZLCBBUlJBWTIsIE4pCglTT1JUIHNvcnRzIGEgcGFpciBvZiBhcnJheXMgaW4gYXNjZW5kaW5nIG9yZGVyIG9mIHRoZSBmaXJzdCBhcnJheQogICAodXNpbmcgdGhlIGhlYXBzb3J0IGFsZ29yaXRobSkKKi8Kdm9pZCBTT1JUKGRvdWJsZSAqQVJSQVksIGRvdWJsZSAqQVJSQVkyLCBpbnQgTikKewoJZG91YmxlIC8qQVJSQVkoMDoqKSwgQVJSQVkyKDA6KiksKi8gVEVNUCwgVEVNUDI7CglpbnQgIC8qTiwqLyBLLCBJUiwgSSwgSjsKCWlmIChOIDwgMikgcmV0dXJuOwoJSyA9IE4gLyAyOwoJSVIgPSBOIC0gMTsKCXdoaWxlICgxKSB7IC8qMTAqLwoJCWlmIChLICE9IDApIHsKCQkJSyA9IEsgLSAxOwoJCQlURU1QID0gKihBUlJBWSArIEspOwoJCQlURU1QMiA9ICooQVJSQVkyICsgSyk7CgkJfSBlbHNlIHsKCQkJVEVNUCA9ICooQVJSQVkgKyBJUik7CgkJCVRFTVAyID0gKihBUlJBWTIgKyBJUik7CgkJCSooQVJSQVkgKyBJUikgPSAqQVJSQVk7CgkJCSooQVJSQVkyICsgSVIpID0gKkFSUkFZMjsKCQkJSVIgPSBJUiAtIDE7CgkJCWlmIChJUiA9PSAwKSB7CgkJCQkqQVJSQVkgPSBURU1QOwoJCQkJKkFSUkFZMiA9IFRFTVAyOwoJCQkJcmV0dXJuOwoJCQl9CgkJfQoJCUkgPSBLOwoJCUogPSBLICsgSyArIDE7CgkJd2hpbGUgKDEpIHsvKjIwKi8KCQkJaWYgKEogPiBJUikgYnJlYWs7CgkJCWlmICgoSiA8IElSKSAmJiAoKihBUlJBWSArIEopIDwgKihBUlJBWSsgSiArIDEpKSkgSiA9IEogKyAxOwoJCQlpZiAoVEVNUCA8ICooQVJSQVkgKyBKKSkgewoJCQkJKihBUlJBWSArIEkpID0gKihBUlJBWSArIEopOwoJCQkJKihBUlJBWTIgKyBJKSA9ICooQVJSQVkyICsgSik7CgkJCQlJID0gSjsKCQkJCUogPSBKICsgSSArIDE7CgkJCX0gZWxzZSB7CgkJCQlKID0gSVIgKyAxOwoJCQl9CgkJfSAvKkdPVE8gMjAqLwoJCSooQVJSQVkgKyBJKSA9IFRFTVA7CgkJKihBUlJBWTIgKyBJKSA9IFRFTVAyOwoJfS8qR09UTyAxMCovCgkvKkVORCovCn0KaW50IF9nZXRsaW5lKGNoYXIgKmJ1ZmYsIHNpemVfdCBzaXplLCBGSUxFICpmcCl7CgljaGFyICpyZXQ7CglyZXQgPSBmZ2V0cyhidWZmLCBzaXplLCBmcCk7CglpZiAocmV0ICE9IE5VTEwpIHsKCQlpZiAoYnVmZltzdHJsZW4oYnVmZikgLSAxXSA9PSAnXG4nKQoJCQlidWZmW3N0cmxlbihidWZmKSAtIDFdID0gMDsKCQlpZiAoYnVmZltzdHJsZW4oYnVmZikgLSAxXSA9PSAnXHInKQoJCQlidWZmW3N0cmxlbihidWZmKSAtIDFdID0gMDsKCX0KCXJldHVybiAocmV0ICE9IE5VTEwpOwp9Cg==