/* *
   File:        pivec.h
   Author:      Anthony DiLello
   Created:     Mon June 2 2:40:27 EDT 1997
   Description: Header for pivec datatype. Warning: this datatype will only 
                 work properly on machines with 32 bit integers. 

   Copyright (C) 1997, Anthony DiLello
*/

#ifndef PIVEC_H
#define PIVEC_H


#include "amut.h"

/*** Some basic file utilities. Should really be in amiv.ch ****/

typedef struct pivec
{
  int size;                /* maximum number of values to be stored in vec */
  int max_value;           /* largest possible value to be stored in vec */
  int *vec;                /* array of values */

  int bits;                /* number of bits max_value value requires */
  int vec_size;            /* length of vec */
  int nums_per_word;       /* number of values per element of vec */
} pivec;

pivec *mk_pivec(int size,int max_value); /* Makes an array of size "size"
                                           in which we promise that all entries
                                           stored in the array will be between
                                           0 <= array_element <= max_value */
                                        /* The initial values are undefined */

void pivec_set_max_value(pivec *pi,int new_max_value);

pivec *mk_zero_pivec(int size,int max_value); /* As above except that the
                                              initial values are all zero. */

void set_base_encoding_to_xml(void); /* Sets the offset for four to six bit
							   encoding to XML mode */

void set_base_encoding_to_normal(void); /* Sets the offset for four to six bit
							   encoding to normal (file) mode */

int pivec_ref(pivec *pi,int index); /* returns the value in the index'th entry
                                   of the pivec. my_error's if index out
                                   of range. */

void pivec_set(pivec *pi,int index,int value); /* sets the index'th element to be 
						  value. my_error's if index out of
						  range or value > max_value */

int pivec_size(pivec *pi); /* returns number of array entries */

int pivec_sum(pivec *pi);

int pivec_max_value(pivec *pi); /* returns the max_value for the pivec */

void free_pivec(pivec *pi); 

pivec *mk_copy_pivec(pivec *pi);

ivec *mk_ivec_from_pivec(pivec *pi);

pivec *mk_pivec_from_ivec(ivec *i); /* Uses ivec_max(i) to deduce the max_value
                                      that should be used. Error if ivec contains
                                       any negative numbers */

void fprintf_pivec(FILE *s,char *m1,pivec *pi,char *m2);

void save_pivec_fast(FILE *s,pivec *pv);

pivec *mk_load_pivec_fast(FILE *s,int *line,char **r_errmess);

/* Returns the number of bytes of memory needed to hold pi */
int pivec_num_bytes(pivec *pi);

/*********** PACKED VECTORS OF REALS ****/

typedef struct pvector
{
  int size;
  float *array;
} pvector;

/* Serve a similar purpose to ivecs, only for doubles.
   (At the moment they are not economical...they use floats and so
    are 4 bytes per element. But can and will be improved if needed) */
pvector *mk_pvector(int size);
int pvector_size(pvector *pv);
double pvector_ref(pvector *pv,int index);
void pvector_set(pvector *pv,int index,double value);
void zero_pvector(pvector *pv);
pvector *mk_zero_pvector(int size);
void free_pvector(pvector *pv);
pvector *mk_copy_pvector(pvector *pv);
dyv *mk_dyv_from_pvector(pvector *pv);
pvector *mk_pvector_from_dyv(dyv *dv);
void fprintf_pvector(FILE *s,char *m1,pvector *pv,char *m2);

void save_pvector_fast(FILE *s,pvector *pv);
pvector *mk_load_pvector_fast(FILE *s,int *line,char **r_errmess);

/* PRE: 0 <= start_index <= end_index <= size
   Returns a new pivec of size end_index - start_index
   consisting of 
     { piv[start_index] , piv[start_index+1] ... piv[end_index-1] }
*/
pivec *mk_pivec_segment(pivec *x,int start_index,int end_index);
/* As above except take the elements given in subset */
pivec *mk_pivec_subset(pivec *x,ivec *subset);

/* Returns a copy of x, except one in which the size is increased by n,
   and in which the final n elements have value 0 */
pivec *mk_add_elements_to_pivec(pivec *x,int n);

int pivec_num_non_zero(pivec *piv);

/* PRE: 0 <= start_index <= end_index <= size
   Returns a new pvector of size end_index - start_index
   consisting of 
     { piv[start_index] , piv[start_index+1] ... piv[end_index-1] }
*/
pvector *mk_pvector_segment(pvector *x,int start_index,int end_index);
/* As above except take elements from subset */
pvector *mk_pvector_subset(pvector *x, ivec *subset);

/* Returns a copy of x, except one in which the size is increased by n,
   and in which the final n elements have value 0 */
pvector *mk_add_elements_to_pvector(pvector *x,int n);

/* Just like mk_copy_pivec, except survives if input is NULL (in
   which case it makes no copy and just returns NULL) */
pivec *mk_copy_pivec_maybe_null(pivec *x);

/* Just like fprintf_pivec except survives when input is NULL, and 
   prints nicely accordingly. */
void fprintf_pivec_maybe_null(FILE *s,char *m1,pivec *x,char *m2);

/* Just like mk_copy_pvector, except survives if input is NULL (in
   which case it makes no copy and just returns NULL) */
pvector *mk_copy_pvector_maybe_null(pvector *x);

/* Just like fprintf_pvector except survives when input is NULL, and 
   prints nicely accordingly. */
void fprintf_pvector_maybe_null(FILE *s,char *m1,pvector *x,char *m2);

void pivec_increment_max_value(pivec *pi);

#endif /* #ifndef PIVEC_H */
