
/* $RCSfile: ValueSet.H,v $
   $Log: ValueSet.H,v $
Revision 1.2  1992/09/16  17:17:51  jm
last version of .H;  moved to .h

 * Revision 1.13  92/09/16  17:06:33  jm
 * added spec for value_range function
 * 
 * Revision 1.12  92/09/16  16:36:33  jm
 * Added commnet to compare function
 * changed NULL to 0.
 * 
 * Revision 1.11  92/09/16  14:38:59  jm
 * Added the class ValueSetIter to provide an iterator for ValueSet
 * Rearranged the different operators for esthetic purposes
 * Added keyword 'const' to all member operators
 * Added LatticeRelation enum type, used by the compare function
 * Added declaration for compare function
 * added operators '>' and '<' for proper superset and proper subset
 * added keyword 'const' to private function count_dup
 * Moved function value_range outside the class as an independent function
 *   that takes only integer parameters
 * 
 * Revision 1.10  92/09/08  14:37:04  jm
 * removed code that had been commented out before.
 * 
 * Revision 1.9  92/09/08  14:30:47  jm
 * the operators have been redefined to be class members in the case of
 * valueset op element, and valueset op valueset. The combination 
 * element op valueset remains as a friend.
 * the function make_set does not take parameters anymore. It operates on
 * the internal value_array and size.
 * function value_range has been changed from class member to independent. It
 * will only work with integer arguments.
 * predicate operators now return an int instead of a char, in order to be
 * able to print the result.
 * 
Revision 1.1  92/09/01  14:02:25  jm
Initial revision

*/

#ifndef ValueSet_h_
#define ValueSet_h_

#include <search.h>
#include <stream.h>
#include <assert.h>
#include "ia.h"

// This class is created to provide a "default" comparator function
// for ValueType. If the user of ValueSet does not like this comparator,
// a new one can be provided.
// Notice the use of void parameters; this is because the return type and
// the argument types must match exactly to the specification needed by
// the "bsearch" and "qsort" routines used in the "contains" and "make_set"
// functions, respectively.

template <class ValueType>
class ValueSetComparator {
public:
    static int value_type_compare(const void *, const void *); 
};

template <class ValueType>
class ValueSetIter;

template <class ValueType>
class ValueSet: public ValueSetComparator<ValueType> {
private:
    unsigned int size;
    ValueType *value_array;
public:
    ValueSet() {size = 0; value_array = 0;}
    ValueSet(const ValueSet&);
    ValueSet& operator= (const ValueSet&);
    ~ValueSet() {if (this->value_array != 0) delete [] value_array;}
    
    ValueSet(ValueType);
    ValueSet(ValueType, ValueType);
    ValueSet(ValueType, ValueType, ValueType);
    ValueSet(ValueType, ValueType, ValueType, ValueType);
    ValueSet(ValueType, ValueType, ValueType, ValueType, ValueType);
    ValueSet(ValueType* const, unsigned int);
    
    // card: cardinality, number of elements in the set
    
    unsigned int card() const {return this->size;}
    
    // contains: predicate for testing membership of an element in a set
    
    int contains(ValueType) const;

    // min: minimum element of the set
    
    ValueType min() const {
	if (this->size == 0) 
	    ia_throw(IA::INVALID_OPERATION, __FILE__, __LINE__);    
	return this->value_array[0];
    }
    
    // max: maximum element of the set
    
    ValueType max() const {
	if (this->size == 0) 
	    ia_throw(IA::INVALID_OPERATION, __FILE__, __LINE__);    
	return this->value_array[this->size-1];
    }
    
    // empty: predicate for testing emptiness of a set 

    int empty() const {return (this->size == 0);}
    
    ValueSet<ValueType>	operator|  (const ValueSet<ValueType>&) const;
    ValueSet<ValueType>	operator&  (const ValueSet<ValueType>&) const;
    ValueSet<ValueType>	operator/  (const ValueSet<ValueType>&) const;
    ValueSet<ValueType>	operator^  (const ValueSet<ValueType>&) const;
        
    ValueSet<ValueType>	operator|  (const ValueType&) const;
    ValueSet<ValueType>	operator&  (const ValueType&) const;
    ValueSet<ValueType>	operator/  (const ValueType&) const;
    ValueSet<ValueType>	operator^  (const ValueType&) const;
    
    friend ValueSet<ValueType>	
    operator|  (const ValueType&, const ValueSet<ValueType>&);
    friend ValueSet<ValueType>	
    operator&  (const ValueType&, const ValueSet<ValueType>&);
    friend ValueSet<ValueType>	
    operator/  (const ValueType&, const ValueSet<ValueType>&);
    friend ValueSet<ValueType>	
    operator^  (const ValueType&, const ValueSet<ValueType>&);

    enum LatticeRelation {
	P_SUBSET, MP_SUBSET, EQUAL, MP_SUPERSET, P_SUPERSET, NO_REL, UNKNOWN
	};

    // The range of return values for this compare function does not include
    // all the enumerated values.
 
    friend LatticeRelation 
    compare(const ValueSet<ValueType>&, const ValueSet<ValueType>&);

    int operator<= (const ValueSet<ValueType>&) const;
    int operator>= (const ValueSet<ValueType>&) const;
    int operator<  (const ValueSet<ValueType>&) const;
    int operator>  (const ValueSet<ValueType>&) const;
    int	operator== (const ValueSet<ValueType>&) const;
    int	operator!= (const ValueSet<ValueType>&) const;

    int operator<= (const ValueType&) const;
    int operator>= (const ValueType&) const;
    int operator<  (const ValueType&) const;
    int operator>  (const ValueType&) const;
    int	operator== (const ValueType&) const;
    int operator!= (const ValueType&) const;

    friend int operator<= (const ValueType&, const ValueSet<ValueType>&);
    friend int operator>= (const ValueType&, const ValueSet<ValueType>&);
    friend int operator<  (const ValueType&, const ValueSet<ValueType>&);
    friend int operator>  (const ValueType&, const ValueSet<ValueType>&);
    friend int operator== (const ValueType&, const ValueSet<ValueType>&);
    friend int operator!= (const ValueType&, const ValueSet<ValueType>&);

    friend ostream& operator<< (ostream&, ValueSet<ValueType>&);
    friend class ValueSetIter<ValueType>;

private:

    // Set_Nth procedure, note:  indices start at 0
    void set_nth (unsigned int index, ValueType value) {
	if (index >= this->size)
	    ia_throw(IA::POINT_INDEX_MISMATCH, __FILE__, __LINE__);
	this->value_array[index] = value;
	// problem? need promotion to proper type?
    }
    
    int count_dup() const;
    void remove_dup();
    void make_set();

};

template <class ValueType>
class ValueSetIter {
    const ValueSet<ValueType>* vsp;
    int i;
public:
    ValueSetIter(const ValueSet<ValueType> &vs) { vsp = &vs; i = 0;}
    int operator()(ValueType& vt) {
	int ret = 1;
	if (i < vsp->size) vt = vsp->value_array[i++];
	else ret = 0;
	return ret;
    }
};

ValueSet<int> value_range(int v0, int v1);

#endif

