/***************************************************************

      VSTAT.H

      header for VSTAT_*.LIB

      source from:
         unistat.c
         mulstat.c
         histo.c

      These are routines for calculating statistics with 
      vector time series.

***************************************************************/

#ifndef vstat_included
#define vstat_included
#ifndef dbhost_included
#include "dbhost.h"                   /* PROTOTYPE_ALLOWED */
#endif

/* unistat.c */
typedef struct {
   int     n,        /* number of elements in each vector */
           n_increments,  /* incremented with each call to update_unistat */
           options;  /* bit flags indicating which stats to collect */
   double *sum,      /* accumulate sums */
          *sumsq;    /* accumulate sums of squares */
   float  *min,      /* minimum found */
          *max;      /* maximum found */
   int    *npts,     /* count points accumulated */
          *imin,     /* index of minimum (start from zero) */
          *imax;     /* index of maximum */
   char   *name;
} UNISTAT_TYPE;

#define U_MEAN          1
#define U_VARIANCE      2
#define U_EXTREMA       4
#define U_INDICES       8
#define U_NORM_EXTREMA 16
#define U_ALL          31

/* mulstat.c */
/* Thoughts on Multistat design:
   Space could be saved by using   double **cov   instead of 
   the 2-D matrix of fixed size.  However, in most cases 
   this saving would be small.  If NVMAX is 10, which is 
   probably enough for most cases, then the pointer matrix 
   has 100 elements which would use at most 400 bytes.
   On the other hand, the greater generality of the pointer 
   approach is appealing.  Therefore I will start with the 
   simpler and more foolproof method (using the array), but 
   will design the routines so that it will be easy to 
   switch to the pointer method.

   The following defines will be needed for pointers:

   define  idiag(s,i)      (i*(s->nv)-i*(i+1)/2)
   define  s_index(s,i,j)  ((j-i) + idiag(s,i))
   define  s_sumpr(s,i,j)  (*(s->sumpr) + s_index(s,i,j))
   define  s_npts(s,i,j)   (*(s->npts) + s_index(s,i,j))

   NOTE:  Since the covariance matrix is symmetric, there is 
   no need to use the part below the diagonal.  For 
   consistency, ensure that j>=i, so that only the upper 
   half is referenced.

   In some cases, only some of the cross products may be 
   desired.  Then the remaining sumpr pointers can be set to 
   NULL, and the update routine can check for this value 
   before adding to the sum of squares.  This will require 
   an additional argument to allocate_multistat (an array of 
   flags, showing which combinations of variables are 
   desired), and will be left to be added later as a 
   refinement.

*/

#define NVMAX 10

typedef struct {
   int     n,                    /* number of elements in each vector */
           nv;                   /* number of variables */
   double *sum[NVMAX],           /* sums    */
          *sumpr[NVMAX][NVMAX];  /* sums of squares  */
   int    *npts[NVMAX][NVMAX];   /* count points accumulated */
   char   *var_name[NVMAX];      /* name of each variable */
   char   *name;                 /* name of the set of variables */
} MULTISTAT_TYPE;

#define s_sumpr(s,i,j)  ((s->sumpr)[i][j])
#define s_npts(s,i,j)   ((s->npts)[i][j])

/* HISTO.C */
typedef struct {
   unsigned int  *bin_array;
   int            nrows,
                  nbins;
   double         origin,
                  bin_width;
   char          *name;
}  HISTOGRAM_TYPE;

#if PROTOTYPE_ALLOWED

/* unistat.c */
void allocate_unistat(UNISTAT_TYPE *s, int n, char *name, int options);
void free_unistat(UNISTAT_TYPE *s);
void zero_unistat(UNISTAT_TYPE *s);
void update_unistat(UNISTAT_TYPE *s, float *array, int na);
void update_unistat_d(UNISTAT_TYPE *s, double *array, int na);
void calculate_unistat(UNISTAT_TYPE *s);
void write_unistat(FILE *fpt, UNISTAT_TYPE *s, double scale, 
                     float *d, char *d_name, int nd_prec);

/* mulstat.c */
void allocate_multistat(MULTISTAT_TYPE *s, int n, int nvar, char *name, char **var_name);
void free_multistat(MULTISTAT_TYPE *s);
void zero_multistat(MULTISTAT_TYPE *s);
void update_multistat(MULTISTAT_TYPE *s, float **array, int na);
void calculate_multistat(MULTISTAT_TYPE *s);
void write_multistat(FILE *fpt, MULTISTAT_TYPE *s, double scale, 
             float *d, char *d_name, int nd_prec, char cv_flag);
void zero_double_array(double *d, int n);
void zero_int_array(int *ia, int n);



/* HISTO.C */
void allocate_histogram(HISTOGRAM_TYPE *h, int nrows, int nbins, char *name);
void free_histogram(HISTOGRAM_TYPE *h);
void zero_histogram(HISTOGRAM_TYPE *h);
void update_histogram(HISTOGRAM_TYPE *h, float *array, int n);
void write_histogram(FILE *fp, HISTOGRAM_TYPE *h, int n_digits,
                     float *d, char *d_name, int nd_prec, char *style);

#else
/* unistat.c */
void allocate_unistat();
void free_unistat();
void zero_unistat();
void update_unistat();
void update_unistat_d();
void calculate_unistat();
void write_unistat();

/* mulstat.c */
void allocate_multistat();
void free_multistat();
void zero_multistat();
void update_multistat();
void calculate_multistat();
void write_multistat();
void zero_double_array();
void zero_int_array();

/* HISTO.C */
void allocate_histogram();
void free_histogram();
void zero_histogram();
void update_histogram();
void write_histogram();

#endif

#endif /* ifndef vstat_included */

