// Emacs -*- C++ -*-

//
//	Copyright 1993, Center for Computer Vision and Visualization,
//	University of Florida.  All rights reserved.
//

//
// $Log: Set.h,v $
// Revision 1.5.1.2  1994/12/08  14:44:44  thoth
// New extensive() method.
// Comparison rework to handle more computable cases.
//
// Revision 1.5.1.1  1994/10/12  17:21:27  thoth
// Added ClosureSets.
// Added op= for binary operations &|^/ .
//
// Revision 1.5  1994/10/03  19:38:09  thoth
// Get rid of redundant scalar-set operations in preparation for operator
// table.
//
// Revision 1.4  1994/10/03  17:50:47  thoth
// Added predicate sets.
//
// Revision 1.3  1994/08/22  15:10:59  thoth
// DOS-inspired name rework
//
// Revision 1.2  1994/07/25  16:45:00  thoth
// Name sanitization.
//
// Revision 1.1  1994/03/21  23:06:36  thoth
// Initial revision
//

#ifndef IA_Set_h_
#define IA_Set_h_

#include "BaseSet.h"


template <class T> class IA_Set;

template <class T> int operator< (const IA_Set<T>&, const IA_Set<T>&);
template <class T> int operator<= (const IA_Set<T>&, const IA_Set<T>&);
template <class T> int operator== (const IA_Set<T>&, const IA_Set<T>&);


template <class T> class IA_SetIter;
template <class T> class IA_ClosureSet;


template <class T>
class IA_Set {

    friend class IA_SetIter<T>;

    IA_BaseSet<T>	*bsp;

    void set_and_reference(IA_BaseSet<T> *);
    void disassociate();

    IA_Set(IA_BaseSet<T> * s) { set_and_reference(s); }
public:
    IA_Set();
    IA_Set(const IA_Set &);

    ~IA_Set();

    IA_Set& operator= (const IA_Set&);
    
    IA_Set(T);
    IA_Set(T, T);
    IA_Set(T, T, T);
    IA_Set(T, T, T, T);
    IA_Set(T, T, T, T, T);
    IA_Set( const T*, unsigned int);

    IA_Set(int (*)(T));
    IA_Set(int (*)(const T&));
    IA_Set(const IA_ClosureSet<T> &);

    int extensive() const { return bsp->extensive(); }

    // card: cardinality, number of elements in the set
    
    unsigned int card() const {return bsp->card();}
    
    // contains: predicate for testing membership of an element in a set
    
    int contains(T t) const { return bsp->contains(t); }
    
    // min: minimum element of the set
    
    T min() const {
	return bsp->min();
    }
    
    // max: maximum element of the set
    
    T max() const {
	return bsp->max();
    }

    // choice: some element from the set, we don\'t care which one
    T choice() const {
	return bsp->choice();
    }
    
    // empty: predicate for testing emptiness of a set 
    
    int empty() const {return bsp->empty();}

    friend IA_Set<T> operator| (const IA_Set<T> &, const IA_Set<T>&);
    friend IA_Set<T> operator& (const IA_Set<T> &, const IA_Set<T>&);
    friend IA_Set<T> operator^ (const IA_Set<T> &, const IA_Set<T>&);
    friend IA_Set<T> operator/ (const IA_Set<T> &, const IA_Set<T>&);
#if 0
    IA_Set<T> & operator|= ( const IA_Set<T> & s ) {
	*this = *this | s;		return *this;	}
    IA_Set<T> & operator&= ( const IA_Set<T> & s ) {
	*this = *this & s;		return *this;	}
    IA_Set<T> & operator^= ( const IA_Set<T> & s ) {
	*this = *this ^ s;		return *this;	}
    IA_Set<T> & operator/= ( const IA_Set<T> & s ) {
	*this = *this / s;		return *this;	}

    IA_Set<T> & operator|= ( T s ) {
	*this = *this | s;		return *this;	}
    IA_Set<T> & operator&= ( T s ) {
	*this = *this & s;		return *this;	}
    IA_Set<T> & operator^= ( T s ) {
	*this = *this ^ s;		return *this;	}
    IA_Set<T> & operator/= ( T s ) {
	*this = *this / s;		return *this;	}
#endif

    // The range of return values for this compare function does not include
    // all the enumerated values.
    

    friend IA::LatticeRelation
	compare(const IA_Set<T>&,
		const IA_Set<T>&);
};

//
//

template <class T> inline
int operator<  (const IA_Set<T>&a, const IA_Set<T>&b) {
    IA::LatticeRelation	cmp = compare(a, b);
    return cmp==IA::P_SUBSET;
}
template <class T> inline
int operator<=  (const IA_Set<T>&a, const IA_Set<T>&b) {
    IA::LatticeRelation	cmp = compare(a, b);
    return cmp==IA::P_SUBSET || cmp==IA::MP_SUBSET || cmp==IA::EQUAL;
}
template <class T> inline
int operator==  (const IA_Set<T>&a, const IA_Set<T>&b) {
    IA::LatticeRelation	cmp = compare(a, b);
    return cmp==IA::EQUAL;
}
template <class T> inline
int operator!=  (const IA_Set<T>&a, const IA_Set<T>&b) {
    IA::LatticeRelation	cmp = compare(a, b);
    return cmp==IA::P_SUBSET || cmp==IA::P_SUPERSET || cmp==IA::NO_REL;
}
template <class T> inline
int operator>  (const IA_Set<T>&a, const IA_Set<T>&b) {
    IA::LatticeRelation	cmp = compare(a, b);
    return cmp==IA::P_SUPERSET;
}
template <class T> inline
int operator>=  (const IA_Set<T>&a, const IA_Set<T>&b) {
    IA::LatticeRelation	cmp = compare(a, b);
    return cmp==IA::P_SUPERSET || cmp==IA::MP_SUPERSET || cmp==IA::EQUAL;
}


//
//

template <class T> inline int operator< (const T&lhs, const IA_Set<T>&rhs) {
    return IA_Set<T>(lhs) < rhs;
}
template <class T> inline int operator<= (const T&lhs, const IA_Set<T>&rhs) {
    return IA_Set<T>(lhs) <= rhs;
}
template <class T> inline int operator== (const T&lhs, const IA_Set<T>&rhs) {
    return IA_Set<T>(lhs) == rhs;
}
template <class T> inline int operator>= (const T&lhs, const IA_Set<T>&rhs) {
    return rhs <= IA_Set<T>(lhs);
}
template <class T> inline int operator> (const T&lhs, const IA_Set<T>&rhs) {
    return rhs <IA_Set<T>(lhs);
}
template <class T> inline int operator!= (const T&lhs, const IA_Set<T>&rhs) {
    return !(IA_Set<T>(lhs) == rhs);
}

//
//

template <class T> inline int operator< (const IA_Set<T>&lhs, const T&rhs) {
    return lhs < IA_Set<T>(rhs);
}
template <class T> inline int operator<= (const IA_Set<T>&lhs, const T&rhs) {
    return lhs <= IA_Set<T>(rhs);
}
template <class T> inline int operator== (const IA_Set<T>&lhs, const T&rhs) {
    return lhs == IA_Set<T>(rhs);
}
template <class T> inline int operator>= (const IA_Set<T>&lhs, const T&rhs) {
    return IA_Set<T>(rhs) <= lhs ;
}
template <class T> inline int operator> (const IA_Set<T>&lhs, const T&rhs) {
    return IA_Set<T>(rhs) < lhs ;
}
template <class T> inline int operator!= (const IA_Set<T>&lhs, const T&rhs) {
    return !(lhs == IA_Set<T>(rhs)) ;
}

//
//
//

#if 1

 /* We shouldn't need these inlines, but template functions are still
    touchy under CFront */

template <class T> inline IA_Set<T> operator|(T lhs, const IA_Set<T> & rhs) {
    return IA_Set<T>(lhs)|rhs;
}

template <class T> inline IA_Set<T> operator&(T lhs, const IA_Set<T> & rhs) {
    return IA_Set<T>(lhs)&rhs;
}

template <class T> inline IA_Set<T> operator^(T lhs, const IA_Set<T> & rhs) {
    return IA_Set<T>(lhs)^rhs;
}

template <class T> inline IA_Set<T> operator/(T lhs, const IA_Set<T> & rhs) {
    return IA_Set<T>(lhs)/rhs;
}

//
//
//

template <class T> inline IA_Set<T> operator|(const IA_Set<T> & lhs, T rhs) {
    return lhs|IA_Set<T>(rhs);
}

template <class T> inline IA_Set<T> operator&(const IA_Set<T> & lhs, T rhs) {
    return lhs&IA_Set<T>(rhs);
}

template <class T> inline IA_Set<T> operator^(const IA_Set<T> & lhs, T rhs) {
    return lhs^IA_Set<T>(rhs);
}

template <class T> inline IA_Set<T> operator/(const IA_Set<T> & lhs, T rhs) {
    return lhs/IA_Set<T>(rhs);
}

#endif

#endif // Set_h_

//
//

#ifdef __CFRONT__

#ifndef SUPPRESS_INCLUDE
#include "IntPS.h"
#include "DblPS.h"
#endif

#endif // __CFRONT__
