/*
 *	File: ad2Carr.c
 *
 *      (C) IWTS
 *          KU Nijmegen
 *          The Netherlands
 *
 *      Author: R. Harald Baayen
 *
 *      History:
 *
 *      - jul 1997, version 1.0
 *
 *      Description:
 *
 *      
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <errno.h>
#include <malloc.h>
#include <string.h>
#include "lex_cons.h"


/* EXTERN FUNCTIONS */

/* functions for lognormal model */

extern double	expV ();
extern double	expV1 ();
extern double	expVm ();

extern double	funcVNy ();
extern double	funcV1Ny (); 
extern double	funcVmNy ();

/* functions for numerical procedures */

extern double	getlexprop ();
extern double	adjustV ();
extern double	adjustVm ();
extern double	qromb ();
extern double	factln ();

/* argument reading, file manipulation, and help function */

extern int	leesgetal ();
extern void	change_extension ();
extern void	help ();


/* GLOBAL VARIABLES */

double   N, V, n1, n2,              /* number of tokens, types, hapaxes, disleg */
         E,                         /* extrapolation sample size */
         mmax,                      /* highest frequency rank */
         mrank,                     /* word frequency, used in expVm() */
         SPECTRUM[MAXM3][3],        /* frequency spectrum m Vm EVm */
         PVM[MAXM3],                /* m*Vm/N */
         mean, stdev, Z,            /* parameters */
         smean, sstdev, sZ,         /* sample-based estimates of parameters */
         Nzero, Vzero,              /* original sample size N0 */
         eV, eV2N, S, eV1,          /* E[V(N)], E[V(2N)], S, E[V(1,N)] */
         CHUNKS[MAXCHUNKS3],        /* the chunk sizes */
         chunksize, remainDer,      /* chunk variables */
         x, y, x1, y2, y3, y4, y5,
         gN, gm,                    /* N, m used by integration functions */
         t,
         OBSERVED[MAXCHUNKS3+1][6], /* V and V1..5 */
         EXPVOCINT[MAXCHUNKS3+1],   /* interpolated vocabulary size */
         lexprop,                   /* proportion specialized words */
         mse,                       /* MSE for specialization fit */
         **sim_mat,		    /* for simplex minimization */
	 *sim_vec,
	 *sim_yy,
	 miny;

FILE     *fpspectrum,               /* fpspectrum: datafile: m, Vm */
         *fpexpspect,               /* expected spectrum */
         *fpexpspect2N,             /* spectrum at 2N */
         *fpprofile,                /* observed developmental profile */
         *fpVN,                     /* file with E[V(N)] and E[V(2N)] */
         *fpsum,                    /* file with summary of model */
         *fpsum2,                   /* file with summary of unadjusted model */
         *fpint,                    /* interpolation results */
         *fpext,                    /* extrapolation results */
         *fpE;                      /* spectrum at sample size E */

int      nranks,                    /* number of different ranks in spectrum */
         maxrank,                   /* largest rank for fit, default 15 */
         i, j, ii, 
         header,                    /* boolean for presence of header */
         k,                         /* variable for chunks */
         nchunks,                   /* number of chunks for interpolation */
         enchunks,                  /* number of chunks for extrapolation */
         token, type,               /* auxiliary variables for scanf */
         again,                     /* boolean for manual param.estimation */
         aantal;                    /* for command line options */

char     woord[MAXWORDLENGTH],      /* variable for skipping header in fscanf */
         new_name[MAXWORDLENGTH],   /* variables for extension handling    */
         base_name[MAXWORDLENGTH],
         c,
         *fs;                       /* variable for scanning options */


/* MAIN () */

int main (argc, argv)
int	argc;
char    *argv[];

{
   /* DEFAULTS */

   maxrank = DEF_MAXRANK;
   nchunks = DEF_CHUNKS;
   enchunks = DEF_CHUNKS;
   header = 1;
   E = NULL_F;

   /* COMMAND LINE OPTIONS */

   while ((--argc > 0) && ((*++argv)[0] == '-')) {
        for (fs = argv[0] + 1; *fs != '\0'; fs++) {
            switch (*fs) {
            case 'h':
                help();
                break;
            case 'E':
                i =  leesgetal (fs, &aantal);
                E = (double) i;
                for (; aantal > 0; aantal--){
                   fs++;
                }
                break;
            case 'k':
                nchunks = leesgetal (fs, &aantal);
                for (; aantal > 0; aantal--){
                   fs++;
                }
                break;
            case 'K':
                enchunks = leesgetal (fs, &aantal);
                for (; aantal > 0; aantal--){
                   fs++;
                }
                break;
            case 'm':
                maxrank = leesgetal (fs, &aantal);
                for (; aantal > 0; aantal--){
                   fs++;
                }
                break;
            case 'H':      /* input files without headers! */
                header = 0;
                break;
            default:
                fprintf(stderr, "ad2Carr: illegal option %c\n", *fs);
                exit(1);
                break;
            }
        }
   } /* of while */

   if (argc == 0) {
     help ();
   }

   /* FILE HANDLING */

   /* load input spectrum, should have .spc extension */

   if ((fpspectrum = fopen(*argv, "r")) == NULL) {
       fprintf(stderr, "ad2Carr: can't open %s\n", *argv);
       exit(1);
   }

   strncpy(base_name, *argv, strlen (*argv) - 4);

   change_extension (base_name, new_name, ".obs");
   if ((fpprofile = fopen(new_name, "r")) == NULL) {
       fprintf(stderr, "ad2Carr: can't open profile file %s\n", new_name);
       exit(1);
   }
   change_extension (base_name, new_name, "_C.sum");
   if ((fpsum2 = fopen(new_name, "r")) == NULL) {
       fprintf(stderr, "ad2Carr: can't open summary file %s\n", new_name);
       exit(1);
   }

   /* file name handling output files */

   change_extension (base_name, new_name, "_bC.spc");
   if ((fpexpspect = fopen(new_name, "w")) == NULL){
      fprintf(stderr, "ad2Carr: can't open output file %s\n", new_name);
      exit(1);
   }
   change_extension (base_name, new_name, "_bC.sp2");
   if ((fpexpspect2N = fopen(new_name, "w")) == NULL){
      fprintf(stderr, "ad2Carr: can't open output file %s\n", new_name);
      exit(1);
   }
   change_extension (base_name, new_name, "_bC.ev2");
   if ((fpVN = fopen(new_name, "w")) == NULL){
      fprintf(stderr, "ad2Carr: can't open output file %s\n", new_name);
      exit(1);
   }
   change_extension (base_name, new_name, "_bC.sum");
   if ((fpsum = fopen(new_name, "w")) == NULL){
      fprintf(stderr, "ad2Carr: can't open output file %s\n", new_name);
      exit(1);
   }
   change_extension (base_name, new_name, "_bC.int");
   if ((fpint = fopen(new_name, "w")) == NULL){
      fprintf(stderr, "ad2Carr: can't open output file %s\n", new_name);
      exit(1);
   }
   change_extension (base_name, new_name, "_bC.ext");
   if ((fpext = fopen(new_name, "w")) == NULL){
      fprintf(stderr, "ad2Carr: can't open output file %s\n", new_name);
      exit(1);
   }
   if (E > NULL_F){
     change_extension (base_name, new_name, "_bC.sp3");
     if ((fpE = fopen(new_name, "w")) == NULL){
        fprintf(stderr, "ad2Carr: can't open output file %s\n", new_name);
        exit(1);
     }
   }

   /* LOAD SUMMARY FILE OF UNADJUSTED MODEL */

   /* scan title line of summary file */
   for (i = 1; i <= 11; i++) fscanf(fpsum2, "%s ", woord);
   /* scan 8 lines of summary data */
   for (i = 1; i <= 8; i++) fscanf(fpsum2, "%s %s %s", woord, woord, woord);
   fscanf(fpsum2, "%s ", woord);
   if (strcmp("Z", woord)!=0){
     fprintf(stderr, "lognormal summary file has wrong format\n");
     fprintf(stderr, "Possibly, cost function C2 was used instead of C1\n");
     exit(1);
   }
   fscanf(fpsum2, "%s %lf",  woord, &Z);

   fscanf(fpsum2, "%s %s %lf", woord, woord, &mean);
   fscanf(fpsum2, "%s %s %lf", woord, woord, &stdev);
   fclose(fpsum2);
   fprintf(stdout, "read summary file, Z = %f, mean = %f, stdev = %f\n", \
	Z, mean, stdev);
   fflush(stdout);

   /* LOAD SPECTRUM FILE */

   nranks = 0; n1 = 0; n2 = 0; 
   if (header){
      fscanf(fpspectrum, "%s ", woord);  /* m */
      fscanf(fpspectrum, "%s ", woord);  /* Vm */
   }

   while (fscanf(fpspectrum, "%d %d", &token, &type) != EOF)  {
        nranks++;
        SPECTRUM[nranks][0] = (double) token;
        SPECTRUM[nranks][1] = (double) type;
        if (token == 1) n1 = type;
        if (token == 2) n2 = type;
        N+= (double) token * (double) type;
        V+= (double) type;
   }
   mmax = SPECTRUM[nranks][0];
   Nzero = N; Vzero = V;

   /* LOAD OBSERVED PROFILE */

   fprintf(stdout, "reading %s.obs\n",base_name);
   fflush(stdout);
   if (header){
       for (i = 1; i <= NMEASURES2; i++){
          if (fscanf(fpprofile, "%s ", woord) == EOF){
            fprintf(stderr, "incomplete header for %s.obs\n", base_name);
          }
       }
   }

   for (i = 1; i <= nchunks; i++){
       if (fscanf(fpprofile, "%d ", &type) != EOF){
           ;
       } else {
       fprintf(stderr, "%s.obs is incompatible with required number of chunks\n", base_name);
           exit(1);
       }
       for (j = 2; j <= NMEASURES2; j++){
           if (fscanf(fpprofile, "%lf ", &x) != EOF){
               switch (j){
                 case 4:
                   OBSERVED[i][0] = x;
                   break;
                 case 5:
                   OBSERVED[i][1] = x;
                   break;
                 case 6:
                   OBSERVED[i][2] = x;
                   break;
                 case 7:
                   OBSERVED[i][3] = x;
                   break;
                 case 8:
                   OBSERVED[i][4] = x;
                   break;
                 case 9:
                   OBSERVED[i][5] = x;
                   break;
                 default:
                   break;
              }
           }
           else{
               fprintf(stderr,
                "%s.obs is incompatible with required number of chunks\n",
                base_name);
               exit(1);
           }
       }
   }

   fprintf(stdout, "loaded input files\n");
   fprintf(stdout, "Z = %f  stdev = %f\n", Z, stdev);
   fflush(stdout);

   /* NOW CALCULATE E[V(N)] AND E[V(m,N)]  */

   fprintf(stdout, "computing expected spectrum at N\n");
   fflush(stdout);
   eV = expV(N);
   eV1 = expV1(N);
   SPECTRUM[1][2] = eV1;
   /*   VMZERO[1] = SPECTRUM[1][2]; */
   fprintf(stdout, "[1]\n");
   fflush(stdout);
   mean = -log(Z);
   S = exp((0.5*stdev*stdev) - mean);
   for (i = 2; i <= maxrank; i++) {
     fprintf(stdout, "[%d]\n", i);
     fflush(stdout);
     SPECTRUM[i][2] = expVm(N, SPECTRUM[i][0]);
     /*    if (i <= 5) VMZERO[i] = SPECTRUM[i][2]; */
   }
   fprintf(stdout, "\n");
   fflush(stdout);

   /* AND DETERMINE THE INTERPOLATED VALUED OF E[V(N)] */

   /* the chunksizes */

   chunksize = floor(Nzero/(nchunks*1.0));
   remainDer = Nzero - ((nchunks*1.0) * chunksize);
   for (k = 1; k <= nchunks; k++)   CHUNKS[k] = chunksize;
   for (k = 1; k <= remainDer; k++) CHUNKS[k]++;
   for (k = 2; k <= nchunks; k++)   CHUNKS[k] += CHUNKS[k-1];


   /* interpolating */

   fprintf(stdout, "computing interpolation statistics unadjusted model\n");

   for (k = 1; k <= nchunks; k++){
       fprintf(stdout, "[%d]\n", k);
       fflush(stdout);
       EXPVOCINT[k] = expV(CHUNKS[k]);
   }
   fprintf(stdout, "\n");

   /* determine optimal specialization proportion */

   fprintf(stdout, "starting estimation of p\n");
   fflush(stdout);

   lexprop = getlexprop ();

   /* PRINT SUMMARY */

   fprintf(fpsum, "Partition-adjusted lognormal model for %s\n", *argv);
   fprintf(fpsum, "N         = %12d\n", (int) N);
   fprintf(fpsum, "V(N)      = %12d\n", (int) V);
   fprintf(fpsum, "E[V(N)]   = %12.4f\n", eV);
   fprintf(fpsum, "V(1,N)    = %12d\n", (int) n1);
   fprintf(fpsum, "E[V(1,N)] = %12.4f\n\n", SPECTRUM[1][2]);
   fprintf(fpsum, "Z         = %12.5f\n",  Z);
   fprintf(fpsum, "mean      = %12.5f\n",  mean);
   fprintf(fpsum, "stdev     = %12.5f\n",  stdev);
   fprintf(fpsum, "S         = %12.5f\n", S);
   fprintf(fpsum, "p         = %12.8f\n", lexprop);
   fprintf(fpsum, "MSE       = %12.8f\n", mse);
   fclose(fpsum);

   /* PRINT SPECTRUM */

   fprintf(fpexpspect, "         m         Vm        EVm     alphaM    EalphaM\n");
   for (i = 1; i <= maxrank; i++) {
    fprintf(fpexpspect, "%10d %10d ",(int) SPECTRUM[i][0],(int) SPECTRUM[i][1]);
    fprintf(fpexpspect, "%10.4f %10.4f %10.4f\n", SPECTRUM[i][2],
           SPECTRUM[i][1]/Vzero, SPECTRUM[i][2]/eV);
   }
   fclose(fpexpspect);

   /* PRINT SPECTRUM AT 2N */

   fprintf(stdout, "computing expected spectrum at 2N\n");
   fflush(stdout);
   N = 2 * Nzero;
   eV2N = adjustV (expV (N), N, lexprop, Nzero, Vzero);
   fprintf(fpexpspect2N, "         m      EVm2N\n");
   for (i = 1; i <= 2 * maxrank; i++){
     fprintf(stdout, "[%d]\n", i);
     fflush(stdout);
     fprintf(fpexpspect2N, "%10d %10.2f\n", i,
          adjustVm (expVm (N, (double) i), N, lexprop, Nzero, SPECTRUM[i][2]));
   }
   fprintf(stdout, "\n");
   fflush(stdout);
   fclose(fpexpspect2N);

   /* PRINT VOCABULARY SIZES */

   fprintf(fpVN, "       V       EV     EV2N\n");
   fprintf(fpVN, "%8.2f %8.2f %8.2f\n", V, eV, adjustV (eV2N, 2 * Nzero, lexprop, Nzero, Vzero));
   fclose(fpVN);

   /* INTERPOLATION */

   if (nchunks > 0){

     /* CALCULATE THE TEXT CHUNKS */

     chunksize = floor(Nzero/(nchunks*1.0));
     remainDer = Nzero - ((nchunks*1.0) * chunksize);
     for (k = 1; k <= nchunks; k++)   CHUNKS[k] = chunksize;
     for (k = 1; k <= remainDer; k++) CHUNKS[k]++;
     for (k = 2; k <= nchunks; k++)   CHUNKS[k] += CHUNKS[k-1];

     /* AND PRINT THE CORRESPONDING STATISTICS */

     fprintf(stdout, "computing interpolation statistics\n");
     fflush(stdout);
     fprintf(fpint, "       N       EV   Alpha1      EV1      EV2      EV3      EV4      EV5       GV\n");
     for (k = 1; k <= nchunks; k++){
        fprintf(stdout, "[%d]\n", k);
        fflush(stdout);
        x = adjustV (expV (CHUNKS[k]), CHUNKS[k], lexprop, Nzero, Vzero);
        x1 = adjustV (expV (CHUNKS[k]+1.0), CHUNKS[k]+1.0, lexprop, Nzero, Vzero);
        y = adjustVm (expVm (CHUNKS[k], 1.0), CHUNKS[k], lexprop, Nzero, SPECTRUM[1][2]);
        y2 = adjustVm (expVm (CHUNKS[k], 2.0), CHUNKS[k], lexprop, Nzero, SPECTRUM[2][2]);
        y3 = adjustVm (expVm (CHUNKS[k], 3.0), CHUNKS[k], lexprop, Nzero, SPECTRUM[3][2]);
        y4 = adjustVm (expVm (CHUNKS[k], 4.0), CHUNKS[k], lexprop, Nzero, SPECTRUM[4][2]);
        y5 = adjustVm (expVm (CHUNKS[k], 5.0), CHUNKS[k], lexprop, Nzero, SPECTRUM[5][2]);
        fprintf(fpint, "%8.2f %8.2f %8.4f %8.2f %8.2f %8.2f %8.2f %8.2f %8.4f\n", CHUNKS[k], x, y/x, y, y2, y3, y4, y5, x1-x);
     }
     fprintf(stdout, "\n");
     fflush(stdout);
   }

   /* EXTRAPOLATION */
 
   if (E == NULL_F) {  /* extrapolate to 2N */
     fprintf(fpext, "       N       EV   Alpha1      EV1      EV2      EV3      EV4      EV5       GV\n");
     fprintf(stdout, "computing extrapolation statistics to 2N\n");
     fflush(stdout);
     for (k = 1; k <= nchunks; k++){
        fprintf(stdout, "[%d]\n", k);
        fflush(stdout);
        x  = adjustV (expV (Nzero+CHUNKS[k]), Nzero+CHUNKS[k], lexprop, Nzero, Vzero);
        x1 = adjustV (expV (Nzero+CHUNKS[k]+1.0), Nzero+CHUNKS[k]+1.0, lexprop, Nzero, Vzero);
        y  = adjustVm (expVm (Nzero+CHUNKS[k], 1.0), Nzero+CHUNKS[k], lexprop, Nzero, SPECTRUM[1][2]);
        y2 = adjustVm (expVm (Nzero+CHUNKS[k], 2.0), Nzero+CHUNKS[k], lexprop, Nzero, SPECTRUM[2][2]);
        y3 = adjustVm (expVm (Nzero+CHUNKS[k], 3.0), Nzero+CHUNKS[k], lexprop, Nzero, SPECTRUM[3][2]);
        y4 = adjustVm (expVm (Nzero+CHUNKS[k], 4.0), Nzero+CHUNKS[k], lexprop, Nzero, SPECTRUM[4][2]);
        y5 = adjustVm (expVm (Nzero+CHUNKS[k], 5.0), Nzero+CHUNKS[k], lexprop, Nzero, SPECTRUM[5][2]);
        fprintf(fpext, "%8.2f %8.2f %8.4f %8.2f %8.2f %8.2f %8.2f %8.2f %8.4f\n", Nzero+CHUNKS[k], x, y/x, y, y2, y3, y4, y5, x1-x);
     }
     fprintf(stdout, "\n");
     fflush(stdout);
   }
   else{

     /* FIND NEW CHUNKSIZES */

     fprintf(stdout, "computing extrapolation statistics to E\n");
     fflush(stdout);
     chunksize = floor((E-Nzero)/(enchunks*1.0));
     remainDer = (E-Nzero) - ((enchunks*1.0) * chunksize);
     for (k = 1; k <= enchunks; k++)   CHUNKS[k] = chunksize;
     for (k = 1; k <= remainDer; k++)  CHUNKS[k]++;
     for (k = 2; k <= enchunks; k++)   CHUNKS[k] += CHUNKS[k-1];

     /* PRINT THE GROWTH CURVE */

     fprintf(fpext, "       N       EV   Alpha1      EV1      EV2      EV3      EV4      EV5       GV\n");

     for (k = 1; k <= enchunks; k++){
        fprintf(stdout, "[%d]\n", k);
        fflush(stdout);
        x  = adjustV (expV (Nzero+CHUNKS[k]), Nzero+CHUNKS[k], lexprop, Nzero, Vzero);
        x1 = adjustV (expV (Nzero+CHUNKS[k]+1.0), Nzero+CHUNKS[k]+1.0, lexprop, Nzero, Vzero);
        y  = adjustVm (expVm (Nzero+CHUNKS[k], 1.0), Nzero+CHUNKS[k], lexprop, Nzero, SPECTRUM[1][2]);
        y2 = adjustVm (expVm (Nzero+CHUNKS[k], 2.0), Nzero+CHUNKS[k], lexprop, Nzero, SPECTRUM[2][2]);
        y3 = adjustVm (expVm (Nzero+CHUNKS[k], 3.0), Nzero+CHUNKS[k], lexprop, Nzero, SPECTRUM[3][2]);
        y4 = adjustVm (expVm (Nzero+CHUNKS[k], 4.0), Nzero+CHUNKS[k], lexprop, Nzero, SPECTRUM[4][2]);
        y5 = adjustVm (expVm (Nzero+CHUNKS[k], 5.0), Nzero+CHUNKS[k], lexprop, Nzero, SPECTRUM[5][2]);
        fprintf(fpext, "%8.2f %8.2f %8.4f %8.2f %8.2f %8.2f %8.2f %8.2f %8.4f\n", Nzero+CHUNKS[k], x, y/x, y, y2, y3, y4, y5, x1-x);
     }
     fprintf(stdout, "\n");
     fflush(stdout);

     /* AND SHOW THE SPECTRUM AT E */

     eV2N = expV(E);
     fprintf(fpE, "         m      EVmXN\n");
     for (i = 1; i <= maxrank; i++){
       fprintf(fpE, "%10d %10.2f\n", i, expVm(E, (double) i));
     }
   }

   return (0);
} /* end of main */


/* LEXICAL STATISTICS FUNCTIONS */

double expV (n)
double	n;

{
  N = n; 
  return (qromb (funcVNy, L_BOUND2, U_BOUND2) * N / (stdev * sqrt (2.0 * PI)));
}


double funcVNy (x) 
double	x;
{
  double	y, w, z;
 
  z = log (x * Z / N) / stdev;
  w = 1.0 / x;
  y = (1.0 - exp (-1.0 * x)) * w * w * exp ((-1.0 / 2.0) * z * z);
  return (y);
}


double expV1 (n)
double	n;
{
  N = n;
  return (qromb (funcV1Ny, L_BOUND2, U_BOUND2) * N / (stdev * sqrt (2.0 * PI)));
}


double funcV1Ny (x) 
double	x;

{
  return((1.0 / x) * exp((-1.0 * x) - ((1.0 / 2.0) * (log (x * Z / N) / stdev) * (log (x * Z / N) / stdev))));
}


double expVm (n, m)  /* voor m >= 2 */
double	m, n;

{
  gN = n;
  gm = m;

  return (qromb (funcVmNy, L_BOUND2, U_BOUND2) * gN / (stdev * sqrt (2.0 * PI)));
}


double funcVmNy (x)   /* m >= 2 */
double	x;

{
  return(exp (((gm - 2.0) * log (x)) - factln ((int) gm)) *
         exp ((-1.0 * x) - (0.5 * (log (x * Z / gN) / stdev) * (log (x * Z / gN) / stdev))));
}


/* FUNCTIONS FOR NUMERICAL PROCEDURES */

double getlexprop ()
{
  double	expvoc, adjvoc, optp, p, t, diff;
  int		i, k;

  /* determine chunksizes */

  chunksize = floor (Nzero / nchunks);
  remainDer = Nzero - nchunks * chunksize;

  for (k = 1; k <= nchunks; k++) {
    CHUNKS[k] = chunksize;
  }

  for (k = 1; k <= remainDer; k++) {
    CHUNKS[k]++;
  }

  for (k = 2; k <= nchunks; k++) {
    CHUNKS[k] += CHUNKS[k-1];
  }

  /* use vocabulary growth curve for fit */

  mse = MAXX;
  optp = NULL_F;

  for (p = 0.01; p <= 1.0; p += 0.01) {
    x = NULL_F;
    for (i = 1; i <= nchunks; i++) {
      N = CHUNKS[i];
      t = N / CHUNKS[nchunks];
      expvoc = EXPVOCINT[i]; 
      adjvoc = (p * t * Vzero) + (1.0 - p) * expvoc;
      diff = (adjvoc - OBSERVED[i][0]);
      x += (diff * diff);
    }

    x = (x / nchunks);

    if (x < mse) {
      mse = x;
      optp = p;
    }
  }

  return (optp);
}


/* HELP FUNCTION */

void help ()
{
  fprintf (stderr, "ad2Carr text.spc\n");
  fprintf (stderr, "OPTIONS:\n");
  fprintf (stderr, "     -h: display help\n");
  fprintf (stderr, "     -m: number of ranks in fit (default: 15)\n");
  fprintf (stderr, "     -k: number of chunks for interpolation (default: 20)\n");
  fprintf (stderr, "     -K: number of chunks for extrapolation (default: 20)\n");
  fprintf (stderr, "     -E: extrapolation sample size (default: 2N)\n");
  fprintf (stderr, "     -H: input files lack header (default: with header)\n"); 
  fprintf (stderr, "INPUT:\n");
  fprintf (stderr, "     text.spc:  m Vm\n");
  fprintf (stderr, "     text_C.sum\n");
  fprintf (stderr, "OUTPUT:\n");
  fprintf (stderr, "     text_bC.spc:   expected spectrum\n");
  fprintf (stderr, "     text_bC.sp2:   expected spectrum at 2N\n");
  fprintf (stderr, "     text_bC.ev2:   E[V(N)] and E[V(2N)]\n");
  fprintf (stderr, "     text_bC.sum:   summary, fitted parameters\n");
  fprintf (stderr, "     text_bC.int:   interpolation V(N), V(1-5,N)\n");
  fprintf (stderr, "     text_bC.ext:   extrapolation V(N), V(1-5,N)\n");
  exit (1);
}
