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

bag.h

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

Click here to get the file

Size 12.1 kB - File type text/plain

File contents

/*ident	"@(#)Set:incl/bag.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 BAGH
#define BAGH

//  The following include is required so that the instantiation
//  files that include bag.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 Bag_internal_item_ATTLCs.

static const int BAG_NODE_SIZE_ATTLC = 16;
static const int BAG_POSITIONS_ATTLC = 8;
static const int BAG_MASK_BITS_ATTLC = 0XF;
static const int BAG_INITIAL_SHIFT_ATTLC = 0;
static const int BAG_SHIFT_INCR_ATTLC = 4;

extern int BAG_LT_ATTLC(Set_or_Bag_hashval a,Set_or_Bag_hashval b);

//  Index to non-parametric classes:

class Bag_bucket_non_param_ATTLC;
class Bag_internal_item_ATTLC;
class Bag_internal_node_ATTLC;
class Bag_position_ATTLC;

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

class Bag_select_ATTLC;
class Bag_reject_ATTLC;
class Bag_map_ATTLC;
class Bag_union_ATTLC;
class Bag_inter_ATTLC;
class Bag_diff_ATTLC;
class Bag_xor_ATTLC;

extern Pool* bag_internal_node_pool_ptr_ATTLC;

struct Bag_bucket_non_param_ATTLC {
    Set_or_Bag_hashval hashval;
};

struct Bag_internal_item_ATTLC {
    //  An Bag_internal_item_ATTLC is a single "slot" in an
    //  Bag_internal_node_ATTLC.  It may contain:
    //
    //	o  An Bag_internal_node_ATTLC*
    //	o  A Bag_bucket_non_param_ATTLC*
    //	o  NULL
    //
    //  Bag_bucket_non_param_ATTLC* and Bag_internal_node_ATTLC* 
    //  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 Bag_bucket_non_param_ATTLC*
    //
    //   o  When the low order bit is 0, the item
    //	is a Bag_internal_node_ATTLC* or NULL.

    union {
	void* ext_leaf;
	Bag_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 Bag_internal_node_ATTLC* next_node() const;
    inline void* external_leaf() const;
    inline void make_leaf(void*);
    inline void make_node(Bag_internal_node_ATTLC*);
    inline void make_null();

    void show(int) const;
};

struct Bag_internal_node_ATTLC {
    //  A Bag_internal_node_ATTLC has 16 Internal_slots
    //  plus a count of how many are in use.
    //  Each Internal_slot is directly indexed
    //  by a 4-bit chunk.

    static void initialize();
    Bag_internal_item_ATTLC item[BAG_NODE_SIZE_ATTLC];
    int	busy_count;
    Bag_internal_node_ATTLC();
    inline ~Bag_internal_node_ATTLC();
    void* operator new(size_t);
    inline void operator delete(void*);
    void show(int) const;
};

struct Bag_position_ATTLC {
    //  A Bag_position_ATTLC 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
    //	   Bag_internal_item_ATTLCs which remembers a
    //	   path of Bag_internal_item_ATTLCs through the
    //	   index:
    //
    //	   o  curr_pos[0] points to the Bag_internal_item_ATTLC
    //		selected by the first 4 bit chunk
    //
    //	   o  curr_pos[1] points to the Bag_internal_item_ATTLC
    //		selected by the second 4 bit chunk
    //
    //	   o  curr_pos[curr_depth] points to the
    //		Bag_internal_item_ATTLC which points to
    //		a Bucket<TYPE>
    //
    //  If Bag mutation occurs, a Bag_position_ATTLC 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
    //

    Bag_internal_item_ATTLC* curr_pos[BAG_POSITIONS_ATTLC];
    int curr_depth;
    Set_or_Bag_hashval curr_value;
    inline Bag_position_ATTLC();
    void show() const;
};

//  Bag_internal_item_ATTLC inlines

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

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

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

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

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

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

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

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

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

//  Bag_internal_node_ATTLC inlines

void
Bag_internal_node_ATTLC::operator delete(void* p)
{
    bag_internal_node_pool_ptr_ATTLC->free(p);
}

Bag_internal_node_ATTLC::~Bag_internal_node_ATTLC()
{
}

//  Bag_position_ATTLC inlines

Bag_position_ATTLC::Bag_position_ATTLC(): curr_depth(-1), curr_value(0)
{
}


//  The following are for public consumption
#ifdef __GNUG__
#pragma interface
#endif

template <class T> class Bag_pair;
template <class T> class Bag_bucket_ATTLC;
template <class T> class Bag_bucketiter_ATTLC;
template <class T> class Bagiter;
template <class T> class Bag;

//  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 pairs of
//	   (values,count) pairs such that the value
//	   hashes to hashval
//
//  Note that ALIGN values in the original version
//  become Bag_bucket_ATTLC<T>* values in this version.
//

template <class T>
struct Bag_pair {
    T value;
    unsigned count;
    int operator==(const Bag_pair<T>& b) {
	return (b.value==value && b.count==count);
    }
};


template <class T>
struct Bag_bucket_ATTLC : public Bag_bucket_non_param_ATTLC {
    List< Bag_pair<T> > collision_list;
    void show() const;
};

template <class T>
class Bag_bucketiter_ATTLC {
    friend class Bag<T>;
protected:
    Bag<T>* my_bag;
    Bag_bucketiter_ATTLC<T>* next_it;
    Bag_position_ATTLC pos;
public:
    Bag_bucketiter_ATTLC(const Bag<T>&);
    Bag_bucketiter_ATTLC(const Bag_bucketiter_ATTLC<T>&);
    ~Bag_bucketiter_ATTLC();
    const Bag_bucket_ATTLC<T>* first();
    const Bag_bucket_ATTLC<T>* next();
    Bag_bucketiter_ATTLC& operator=(const Bag_bucketiter_ATTLC<T>&);
    void clobber() {
	pos.curr_depth = -1;
    }
};

template <class T>
class Bagiter : public Bag_bucketiter_ATTLC<T> {
private:
    int inited;
    Listiter< Bag_pair<T> >* itp;
public:
    Bagiter(const Bag<T>& b)
	: Bag_bucketiter_ATTLC<T>(b), inited(0), itp(0) {}
    Bagiter(const Bagiter<T>& bi)
	: Bag_bucketiter_ATTLC<T>(bi), inited(0), itp(0) {}
    ~Bagiter() {
	if (itp)
	    delete itp;
    }
    const Bag_pair<T>* first();
    const Bag_pair<T>* next();
    int next(const Bag_pair<T>*& t) {
	t = next();
	return t!=0;
    }
    void reset() {
	inited=0;
    }
    const Bag<T>* the_bag() const {
	return my_bag;
    }
    Bagiter<T>& operator=(const Bagiter<T>& bi) {
    	return (Bagiter<T>&)((Bag_bucketiter_ATTLC<T>&)(*this) =
			 (const Bag_bucketiter_ATTLC<T>&)bi);
    }
};


template <class T>
class Bag {
    friend class Bag_bucketiter_ATTLC<T>;
    friend class Bagiter<T>;

private:
    int sze;
    int	sze_unique;
    Bag_internal_item_ATTLC contents;
    Bag_bucketiter_ATTLC<T>* iter_head;
    Bag_position_ATTLC pos;

//  The following functions are only used
//  on empty Bags

    void make_setlogic(const Bag<T>&, const Bag<T>&, int);
    Bag(const Bag<T>&, const Bag<T>&, Bag_union_ATTLC*);
    Bag(const Bag<T>&, const Bag<T>&, Bag_inter_ATTLC*);
    Bag(const Bag<T>&, const Bag<T>&, Bag_diff_ATTLC*);
    Bag(const Bag<T>&, const Bag<T>&, Bag_xor_ATTLC*);
    void warn_iterators() const;

public:

//  Constructors

    Bag();
    Bag(const T&);
    Bag(const T&, const T&);
    Bag(const T&, const T&, const T&);
    Bag(const T&, const T&, const T&, const T&);
    Bag(const Bag<T>&);
    ~Bag();

//  Size

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

//  Assignment

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

//  Relations

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

//  Membership

    const Bag_pair<T>* contains(const T&) const;
    unsigned int count(const T&) const;

//  Insert and Remove elements

    const Bag_pair<T>* insert(const T&, int count=1);
    unsigned int remove(const T&, int count=1);
    unsigned int remove_all(const T&);
    unsigned int remove_all();

//  Select an arbitrary element

    const Bag_pair<T>* select() const;

//  Bag algebra

    Bag<T> operator|(const Bag<T>& b) const {
	return Bag<T>(*this,b,(Bag_union_ATTLC*)0);
    }
    Bag<T> operator-(const Bag<T>& b) const {
	return Bag<T>(*this, b,(Bag_diff_ATTLC*)0);
    }
    Bag<T> operator&(const Bag<T>& b) const {
	return Bag<T>(*this,b,(Bag_inter_ATTLC*)0);
    }
    Bag<T> operator^(const Bag<T>& b) const {
	return Bag<T>(*this,b,(Bag_xor_ATTLC*)0);
    }
    Bag<T>& operator|=(const Bag<T>&);
    Bag<T>& operator-=(const Bag<T>&);
    Bag<T>& operator&=(const Bag<T>&);
    Bag<T>& operator^=(const Bag<T>&);

//  Performance tuning

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

//  Debugging

    void check() const;
    void show() const;

//  Hash function

    static Set_or_Bag_hashval hash(const T&);

    ostream& print(ostream&) const;
};

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

template <class T>
Set_or_Bag_hashval
Bag<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 Bag_bucket_ATTLC<T>::show() const
{
    cout << "    hashval=" << hashval << "\n";
    cout << "    collision_list=";
    Listiter< Bag_pair<T> > it(collision_list);
    int first=1;
    cout << "<";

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

	Bag_pair<T>* result;
	it.next(result);
	cout << "(" << result->count << ","  << result->value << ")";
    }
    cout << ">\n";
}

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

#endif

template <class T>
ostream&
operator<<(ostream& os,const Bag<T>& b)
{
    Bag_bucketiter_ATTLC<T> bi(b);
    const Bag_bucket_ATTLC<T>* bp = bi.first();
    os << "{";

    while ( bp ) {
	Listiter< Bag_pair<T> > li(((Bag_bucket_ATTLC<T>*)bp)->collision_list);

	while ( !li.at_end() ) {
	    Bag_pair<T>* tp;
	    li.next(tp);
	    os 	<< "("
		<< tp->count
		<< ","
		<< tp->value
		<< ")"
	    ;
	}
	bp = bi.next();
    }
    os << "}";
    return os;
}

#if (defined(__edg_att_40) || defined(__GNUG__)) && !defined(__IMPLICIT_INCLUDE)
#include <bag.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: