// General vectors. #ifndef _CL_GV_H #define _CL_GV_H #include "cln/object.h" #include "cln/V.h" #include "cln/abort.h" #include namespace cln { // A vector is a structure having the following interface: // v.length() returns the number of elements // v[i] returns the i-th element (0<=i class cl_GV_inner; template class cl_GV_index; template class cl_GV_constindex; template struct cl_GV_vectorops; template class cl_GV_inner { protected: uintL len; // number of elements public: uintL length () const; // number of elements cl_GV_vectorops* vectorops; // get/set element const cl_GV_index operator[] (unsigned long index); const cl_GV_constindex operator[] (unsigned long index) const; const cl_GV_index operator[] (long index); const cl_GV_constindex operator[] (long index) const; const cl_GV_index operator[] (unsigned int index); const cl_GV_constindex operator[] (unsigned int index) const; const cl_GV_index operator[] (int index); const cl_GV_constindex operator[] (int index) const; public: /* ugh */ // Constructor. cl_GV_inner (uintL l, cl_GV_vectorops* ops) : len (l), vectorops (ops) {} public: // Destructor. ~cl_GV_inner (); // Ability to place an object at a given address. void* operator new (size_t size, void* ptr) { (void)size; return ptr; } private: // No default constructor, copy constructor, assignment operator, new. cl_GV_inner (); cl_GV_inner (const cl_GV_inner&); cl_GV_inner& operator= (const cl_GV_inner&); void* operator new (size_t size) { (void)size; return (void*)1; } // SGI CC needs this definition // Friend declarations. They are for the compiler. Just ignore them. friend class cl_GV_index; friend class cl_GV_constindex; }; template class cl_GV_index { // This is the class of objects created by accessing a non-const vector // through []. public: cl_GV_inner* vec; uintL index; operator T () const; // Constructor: cl_GV_index (cl_GV_inner* v, uintL i) : vec (v), index (i) {} // Assignment operator. void operator= (const T& x) const; #if (defined(__sparc__) || defined(__sparc64__) || defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // maybe an SGI CC and Sun CC bug? void operator= (const cl_GV_index&) const; void operator= (const cl_GV_constindex&) const; #else private: // No assignment operator. cl_GV_index& operator= (const cl_GV_index&); #endif private: // No default constructor. cl_GV_index (); }; template class cl_GV_constindex { // This is the class of objects created by accessing a const vector // through []. It lacks the assignment operator. public: const cl_GV_inner* vec; uintL index; operator T () const; // Constructor: cl_GV_constindex (const cl_GV_inner* v, uintL i) : vec (v), index (i) {} private: // No default constructor, assignment operator. cl_GV_constindex (); cl_GV_constindex& operator= (const cl_GV_constindex&); }; template struct cl_GV_vectorops { const T (*element) (const cl_GV_inner* vec, uintL index); void (*set_element) (cl_GV_inner* vec, uintL index, const T& x); void (*do_delete) (cl_GV_inner* vec); void (*copy_elements) (const cl_GV_inner* srcvec, uintL srcindex, cl_GV_inner* destvec, uintL destindex, uintL count); }; // All member functions are inline. template inline uintL cl_GV_inner::length () const { return len; } template inline const cl_GV_index cl_GV_inner::operator[] (unsigned long index) { return cl_GV_index(this,index); } template inline const cl_GV_constindex cl_GV_inner::operator[] (unsigned long index) const { return cl_GV_constindex(this,index); } template inline const cl_GV_index cl_GV_inner::operator[] (long index) { return operator[]((unsigned long)index); } template inline const cl_GV_constindex cl_GV_inner::operator[] (long index) const { return operator[]((unsigned long)index); } template inline const cl_GV_index cl_GV_inner::operator[] (unsigned int index) { return operator[]((unsigned long)index); } template inline const cl_GV_constindex cl_GV_inner::operator[] (unsigned int index) const { return operator[]((unsigned long)index); } template inline const cl_GV_index cl_GV_inner::operator[] (int index) { return operator[]((unsigned long)index); } template inline const cl_GV_constindex cl_GV_inner::operator[] (int index) const { return operator[]((unsigned long)index); } template inline cl_GV_inner::~cl_GV_inner () { vectorops->do_delete(this); } template inline cl_GV_index::operator T () const { #ifndef CL_GV_NO_RANGECHECKS if (!(index < vec->len)) cl_abort(); #endif return vec->vectorops->element(vec,index); } template inline void cl_GV_index::operator= (const T& x) const { #ifndef CL_GV_NO_RANGECHECKS if (!(index < vec->len)) cl_abort(); #endif vec->vectorops->set_element(vec,index,x); } template inline cl_GV_constindex::operator T () const { #ifndef CL_GV_NO_RANGECHECKS if (!(index < vec->len)) cl_abort(); #endif return vec->vectorops->element(vec,index); } #if (defined(__sparc__) || defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // maybe an SGI CC and Sun CC bug? handle "y[j] = x[i];" template inline void cl_GV_index::operator= (const cl_GV_index& x) const { operator= ((T) x); } template inline void cl_GV_index::operator= (const cl_GV_constindex& x) const { operator= ((T) x); } #endif // In memory, a vector looks like this: template struct cl_heap_GV : cl_heap { cl_GV_inner v; // here room for the elements }; // And a reference to a vector always looks like this: template struct cl_GV : public BASE { public: // Length. uintL length () const { return ((const cl_heap_GV *) pointer)->v.length(); } // Reference. Forbid modification of `const cl_GV&' arguments. const cl_GV_constindex operator[] (unsigned long index) const { return ((const cl_heap_GV *) pointer)->v[index]; } const cl_GV_index operator[] (unsigned long index) { return ((cl_heap_GV *) pointer)->v[index]; } const cl_GV_constindex operator[] (long index) const { return operator[]((unsigned long)index); } const cl_GV_index operator[] (long index) { return operator[]((unsigned long)index); } const cl_GV_constindex operator[] (unsigned int index) const { return operator[]((unsigned long)index); } const cl_GV_index operator[] (unsigned int index) { return operator[]((unsigned long)index); } const cl_GV_constindex operator[] (int index) const { return operator[]((unsigned long)index); } const cl_GV_index operator[] (int index) { return operator[]((unsigned long)index); } // Copy constructor. cl_GV (const cl_GV&); // Assignment operator. cl_GV& operator= (const cl_GV&); // Copy a piece of a vector into another vector. // (Both vectors must be of the same type. Overlapping not allowed.) static void copy_elements (const cl_GV& src, uintL srcindex, cl_GV& dest, uintL destindex, uintL count) { const cl_heap_GV * hsrc = (const cl_heap_GV *) src.pointer; cl_heap_GV * hdest = (cl_heap_GV *) dest.pointer; if (!(hsrc->v.vectorops == hdest->v.vectorops)) cl_abort(); hsrc->v.vectorops->copy_elements(&hsrc->v,srcindex,&hdest->v,destindex,count); } // Private pointer manipulations. operator cl_heap_GV* () const; cl_GV (cl_heap_GV* p) : BASE ((cl_private_thing) p) {} cl_GV (cl_private_thing p) : BASE (p) {} protected: // Forbid use of default constructor. cl_GV (); }; #define CL_GV(T,BASE) cl_GV // Define copy constructor. template _CL_DEFINE_COPY_CONSTRUCTOR2(CL_GV(T,BASE),cl_GV,BASE) // Define assignment operator. template CL_DEFINE_ASSIGNMENT_OPERATOR(CL_GV(T,BASE),CL_GV(T,BASE)) // Private pointer manipulations. Never throw away a `struct cl_heap_GV *'! template inline CL_GV(T,BASE)::operator cl_heap_GV* () const { cl_heap_GV* hpointer = (cl_heap_GV*)pointer; cl_inc_refcount(*this); return hpointer; } #undef CL_GV // The "generic" general vector type. typedef cl_heap_GV cl_heap_GV_any; typedef cl_GV cl_GV_any; // Hack section. // Conversions to subtypes without checking: #define The(type) *(const type *) & cl_identity // This inline function is for type checking purposes only. inline const cl_GV_any& cl_identity (const cl_GV_any& x) { return x; } } // namespace cln #endif /* _CL_GV_H */