You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

301 lines
8.8 KiB

25 years ago
25 years ago
25 years ago
25 years ago
  1. // General vectors.
  2. #ifndef _CL_GV_H
  3. #define _CL_GV_H
  4. #include "cln/object.h"
  5. #include "cln/V.h"
  6. #include "cln/abort.h"
  7. #include <stdlib.h>
  8. namespace cln {
  9. // A vector is a structure having the following interface:
  10. // v.length() returns the number of elements
  11. // v[i] returns the i-th element (0<=i<length), as a
  12. // pseudo-lvalue (you can assign to it, but not take its
  13. // address - exactly what you want for bit-vectors)
  14. // This is implemented by letting v[i] be of a special "vector index" type.
  15. template <class T> class cl_GV_inner;
  16. template <class T> class cl_GV_index;
  17. template <class T> class cl_GV_constindex;
  18. template <class T> struct cl_GV_vectorops;
  19. template <class T>
  20. class cl_GV_inner {
  21. protected:
  22. uintL len; // number of elements
  23. public:
  24. uintL length () const; // number of elements
  25. cl_GV_vectorops<T>* vectorops; // get/set element
  26. const cl_GV_index<T> operator[] (unsigned long index);
  27. const cl_GV_constindex<T> operator[] (unsigned long index) const;
  28. const cl_GV_index<T> operator[] (long index);
  29. const cl_GV_constindex<T> operator[] (long index) const;
  30. const cl_GV_index<T> operator[] (unsigned int index);
  31. const cl_GV_constindex<T> operator[] (unsigned int index) const;
  32. const cl_GV_index<T> operator[] (int index);
  33. const cl_GV_constindex<T> operator[] (int index) const;
  34. public: /* ugh */
  35. // Constructor.
  36. cl_GV_inner (uintL l, cl_GV_vectorops<T>* ops) : len (l), vectorops (ops) {}
  37. public:
  38. // Destructor.
  39. ~cl_GV_inner ();
  40. // Ability to place an object at a given address.
  41. void* operator new (size_t size, cl_GV_inner* ptr) { (void)size; return ptr; }
  42. private:
  43. // No default constructor, copy constructor, assignment operator, new.
  44. cl_GV_inner ();
  45. cl_GV_inner (const cl_GV_inner&);
  46. cl_GV_inner& operator= (const cl_GV_inner&);
  47. void* operator new (size_t size)
  48. { (void)size; return (void*)1; } // SGI CC needs this definition
  49. // Friend declarations. They are for the compiler. Just ignore them.
  50. friend class cl_GV_index<T>;
  51. friend class cl_GV_constindex<T>;
  52. };
  53. template <class T>
  54. class cl_GV_index {
  55. // This is the class of objects created by accessing a non-const vector
  56. // through [].
  57. public:
  58. cl_GV_inner<T>* vec;
  59. uintL index;
  60. operator T () const;
  61. // Constructor:
  62. cl_GV_index (cl_GV_inner<T>* v, uintL i) : vec (v), index (i) {}
  63. // Assignment operator.
  64. void operator= (const T& x) const;
  65. #if (defined(__sparc__) || defined(__sparc64__) || defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // maybe an SGI CC and Sun CC bug?
  66. void operator= (const cl_GV_index<T>&) const;
  67. void operator= (const cl_GV_constindex<T>&) const;
  68. #else
  69. private:
  70. // No assignment operator.
  71. cl_GV_index& operator= (const cl_GV_index&);
  72. #endif
  73. private:
  74. // No default constructor.
  75. cl_GV_index ();
  76. };
  77. template <class T>
  78. class cl_GV_constindex {
  79. // This is the class of objects created by accessing a const vector
  80. // through []. It lacks the assignment operator.
  81. public:
  82. const cl_GV_inner<T>* vec;
  83. uintL index;
  84. operator T () const;
  85. // Constructor:
  86. cl_GV_constindex (const cl_GV_inner<T>* v, uintL i) : vec (v), index (i) {}
  87. private:
  88. // No default constructor, assignment operator.
  89. cl_GV_constindex ();
  90. cl_GV_constindex& operator= (const cl_GV_constindex&);
  91. };
  92. template <class T>
  93. struct cl_GV_vectorops {
  94. const T (*element) (const cl_GV_inner<T>* vec, uintL index);
  95. void (*set_element) (cl_GV_inner<T>* vec, uintL index, const T& x);
  96. void (*do_delete) (cl_GV_inner<T>* vec);
  97. void (*copy_elements) (const cl_GV_inner<T>* srcvec, uintL srcindex, cl_GV_inner<T>* destvec, uintL destindex, uintL count);
  98. };
  99. // All member functions are inline.
  100. template <class T>
  101. inline uintL cl_GV_inner<T>::length () const
  102. {
  103. return len;
  104. }
  105. template <class T>
  106. inline const cl_GV_index<T> cl_GV_inner<T>::operator[] (unsigned long index)
  107. {
  108. return cl_GV_index<T>(this,index);
  109. }
  110. template <class T>
  111. inline const cl_GV_constindex<T> cl_GV_inner<T>::operator[] (unsigned long index) const
  112. {
  113. return cl_GV_constindex<T>(this,index);
  114. }
  115. template <class T>
  116. inline const cl_GV_index<T> cl_GV_inner<T>::operator[] (long index)
  117. {
  118. return operator[]((unsigned long)index);
  119. }
  120. template <class T>
  121. inline const cl_GV_constindex<T> cl_GV_inner<T>::operator[] (long index) const
  122. {
  123. return operator[]((unsigned long)index);
  124. }
  125. template <class T>
  126. inline const cl_GV_index<T> cl_GV_inner<T>::operator[] (unsigned int index)
  127. {
  128. return operator[]((unsigned long)index);
  129. }
  130. template <class T>
  131. inline const cl_GV_constindex<T> cl_GV_inner<T>::operator[] (unsigned int index) const
  132. {
  133. return operator[]((unsigned long)index);
  134. }
  135. template <class T>
  136. inline const cl_GV_index<T> cl_GV_inner<T>::operator[] (int index)
  137. {
  138. return operator[]((unsigned long)index);
  139. }
  140. template <class T>
  141. inline const cl_GV_constindex<T> cl_GV_inner<T>::operator[] (int index) const
  142. {
  143. return operator[]((unsigned long)index);
  144. }
  145. template <class T>
  146. inline cl_GV_inner<T>::~cl_GV_inner ()
  147. {
  148. vectorops->do_delete(this);
  149. }
  150. template <class T>
  151. inline cl_GV_index<T>::operator T () const
  152. {
  153. #ifndef CL_GV_NO_RANGECHECKS
  154. if (!(index < vec->len)) cl_abort();
  155. #endif
  156. return vec->vectorops->element(vec,index);
  157. }
  158. template <class T>
  159. inline void cl_GV_index<T>::operator= (const T& x) const
  160. {
  161. #ifndef CL_GV_NO_RANGECHECKS
  162. if (!(index < vec->len)) cl_abort();
  163. #endif
  164. vec->vectorops->set_element(vec,index,x);
  165. }
  166. template <class T>
  167. inline cl_GV_constindex<T>::operator T () const
  168. {
  169. #ifndef CL_GV_NO_RANGECHECKS
  170. if (!(index < vec->len)) cl_abort();
  171. #endif
  172. return vec->vectorops->element(vec,index);
  173. }
  174. #if (defined(__sparc__) || defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // maybe an SGI CC and Sun CC bug? handle "y[j] = x[i];"
  175. template <class T>
  176. inline void cl_GV_index<T>::operator= (const cl_GV_index<T>& x) const
  177. { operator= ((T) x); }
  178. template <class T>
  179. inline void cl_GV_index<T>::operator= (const cl_GV_constindex<T>& x) const
  180. { operator= ((T) x); }
  181. #endif
  182. // In memory, a vector looks like this:
  183. template <class T>
  184. struct cl_heap_GV : cl_heap {
  185. cl_GV_inner<T> v;
  186. // here room for the elements
  187. };
  188. // And a reference to a vector always looks like this:
  189. template <class T, class BASE>
  190. struct cl_GV : public BASE {
  191. public:
  192. // Length.
  193. uintL length () const
  194. {
  195. return ((const cl_heap_GV<T> *) pointer)->v.length();
  196. }
  197. // Reference. Forbid modification of `const cl_GV&' arguments.
  198. const cl_GV_constindex<T> operator[] (unsigned long index) const
  199. {
  200. return ((const cl_heap_GV<T> *) pointer)->v[index];
  201. }
  202. const cl_GV_index<T> operator[] (unsigned long index)
  203. {
  204. return ((cl_heap_GV<T> *) pointer)->v[index];
  205. }
  206. const cl_GV_constindex<T> operator[] (long index) const
  207. { return operator[]((unsigned long)index); }
  208. const cl_GV_index<T> operator[] (long index)
  209. { return operator[]((unsigned long)index); }
  210. const cl_GV_constindex<T> operator[] (unsigned int index) const
  211. { return operator[]((unsigned long)index); }
  212. const cl_GV_index<T> operator[] (unsigned int index)
  213. { return operator[]((unsigned long)index); }
  214. const cl_GV_constindex<T> operator[] (int index) const
  215. { return operator[]((unsigned long)index); }
  216. const cl_GV_index<T> operator[] (int index)
  217. { return operator[]((unsigned long)index); }
  218. // Copy constructor.
  219. cl_GV (const cl_GV&);
  220. // Assignment operator.
  221. cl_GV& operator= (const cl_GV&);
  222. // Copy a piece of a vector into another vector.
  223. // (Both vectors must be of the same type. Overlapping not allowed.)
  224. static void copy_elements (const cl_GV& src, uintL srcindex, cl_GV& dest, uintL destindex, uintL count)
  225. {
  226. const cl_heap_GV<T> * hsrc = (const cl_heap_GV<T> *) src.pointer;
  227. cl_heap_GV<T> * hdest = (cl_heap_GV<T> *) dest.pointer;
  228. if (!(hsrc->v.vectorops == hdest->v.vectorops))
  229. cl_abort();
  230. hsrc->v.vectorops->copy_elements(&hsrc->v,srcindex,&hdest->v,destindex,count);
  231. }
  232. // Private pointer manipulations.
  233. operator cl_heap_GV<T>* () const;
  234. cl_GV (cl_heap_GV<T>* p) : BASE ((cl_private_thing) p) {}
  235. cl_GV (cl_private_thing p) : BASE (p) {}
  236. protected:
  237. // Forbid use of default constructor.
  238. cl_GV ();
  239. };
  240. #define CL_GV(T,BASE) cl_GV<T,BASE>
  241. // Define copy constructor.
  242. template <class T, class BASE>
  243. _CL_DEFINE_COPY_CONSTRUCTOR2(CL_GV(T,BASE),cl_GV,BASE)
  244. // Define assignment operator.
  245. template <class T, class BASE>
  246. CL_DEFINE_ASSIGNMENT_OPERATOR(CL_GV(T,BASE),CL_GV(T,BASE))
  247. // Private pointer manipulations. Never throw away a `struct cl_heap_GV<T> *'!
  248. template <class T, class BASE>
  249. inline CL_GV(T,BASE)::operator cl_heap_GV<T>* () const
  250. {
  251. cl_heap_GV<T>* hpointer = (cl_heap_GV<T>*)pointer;
  252. cl_inc_refcount(*this);
  253. return hpointer;
  254. }
  255. #undef CL_GV
  256. // The "generic" general vector type.
  257. typedef cl_heap_GV<cl_gcobject> cl_heap_GV_any;
  258. typedef cl_GV<cl_gcobject,cl_V_any> cl_GV_any;
  259. // Hack section.
  260. // Conversions to subtypes without checking:
  261. #define The(type) *(const type *) & cl_identity
  262. // This inline function is for type checking purposes only.
  263. inline const cl_GV_any& cl_identity (const cl_GV_any& x) { return x; }
  264. } // namespace cln
  265. #endif /* _CL_GV_H */