Personal tools
You are here: Home Projects C++ Cfront releases Release 3.0.3 source incl-master const-headers set.h
Document Actions

set.h

by Michael L Powell last modified 2007-01-26 03:20

Click here to get the file

Size 12.8 kB - File type text/plain

File contents

/*ident	"@(#)Set:incl/set.h	3.1" */
/******************************************************************************
*
* C++ Standard Components, Release 3.0.
*
* Copyright (c) 1991, 1992 AT&T and Unix System Laboratories, Inc.
* Copyright (c) 1988, 1989, 1990 AT&T.  All Rights Reserved.
*
* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T and Unix System
* Laboratories, Inc.  The copyright notice above does not evidence
* any actual or intended publication of such source code.
*
******************************************************************************/

#ifndef SETH
#define SETH

//  The following include is required so that the instantiation
//  files that include set.h will get what they need from Set.h

#include <Set.h>

class ostream;

//  The 32 bits of a Set_or_Bag_hashval are broken into
//  8 4-bit groups.  Each 4-bit group indexes
//  into a Internal_node of 16 Internal_items.

static const int SET_NODE_SIZE_ATTLC = 16;
static const int SET_POSITIONS_ATTLC = 8;
static const int SET_MASK_BITS_ATTLC = 0XF;
static const int SET_INITIAL_SHIFT_ATTLC = 0;
static const int SET_SHIFT_INCR_ATTLC = 4;

extern int SET_LT_ATTLC( Set_or_Bag_hashval a, Set_or_Bag_hashval b );

struct Space_info_ATTLC {
    int max_level;			// max depth of tree
    long node_count;			// total nodes
    long leaf_count;    		// total leaves
    long overhead;			// size of data structure
    int leaves[SET_POSITIONS_ATTLC];	// leaves at each level
    int occupancy[SET_POSITIONS_ATTLC]; // non-null items at each level
};

//  Index to non-parametric classes:

class Set_bucket_non_param_ATTLC;
class Internal_item_ATTLC;
class Internal_node_ATTLC;
class Position_ATTLC;

//  The following ATTLC class declarations are
//  needed to disambiguate the copy-avoidance
//  constructors:

class Set_select_ATTLC;
class Set_reject_ATTLC;
class Set_map_ATTLC;
class Set_union_ATTLC;
class Set_inter_ATTLC;
class Set_diff_ATTLC;
class Set_xor_ATTLC;

extern Pool* internal_node_pool_ptr_ATTLC;

struct Set_bucket_non_param_ATTLC {
    Set_or_Bag_hashval hashval;
};

struct Internal_item_ATTLC
{
    //  An Internal_item is a single "slot" in an
    //  Internal_node.  It may contain:
    //
    //	o  An Internal_node*
    //	o  A Set_bucket_non_param_ATTLC*
    //	o  NULL
    //
    //  Set_bucket_non_param_ATTLC* and Internal_node* pointers 
    //  can't be byte-aligned, so the low order bit is free to
    //  be used as the union discriminant.
    //
    //   o  When the low-order bit is 1, the item
    //	    is a Set_bucket_non_param_ATTLC*
    //
    //   o  When the low order bit is 0, the item
    //	    is a Internal_node* or NULL.

    union {
	void* ext_leaf;
	Internal_node_ATTLC* nodep;
	long this_is_leaf;
    };
    inline int is_leaf_or_null() const;

    inline int is_node() const;
    inline int is_leaf() const;
    inline int is_null() const;
    inline Internal_node_ATTLC* next_node() const;
    inline void* external_leaf() const;
    inline void make_leaf(void*);
    inline void make_node(Internal_node_ATTLC*);
    inline void make_null();

    void show(int) const;
    void space(int,Space_info_ATTLC&) const;
};

struct Internal_node_ATTLC {
    //  A Internal_node has SET_NODE_SIZE_ATTLC Internal_items
    //  plus a count of how many of these are in use.
    //  Each Internal_item is directly indexed
    //  by a lg(SET_NODE_SIZE_ATTLC) chunk.

    static void initialize();
    Internal_item_ATTLC item[SET_NODE_SIZE_ATTLC];
    int busy_count;
    Internal_node_ATTLC();
    inline ~Internal_node_ATTLC();
    void* operator new(size_t);
    inline void operator delete(void*);
    void show(int) const;
    void space(int,Space_info_ATTLC&) const;
};

struct Position_ATTLC {
    //  A Position caches the result of the most
    //  recent search, down to the level of the
    //  Bucket:
    //
    //	o  curr_value is the Set_or_Bag_hashval that we
    //	   searched for
    //
    //	o  curr_pos is a stack of pointers to
    //	   Internal_items which remembers a
    //	   path of Internal_items through the
    //	   index:
    //
    //	   o  curr_pos[0] points to the Internal_item
    //	      selected by the first 4 bit chunk
    //
    //	   o  curr_pos[1] points to the Internal_item
    //	      selected by the second 4 bit chunk
    //
    //	   o  curr_pos[curr_depth] points to the
    //	      Internal_item which points to
    //	      a Bucket_ATTLC(T)
    //
    //  If set mutation occurs, a Position is
    //  canceled by setting its curr_depth to -1;
    //  curr_value can be used subsequently to rebuild
    //  the cur_pos stack so that iteration can resume
    //

    Internal_item_ATTLC* curr_pos[SET_POSITIONS_ATTLC];
    int curr_depth;
    Set_or_Bag_hashval curr_value;

    inline Position_ATTLC();
    void show() const;
};

//  Internal_item inlines

int
Internal_item_ATTLC::is_leaf_or_null() const
{
    return this_is_leaf & 01;
}

int
Internal_item_ATTLC::is_node() const
{
    return !is_leaf_or_null() && nodep;
}

int
Internal_item_ATTLC::is_leaf() const
{
    return is_leaf_or_null() && ((long)ext_leaf & ~(long)01);
}

int
Internal_item_ATTLC::is_null() const
{
    return !nodep;
}

Internal_node_ATTLC*
Internal_item_ATTLC::next_node() const
{
#ifdef DEBUG_ATTLC
    assert(is_node());
#endif
    return nodep;
}

void*
Internal_item_ATTLC::external_leaf() const
{
#ifdef DEBUG_ATTLC
    assert(is_leaf());
#endif
    return (void*)((long)ext_leaf & ~(long)01);
}

void
Internal_item_ATTLC::make_leaf(void* p)
{
#ifdef DEBUG_ATTLC
    assert(((long)p & 01) == 0);
#endif
    ext_leaf = (void*)((long)p | 01);
}

void
Internal_item_ATTLC::make_node(Internal_node_ATTLC* cp)
{
#ifdef DEBUG_ATTLC
    assert(((long)cp & 01) == 0);
#endif
    nodep = cp;
}

void
Internal_item_ATTLC::make_null()
{
    nodep = 0;
}

//  Internal_node inlines

void
Internal_node_ATTLC::operator delete(void* p)
{
    internal_node_pool_ptr_ATTLC->free(p);
}

Internal_node_ATTLC::~Internal_node_ATTLC()
{
}

//  Position inlines

Position_ATTLC::Position_ATTLC() : curr_depth(-1), curr_value(0)  //  curr_value probably not needed
{
}


#ifdef __GNUG__
#pragma interface
#endif

template <class T> class Bucket_ATTLC;
template <class T> class Bucketiter_ATTLC;

//  The following classes are for public consumption:

template <class T> class Setiter;
template <class T> class Set;

//  Each leaf item in the tree-structured index
//  points to a pair of values:
//
//	o  'hashval' is the hash key
//	o  'collision_list' is a list of values which
//	   hash to hashval
//
//  Note that ALIGN values in the original version
//  become Bucket_ATTLC<T>* values in this version.
//

template <class T>
struct Bucket_ATTLC : public Set_bucket_non_param_ATTLC
{
    List<T> collision_list;
    void show() const;
};

template <class T>
class Bucketiter_ATTLC
{
    friend class Set<T>;
protected:
    Set<T>* my_set;
    Bucketiter_ATTLC<T>* next_it;
    Position_ATTLC pos;
public:
    Bucketiter_ATTLC(const Set<T>&);
    Bucketiter_ATTLC(const Bucketiter_ATTLC<T>&);
    ~Bucketiter_ATTLC();
    const Bucket_ATTLC<T>* first();
    const Bucket_ATTLC<T>* next();
    void clobber() { pos.curr_depth = -1; }
    Bucketiter_ATTLC<T>& operator=(const Bucketiter_ATTLC<T>&);
};

//  This class must be modified to use
//  Bucketiter_ATTLC<T>(*this).first() and next().

template <class T>
class Setiter : public Bucketiter_ATTLC<T>
{
private:
    int inited;					// new
    Listiter<T>* itp;
public:
    const Set<T>* the_set() const {	// new
	return my_set;
    }
    Setiter(const Set<T>& s)
	: Bucketiter_ATTLC<T>(s), inited(0), itp(0) {}
    Setiter(const Setiter<T>& si)
	: Bucketiter_ATTLC<T>(*(si.the_set())), inited(0), itp(0) {}
    ~Setiter() {
	if (itp)
	    delete itp;
    }
    const T* first();			// undocumented - TBD_make private
    const T* next();			// subsumes first, next
    int next(const T*& t) {		// new
	t = next();
	return t!=0;
    }
    void reset() {			// new semantics
	inited=0;
    }
    Setiter<T>& operator=(const Setiter<T>& si) {
	return (Setiter<T>&)((Bucketiter_ATTLC<T>&)*this =
			     (const Bucketiter_ATTLC<T>&)si);
    }
};

template <class T>
class Set
{
    friend class Bucketiter_ATTLC<T>;
    friend class Setiter<T>;
private:
    int sze;
    Internal_item_ATTLC contents;
    Bucketiter_ATTLC<T>* iter_head;	// was Setiter<T>
    Position_ATTLC pos;			// was Position<T>

//  The following are only used on empty sets

    void make_setlogic(const Set<T>&, const Set<T>&, int);

    Set(const Set<T>&, const Set<T>&, Set_union_ATTLC*);
    Set(const Set<T>&, const Set<T>&, Set_inter_ATTLC*);
    Set(const Set<T>&, const Set<T>&, Set_diff_ATTLC*);
    Set(const Set<T>&, const Set<T>&, Set_xor_ATTLC*);
    void warn_iterators() const;

public:

//  Constructors

    Set() : sze(0), iter_head(0) {
	pos.curr_depth = -1;
	contents.make_null();
    }
    Set(const T&);
    Set(const T&, const T&);
    Set(const T&, const T&, const T&);
    Set(const T&, const T&, const T&, const T&);
    Set(const Set<T>&);
    ~Set();

//  Size

    unsigned int size() const {
	return (unsigned)sze;
    }
    unsigned int size_unique() const {
	return (unsigned)sze;
    }
    operator const void*() const {
	return (size()? (this): (0));
    }

//  Assignment

    Set<T>& operator=(const Set<T>&);

//  Relations

    int operator==(const Set<T>& b) const {
	return containment(b, 0);
    }
    int operator!=(const Set<T>& s) const {
	return !(*this == s);
    }
    int operator<=(const Set<T>& b) const {
	return containment(b, 1);
    }
    int operator<(const Set<T>& b) const {
	return containment(b, 2);
    }
    int operator>=(const Set<T>& s) const {
	return s <= *this;
    }
    int operator>(const Set<T>& s) const {
	return s < *this;
    }
private:
    int containment(const Set<T>&, int) const;
public:

//  Membership

    const T* contains(const T&) const;
    unsigned int count(const T& t) const {
	return contains(t)?1:0;
    }

//  Insert and Remove elements

    const T* insert(const T&, int=1);
    unsigned remove(const T&, int=1);
    unsigned remove_all(const T& t) {
	return remove(t);
    }
    unsigned remove_all();

//  Select an arbitrary element

    const T* select() const;

//  Set algebra

    Set<T> operator|(const Set<T>& s) const {
	return Set<T>(*this,s,(Set_union_ATTLC*)0);
    }
    Set<T> operator-(const Set<T>& s) const {
	return Set<T>(*this, s,(Set_diff_ATTLC*)0);
    }
    Set<T> operator&(const Set<T>& s) const {
	return Set<T>(*this,s,(Set_inter_ATTLC*)0);
    }
    Set<T> operator^(const Set<T>& s) const {
	return Set<T>(*this,s,(Set_xor_ATTLC*)0);
    }
    Set<T>& operator|=(const Set<T>&);
    Set<T>& operator-=(const Set<T>&);
    Set<T>& operator&=(const Set<T>&);
    Set<T>& operator^=(const Set<T>&);

//  Performance tuning

    void histogram(Map<Set_or_Bag_hashval, unsigned>&) const;

//  Debugging, performance tuning

    void check() const;
    void show() const;
    Space_info_ATTLC space() const;

//  Hash function

    static Set_or_Bag_hashval hash(const T&);	// user specializes if needed

    ostream& print(ostream&) const;
};

template <class T>
ostream&
operator<<(ostream&, const Set<T>&);

template <class T>
Set_or_Bag_hashval
Set<T>::hash(const T&)
{
    return 0;
}


// Debugging code - don't want to require including <iostream.h>
// Developer can uncomment for debugging

#if 0
template <class T>
void Bucket_ATTLC<T>::show() const
{
    cout << "    hashval=" << hashval << "\n";
    cout << "    collision_list=";
    Listiter<T> it(collision_list);
    int first=1;
    cout << "<";

    while(!it.at_end()) {
	if ( first )
	    first=0;
	else
	    cout << ",";

	cout << it.next();
    }
    cout << ">\n";
}

template <class T>
static void showiter(Listiter<T>* itp)
{
    T e;

    if ( itp ) {
	if ( itp->peek_prev(e) )
	    cout << e;
	else
	    cout << "*";

	if ( itp->peek_next(e) )
	    cout << e;
	else
	    cout << "*";

	cout << ">\n";
    }
    else
	cout << "0";
}

template <class T>
void
Set<T>::show() const
{
    cout << "sze = " << sze << "\n";
    cout << "pos =\n";
    pos.show();
    cerr << "contents =\n";
    contents.show(0);
}

template <class T>
Space_info_ATTLC
Set<T>::space() const
{
    //  contents is level 0; the first node is level 1, etc.

    Space_info_ATTLC result;
    result.max_level = -1;
    result.node_count = 0;
    result.leaf_count = 0;

    if( !contents.is_null() ) {
	int i;
	for ( i=0 ; i<SET_POSITIONS_ATTLC ; i++) {
	    result.leaves[i] = 0;
	    result.occupancy[i] = 0;
	}
	result.occupancy[0] = 1;
	contents.space(0,result);
    }
    result.overhead = (sizeof(Internal_item_ATTLC) +
		       result.node_count * sizeof(Internal_node_ATTLC));
    return result;
}

#endif

template <class T>
ostream& operator<<(ostream& os, const Set<T>& s)
{
    os << "{";
    Setiter<T> it(s);
    const T* tp;
    int first=1;

    while( tp = it.next() ) {
	if ( first )
	    first=0;
	else
	    os << ",";

	os << *tp;
    }
    os << "}";
    return os;
}

#if (defined(__edg_att_40) || defined(__GNUG__)) && !defined(__IMPLICIT_INCLUDE)
#include <set.c>
#endif
#endif
« April 2024 »
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: