source: git/ntl/include/NTL/vector.h @ 77902f

spielwiese
Last change on this file since 77902f was 77902f, checked in by Hans Schönemann <hannes@…>, 21 years ago
*hannes: iostream adaption git-svn-id: file:///usr/local/Singular/svn/trunk@6321 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 10.1 KB
Line 
1
2#ifndef NTL_vector__H
3#define NTL_vector__H
4
5#include <NTL/tools.h>
6
7struct _ntl_VectorHeader {
8   long length;
9   long alloc;
10   long init;
11   long fixed;
12};
13
14union _ntl_AlignedVectorHeader {
15   _ntl_VectorHeader h;
16   double x1;
17   long x2;
18   char *x3;
19};
20
21#define NTL_VECTOR_HEADER_SIZE (sizeof(_ntl_AlignedVectorHeader))
22
23#define NTL_VEC_HEAD(p) (& (((_ntl_AlignedVectorHeader *) p)[-1].h))
24
25struct _ntl_vector_placement {
26   void *p;
27};
28
29inline _ntl_vector_placement _ntl_vector_placement_fn(void *p)
30{
31   _ntl_vector_placement x;
32   x.p = p;
33   return x;
34}
35
36inline void *operator new(NTL_SNS size_t, _ntl_vector_placement x) { return x.p; }
37
38// All of this monkey business is to avoid possible clashes with
39// a "placement new" operator which may or may not be defined
40// in a standard header file....why wasn't this just built
41// into the language to begin with?
42
43#ifndef NTL_RANGE_CHECK
44#define NTL_RANGE_CHECK_CODE
45#else
46#define NTL_RANGE_CHECK_CODE if (l__i < 0 || !_vec__rep || l__i >= NTL_VEC_HEAD(_vec__rep)->length) RangeError(l__i);
47#endif
48
49// vectors are allocated in chunks of this size
50
51#ifndef NTL_VectorMinAlloc
52#define NTL_VectorMinAlloc (4)
53#endif
54
55// vectors are always expanded by at least this ratio
56
57#ifndef NTL_VectorExpansionRatio
58#define NTL_VectorExpansionRatio (1.2)
59#endif
60
61// controls initialization during input
62
63#ifndef NTL_VectorInputBlock
64#define NTL_VectorInputBlock 50
65#endif
66
67
68#define NTL_vector_default(T)   \
69void BlockConstruct(T* l__p, long l__n)  \
70{  \
71   long l__i;  \
72  \
73   for (l__i = 0; l__i < l__n; l__i++)  \
74      (void) new(_ntl_vector_placement_fn(&l__p[l__i])) T;  \
75}  \
76  \
77void BlockDestroy(T* l__p, long l__n)  \
78{  \
79   long l__i;  \
80  \
81   for (l__i = 0; l__i < l__n; l__i++)  \
82      l__p[l__i].~T();  \
83}
84
85
86
87#define NTL_vector_decl(T,vec_T)  \
88class vec_T {  \
89public:  \
90   T *_vec__rep;  \
91  \
92   void RangeError(long l__i) const;  \
93  \
94   vec_T() { _vec__rep = 0; }  \
95   vec_T(NTL_NNS INIT_SIZE_TYPE, long l__n) { _vec__rep = 0; SetLength(l__n); }  \
96   vec_T(const vec_T& l__a) { _vec__rep = 0; *this = l__a; }     \
97   vec_T& operator=(const vec_T& l__a);  \
98   ~vec_T();  \
99   void kill(); \
100  \
101   void SetLength(long l__n);  \
102   void SetMaxLength(long l__n); \
103   void FixLength(long l__n); \
104   void QuickSetLength(long l__n) { NTL_VEC_HEAD(_vec__rep)->length = l__n; } \
105  \
106   long length() const { return (!_vec__rep) ?  0 : NTL_VEC_HEAD(_vec__rep)->length; }  \
107   long MaxLength() const { return (!_vec__rep) ?  0 : NTL_VEC_HEAD(_vec__rep)->init; } \
108   long fixed() const { return _vec__rep && NTL_VEC_HEAD(_vec__rep)->fixed; } \
109  \
110   T& operator[](long l__i)   \
111   {  \
112      NTL_RANGE_CHECK_CODE  \
113      return _vec__rep[l__i];  \
114   }  \
115  \
116   const T& operator[](long l__i) const \
117   {  \
118      NTL_RANGE_CHECK_CODE  \
119      return _vec__rep[l__i];  \
120   }  \
121  \
122   T& RawGet(long l__i)   \
123   {  \
124      return _vec__rep[l__i];  \
125   }  \
126  \
127   const T& RawGet(long l__i) const \
128   {  \
129      return _vec__rep[l__i];  \
130   }  \
131  \
132   T& operator()(long l__i) { return (*this)[l__i-1]; }  \
133   const T& operator()(long l__i) const { return (*this)[l__i-1]; } \
134   \
135  \
136   const T* elts() const { return _vec__rep; }  \
137   T* elts() { return _vec__rep; }  \
138         \
139 \
140   vec_T(vec_T& l__x, NTL_NNS INIT_TRANS_TYPE) { _vec__rep = l__x._vec__rep; l__x._vec__rep = 0; } \
141   long position(const T& l__a) const;  \
142};  \
143 \
144void swap(vec_T& l__x, vec_T& l__y);  \
145void append(vec_T& l__v, const T& l__a); \
146void append(vec_T& l__v, const vec_T& l__w); \
147
148
149
150#define NTL_eq_vector_decl(T,vec_T)  \
151long operator==(const vec_T& l__a, const vec_T& l__b);  \
152long operator!=(const vec_T& l__a, const vec_T& l__b);
153
154
155#define NTL_vector_impl(T,vec_T) NTL_vector_default(T) NTL_vector_impl_plain(T,vec_T) 
156
157#define NTL_vector_impl_plain(T,vec_T)  \
158 \
159void vec_T::SetLength(long l__n)   \
160{   \
161   long l__m;  \
162  \
163   if (l__n < 0) {  \
164      NTL_NNS Error("negative length in vector::SetLength");  \
165   }  \
166   if (l__n >= long((1L << (NTL_BITS_PER_LONG-4))/sizeof(T)))  \
167      NTL_NNS Error("excessive length in vector::SetLength"); \
168      \
169   if (_vec__rep && NTL_VEC_HEAD(_vec__rep)->fixed) {\
170      if (NTL_VEC_HEAD(_vec__rep)->length == l__n) \
171         return; \
172      else \
173         NTL_NNS Error("SetLength: can't change this vector's length"); \
174   }  \
175   if (l__n == 0) {  \
176      if (_vec__rep) NTL_VEC_HEAD(_vec__rep)->length = 0;  \
177      return;  \
178   }  \
179  \
180   if (!_vec__rep) {  \
181      l__m = ((l__n+NTL_VectorMinAlloc-1)/NTL_VectorMinAlloc) * NTL_VectorMinAlloc; \
182      if (l__m >= long((1L << (NTL_BITS_PER_LONG-4))/sizeof(T)))  \
183         NTL_NNS Error("excessive length in vector::SetLength"); \
184      char *l__p = (char *) NTL_SNS malloc(sizeof(_ntl_AlignedVectorHeader)+sizeof(T)*l__m); \
185      if (!l__p) {  \
186         NTL_NNS Error("out of memory in vector::SetLength()");  \
187      }  \
188      _vec__rep = (T *) (l__p + sizeof(_ntl_AlignedVectorHeader)); \
189  \
190      BlockConstruct(_vec__rep, l__n); \
191  \
192      NTL_VEC_HEAD(_vec__rep)->length = l__n;  \
193      NTL_VEC_HEAD(_vec__rep)->init = l__n;  \
194      NTL_VEC_HEAD(_vec__rep)->alloc = l__m;  \
195      NTL_VEC_HEAD(_vec__rep)->fixed = 0;  \
196   }  \
197   else if (l__n <= NTL_VEC_HEAD(_vec__rep)->init) {  \
198      NTL_VEC_HEAD(_vec__rep)->length = l__n;  \
199   }  \
200   else  {  \
201      if (l__n > NTL_VEC_HEAD(_vec__rep)->alloc) {  \
202         l__m = NTL_NNS max(l__n, long(NTL_VectorExpansionRatio*NTL_VEC_HEAD(_vec__rep)->alloc));  \
203         l__m = ((l__m+NTL_VectorMinAlloc-1)/NTL_VectorMinAlloc) * NTL_VectorMinAlloc; \
204         if (l__m >= long((1L << (NTL_BITS_PER_LONG-4))/sizeof(T)))  \
205            NTL_NNS Error("excessive length in vector::SetLength"); \
206         char *l__p = ((char *) _vec__rep) - sizeof(_ntl_AlignedVectorHeader); \
207         l__p = (char *) NTL_SNS realloc(l__p, sizeof(_ntl_AlignedVectorHeader)+sizeof(T)*l__m); \
208         if (!l__p) {  \
209            NTL_NNS Error("out of memory in vector::SetLength()");  \
210         }  \
211         _vec__rep = (T *) (l__p + sizeof(_ntl_AlignedVectorHeader)); \
212         NTL_VEC_HEAD(_vec__rep)->alloc = l__m;  \
213      }  \
214      BlockConstruct(_vec__rep + NTL_VEC_HEAD(_vec__rep)->init, l__n - NTL_VEC_HEAD(_vec__rep)->init); \
215      NTL_VEC_HEAD(_vec__rep)->length = l__n;  \
216      NTL_VEC_HEAD(_vec__rep)->init = l__n;  \
217   }  \
218}  \
219 \
220 \
221void vec_T::SetMaxLength(long l__n) \
222{ \
223   long l__OldLength = length(); \
224   SetLength(l__n); \
225   SetLength(l__OldLength); \
226} \
227 \
228void vec_T::FixLength(long l__n) \
229{ \
230   if (_vec__rep) NTL_NNS Error("FixLength: can't fix this vector"); \
231   if (l__n < 0) NTL_NNS Error("FixLength: negative length"); \
232   if (l__n > 0) \
233      SetLength(l__n); \
234   else { \
235      char *l__p = (char *) NTL_SNS malloc(sizeof(_ntl_AlignedVectorHeader)); \
236      if (!l__p) {  \
237         NTL_NNS Error("out of memory in vector::FixLength()");  \
238      }  \
239      _vec__rep = (T *) (l__p + sizeof(_ntl_AlignedVectorHeader)); \
240  \
241      NTL_VEC_HEAD(_vec__rep)->length = 0;  \
242      NTL_VEC_HEAD(_vec__rep)->init = 0;  \
243      NTL_VEC_HEAD(_vec__rep)->alloc = 0;  \
244   } \
245   NTL_VEC_HEAD(_vec__rep)->fixed = 1; \
246} \
247  \
248vec_T& vec_T::operator=(const vec_T& l__a)  \
249{  \
250   long l__i, l__n;  \
251   T *l__p;  \
252   const T *l__ap;  \
253  \
254   l__n = l__a.length();  \
255   SetLength(l__n);  \
256   l__ap = l__a.elts();  \
257   l__p = elts();  \
258  \
259   for (l__i = 0; l__i < l__n; l__i++)  \
260      l__p[l__i] = l__ap[l__i];  \
261   return *this;  \
262}  \
263       \
264  \
265vec_T::~vec_T()  \
266{  \
267   if (!_vec__rep) return;  \
268   BlockDestroy(_vec__rep, NTL_VEC_HEAD(_vec__rep)->init); \
269   NTL_SNS free(((char *) _vec__rep) - sizeof(_ntl_AlignedVectorHeader));  \
270}  \
271   \
272void vec_T::kill()  \
273{  \
274   if (!_vec__rep) return;  \
275   if (NTL_VEC_HEAD(_vec__rep)->fixed) NTL_NNS Error("can't kill this vector"); \
276   BlockDestroy(_vec__rep, NTL_VEC_HEAD(_vec__rep)->init); \
277   NTL_SNS free(((char *) _vec__rep) - sizeof(_ntl_AlignedVectorHeader));  \
278   _vec__rep = 0; \
279}  \
280  \
281void vec_T::RangeError(long l__i) const  \
282{  \
283   NTL_SNS Error( "index out of range in vector: ");  \
284   abort();  \
285}  \
286  \
287long vec_T::position(const T& l__a) const  \
288{  \
289   if (!_vec__rep) return -1;  \
290   long l__num_alloc = NTL_VEC_HEAD(_vec__rep)->alloc;  \
291   long l__num_init = NTL_VEC_HEAD(_vec__rep)->init;  \
292   if (&l__a < _vec__rep || &l__a >= _vec__rep + l__num_alloc) return -1;  \
293   long l__res = (&l__a) - _vec__rep;  \
294   \
295   /* the next test ensures that we conform to the C/C++ standard,  \
296      which only guarantees that relational operators are meaningful when  \
297      pointers point to objects in the same array...I don't know  \
298      if it ever *really* makes a diiference...  */  \
299   \
300   if (l__res < 0 || l__res >= l__num_alloc ||   \
301       _vec__rep + l__res != &l__a) return -1;  \
302   \
303   if (l__res >= l__num_init)  \
304       NTL_NNS Error("position: reference to uninitialized object"); \
305   return l__res;  \
306}  \
307 \
308void swap(vec_T& l__x, vec_T& l__y)  \
309{  \
310   T* l__t;  \
311   long l__xf = l__x.fixed();  \
312   long l__yf = l__y.fixed();  \
313   if (l__xf != l__yf ||   \
314       (l__xf && NTL_VEC_HEAD(l__x._vec__rep)->length != NTL_VEC_HEAD(l__y._vec__rep)->length))  \
315      NTL_NNS Error("swap: can't swap these vectors");  \
316   l__t = l__x._vec__rep;  \
317   l__x._vec__rep = l__y._vec__rep;  \
318   l__y._vec__rep = l__t;  \
319} \
320 \
321void append(vec_T& l__v, const T& l__a)  \
322{  \
323   long l__l = l__v.length(); \
324   long l__pos = l__v.position(l__a);  \
325   l__v.SetLength(l__l+1);  \
326   if (l__pos != -1)  \
327      l__v[l__l] = l__v.RawGet(l__pos);  \
328   else  \
329      l__v[l__l] = l__a;  \
330}  \
331  \
332void append(vec_T& l__v, const vec_T& l__w)  \
333{  \
334   long l__l = l__v.length();  \
335   long l__m = l__w.length();  \
336   long l__i;  \
337   l__v.SetLength(l__l+l__m);  \
338   for (l__i = 0; l__i < l__m; l__i++)  \
339      l__v[l__l+l__i] = l__w[l__i];  \
340}
341
342
343
344
345#define NTL_eq_vector_impl(T,vec_T) \
346long operator==(const vec_T& l__a, const vec_T& l__b) \
347{  \
348   long l__n = l__a.length();  \
349   if (l__b.length() != l__n) return 0;  \
350   const T* l__ap = l__a.elts(); \
351   const T* l__bp = l__b.elts(); \
352   long l__i;  \
353   for (l__i = 0; l__i < l__n; l__i++) if (l__ap[l__i] != l__bp[l__i]) return 0;  \
354   return 1;  \
355} \
356long operator!=(const vec_T& l__a, const vec_T& l__b) \
357{  return !(l__a == l__b); }
358
359   
360
361
362#endif
363
Note: See TracBrowser for help on using the repository browser.