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

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

// 
// $Log: BasePS.h,v $
// Revision 1.20  1993/11/17  18:02:03  thoth
// extensivep() is now extensive()
//
// Revision 1.19  1993/08/08  13:11:06  thoth
// deInline some of the fallback virtual functions.
//
// Revision 1.18  93/07/15  11:34:09  thoth
// eliminate cruft.
// Add support for iterator virtual method.
// 
// Revision 1.17  93/06/10  17:14:48  thoth
// *** empty log message ***
// 
// Revision 1.16  93/05/26  16:40:51  thoth
// Copyright Notices.
// 
// Revision 1.15  93/02/12  16:25:38  thoth
// more IA_ prefixes.
// more comments.
// 
// Revision 1.14  92/12/16  14:47:55  thoth
// conversion to IA_ mostly complete
// 
// Revision 1.13  92/12/07  12:05:07  thoth
// new IntPoint index(unsigned) operation for use with "other" iterators.
// 
// Revision 1.12  92/09/30  10:23:47  thoth
// BasePS is now templatized
// infimum & supremum virtuals now inf & sup
// contains now accepts const Point<>&
// type() system now based on address of static data member
// reference counts are protected from IntPointSet, unfortunately
// 
// Revision 1.11  92/09/20  17:37:31  thoth
// fixed spelling error
// 
// Revision 1.10  92/09/20  14:04:20  thoth
// new infimum and supremum methods for point sets.
// 
// Revision 1.9  92/09/03  13:29:58  thoth
// hash_self now deals with unsigneds
// offsetted is only valid for extensives
// lazy point sets now exist
// 
// Revision 1.8  92/08/26  13:41:58  thoth
// meaningful exception types
// 
// Revision 1.7  92/08/25  15:28:36  thoth
// new offsetted virtual functions
// 
// Revision 1.6  92/08/23  13:29:44  thoth
// CFrontified version
// 
// 

#ifndef BasePS_h_
#define BasePS_h_

#ifdef IA_PRII
#pragma interface
#endif

#include "ia.h"

#include "Point.h"

/*

  The BasePS class defines the interface for all PS objects derived
from it.  It has no information about implementation of classes
derived from it and therefore most of its virtual functions are
abstract.

  The functions that MUST be defined by each derived class are
abstract.

  A few of the virtual functions have bodies that throw.  This is
because most derived classes would also throw.  The default throw
prevents the duplication of code that would occurr if each were
abstract and every derived class would have to write its own version
that threw.

*/

typedef const char * IA_PointSetType;

template <class P>
class IA_BasePSIter;

template <class P_t>
class IA_BasePS {
private:
    int	refcount;
protected:
    unsigned		dimen;
public:
    // Take care of data members so derived classes don\'t have to worry.
    IA_BasePS(unsigned dim) { dimen = dim; refcount=0; }
    // Destructors can never be abstract.
    virtual ~IA_BasePS() {
	// nothing to clean up
    }
							
    // This method is for the hash table.  It returns true iff the BasePS*
    // points to an object of the same class as *this, and the other IPS
    // is structurally equivalent.
    virtual int equal(IA_BasePS*) const =0;

    // This method is for the hash table.  It returns a value that is
    // uniquely determined by the points in the point set.
    virtual unsigned hash_self(unsigned) const =0;

    // This function returns a number that is distinct to every non-abstract
    // class derived from us.  Please return the address of a static data
    // member.
    virtual IA_PointSetType type() const =0;

    // The dimensionality of the point set
    unsigned dim() const { return dimen; }

    // Returns nonzero iff the P_t is a member of the point set.
    virtual int contains(const P_t&) const =0;

    // Returns the index of the point inside the iteration order of
    // the pointset.  It is an error if the point is not contained.
    // It is an error if the point set is not extensive.
    virtual unsigned index(const P_t&) const;

    // And here is the inverse of the previous function
    virtual P_t index(unsigned) const;

    // Returns the lexicographically minimum point in the point set
    virtual P_t min() const;

    // Returns the lexicographically maximum point in the point set
    virtual P_t max() const;

    // The infimum of the pointset. (greatest lower bound)
    virtual P_t inf() const;

    // The supremum of the pointset. (least upper bound)
    virtual P_t sup() const;

    // returns a point in the point set.  Which point it returns is not
    // specified or guaranteed.
    // do we need this any more?
    virtual P_t choice() const;

    // returns a count of the number of points in the point set.
    virtual unsigned card() const {
	ia_throw(IA::PSET_REQUIRE_EXTENSIVE,__FILE__,__LINE__);
	return 0;
    }

    // returns true iff the point set contains no points
    virtual int empty() const {
	ia_throw(IA::PSET_REQUIRE_EXTENSIVE,__FILE__,__LINE__);
	return 0;
    }

    // Returns a pointer to something derived from BasePS allocated
    // on the heap.  The something is "similar" to this pointset, but
    // all the points are translated by the argument.
    virtual IA_BasePS * offsetted(const P_t &) const{
	// This should be defined to return a lazy by default.
	ia_throw(IA::PSET_REQUIRE_EXTENSIVE,__FILE__,__LINE__);
	return 0;
    }

    // Returns true if it is possible to iterate over this point set.
    // extensiveness implies many things.  Lack of extensiveness makes
    // the equal, hash_self, index, min, max, inf, sup, choice, card
    // and empty methods meaningless.
    virtual int extensive() const =0;

    // returns a pointer to an iterator over the pointset
    virtual IA_BasePSIter<P_t> *iterator() const {
	ia_throw(IA::PSET_REQUIRE_EXTENSIVE,__FILE__,__LINE__);
	return 0;
    }

    // A debugging function.
    virtual void output(ostream&, unsigned=0) const =0;

    // So anyone can frob the reference count.
    // Don\'t try this at home, kids.
    void enref() { refcount++; }
    int unref() { return --refcount; }
    // friend class PS_t;
};

#endif
