/*
   File:        column.h
   Author:      Andrew W. Moore
   Created:     Sat Aug 14 12:50:29 EDT 1999
   Description: Header for SPR/Auton Column of a datset structure

   Copyright 1999, Schenley Park Research
*/


#ifndef COLUMN_H
#define COLUMN_H
#include "amut.h"
#include "pivec.h"
#include "colshape.h"

/* This represents the actual values in the actual dataset of a column
   of data (more precisely called a column of attribute values) */
typedef struct column
{
  pivec *symbol_values; /* non-NULL if and only if symbolic data */
  pvector *real_values;    /* non-null if and only if real data */

  int num_missing;
  /* Invariant: num_missing==0 <=> missing==NULL

                if missing is non-null, then 
                     num_missing == number of "1"'s in missing pivec. */

  pivec *missing; /* NULL <=> there are no records in which
                                     this attribute is missing.

                            Non-null <=> this is a pivec in which entries
                                         are all binary numbers. Then
                                           pivec_ref(missing,i)==0 means
                                              "This attribute NOT missing
                                               in i'th record"
                                         and
                                           pivec_ref(missing,i)==1 means
                                              "This attribute IS missing
                                               in i'th record" */

} column;

#define column_value_is_missing(col,row) \
    ((col)->missing != NULL && pivec_ref(col->missing,row)==1)

void free_column(column *x);

column *mk_copy_column(column *x);

void fprintf_column(FILE *s,char *m1,column *x,char *m2);

column *mk_zero_column(colshape *cs,int num_entries);

bool column_real_ref_ok(column *col);

bool column_symbol_ref_ok(column *col);

void save_column_fast(FILE *s,column *col);

column *mk_column_from_stream_fast(FILE *s,colshape *cs,int *line,int version,
                                   char **r_errmess);

int column_symbol_ref(column *col,int row);

double column_real_ref(column *col,int row);

void column_set_value_non_missing(column *col,int row);

int column_size(column *col);

void column_set_value_missing(column *col,int row);

/* If the column has both coltypes this function does not
   complain and merely updates the symbol coltype */
void column_symbol_set(column *col,int row,int value);

/* If the column has both coltypes this function does not
   complain and merely updates the real coltype */
void column_real_set(column *col,int row,double value);

/* Use this function to mess with the column types. You have three
   options:

     major_coltype == REAL_COL , minor_coltype == UNDEFINED_COL
        This with allow real_refs and real_sets in future and will
        forbid symbol_refs and symbol_sets. Any previous symbolic 
        values will be eliminated.

        If real_ref was okay on entry (i.e. if real values were previously
        defined) they remain unchanged by this function. If they were
        previously undefined, they will start life with all 0.0 values.


     major_coltype == SYMBOL_COL , minor_coltype == UNDEFINED_COL
        This with allow symbol_refs and symbol_sets in future and will
        forbid real_refs and real_sets. Any previous real 
        values will be eliminated.

        If symbol_ref was okay on entry (i.e. if symbol values were previously
        defined) they remain unchanged by this function. If they were
        previously undefined, they will start life with all 0 values.


     major_coltype == SYMBOL_COL , minor_coltype == REAL_COL
     major_coltype == REAL_COL   , minor_coltype == SYMBOL_COL
        (The above two are equivalent in meaning...this behavior
         differs from colshape_set_type()'s behavior)

        This will allow both symbol_refs and symbol_sets in future and will
        allow real_refs and real_sets.

        If symbol_ref was okay on entry (i.e. if symbol values were previously
        defined) they remain unchanged by this function. If they were
        previously undefined, they will start life with all 0 values.
        If real_ref was okay on entry (i.e. if real values were previously
        defined) they remain unchanged by this function. If they were
        previously undefined, they will start life with all 0.0 values.

  So what about the arity of the symbol component? If there no
  symbol component, then it doesn't matter. If there *is* is new 
  symbol component (previously none) then the arity will be zero.
  And if there was a symbol component before and there's still one,
  the arity will be unchanged.
*/
void column_set_coltype(column *col,int major_coltype,int minor_coltype);

void check_column_symbol_ref_ok(column *co);

/* Changes the arity of the column to the new arity. What happens to the
   values in the new column? If the arity is increased it remains 
   unchanged. If the arity is decreased, all previous values of "arity"
   or greater are changed to arity-1.

   It is okay to call this with an arity of zero, but in that case
   values may never be referenced. */
void column_set_arity(column *col,int arity);
  
/* All values greater than "value" are decremented. All
   values that were previously equal to "value" are
   set to be missing values. */
void column_delete_value(column *col,int value);

void column_delete_last_n_records(column *co,int n);
/* Like above, except just keep those given in subset */
void column_keep_subset(column *co,ivec *subset);

void column_add_records(column *co,int n);

void column_increment_arity(column *co);



#endif /* #ifndef COLUMN_H */
