source: git/ntl/include/NTL/vector.h @ 92c0ac

spielwiese
Last change on this file since 92c0ac was 92c0ac, checked in by Hans Schönemann <hannes@…>, 21 years ago
NTL-5.2 git-svn-id: file:///usr/local/Singular/svn/trunk@6320 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 12.0 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
151#define NTL_io_vector_decl(T,vec_T)  \
152NTL_SNS istream& operator>>(NTL_SNS istream&, vec_T&);  \
153  \
154NTL_SNS ostream& operator<<(NTL_SNS ostream&, const vec_T&);  \
155
156
157#define NTL_eq_vector_decl(T,vec_T)  \
158long operator==(const vec_T& l__a, const vec_T& l__b);  \
159long operator!=(const vec_T& l__a, const vec_T& l__b);
160
161
162#define NTL_vector_impl(T,vec_T) NTL_vector_default(T) NTL_vector_impl_plain(T,vec_T) 
163
164#define NTL_vector_impl_plain(T,vec_T)  \
165 \
166void vec_T::SetLength(long l__n)   \
167{   \
168   long l__m;  \
169  \
170   if (l__n < 0) {  \
171      NTL_NNS Error("negative length in vector::SetLength");  \
172   }  \
173   if (l__n >= long((1L << (NTL_BITS_PER_LONG-4))/sizeof(T)))  \
174      NTL_NNS Error("excessive length in vector::SetLength"); \
175      \
176   if (_vec__rep && NTL_VEC_HEAD(_vec__rep)->fixed) {\
177      if (NTL_VEC_HEAD(_vec__rep)->length == l__n) \
178         return; \
179      else \
180         NTL_NNS Error("SetLength: can't change this vector's length"); \
181   }  \
182   if (l__n == 0) {  \
183      if (_vec__rep) NTL_VEC_HEAD(_vec__rep)->length = 0;  \
184      return;  \
185   }  \
186  \
187   if (!_vec__rep) {  \
188      l__m = ((l__n+NTL_VectorMinAlloc-1)/NTL_VectorMinAlloc) * NTL_VectorMinAlloc; \
189      if (l__m >= long((1L << (NTL_BITS_PER_LONG-4))/sizeof(T)))  \
190         NTL_NNS Error("excessive length in vector::SetLength"); \
191      char *l__p = (char *) NTL_SNS malloc(sizeof(_ntl_AlignedVectorHeader)+sizeof(T)*l__m); \
192      if (!l__p) {  \
193         NTL_NNS Error("out of memory in vector::SetLength()");  \
194      }  \
195      _vec__rep = (T *) (l__p + sizeof(_ntl_AlignedVectorHeader)); \
196  \
197      BlockConstruct(_vec__rep, l__n); \
198  \
199      NTL_VEC_HEAD(_vec__rep)->length = l__n;  \
200      NTL_VEC_HEAD(_vec__rep)->init = l__n;  \
201      NTL_VEC_HEAD(_vec__rep)->alloc = l__m;  \
202      NTL_VEC_HEAD(_vec__rep)->fixed = 0;  \
203   }  \
204   else if (l__n <= NTL_VEC_HEAD(_vec__rep)->init) {  \
205      NTL_VEC_HEAD(_vec__rep)->length = l__n;  \
206   }  \
207   else  {  \
208      if (l__n > NTL_VEC_HEAD(_vec__rep)->alloc) {  \
209         l__m = NTL_NNS max(l__n, long(NTL_VectorExpansionRatio*NTL_VEC_HEAD(_vec__rep)->alloc));  \
210         l__m = ((l__m+NTL_VectorMinAlloc-1)/NTL_VectorMinAlloc) * NTL_VectorMinAlloc; \
211         if (l__m >= long((1L << (NTL_BITS_PER_LONG-4))/sizeof(T)))  \
212            NTL_NNS Error("excessive length in vector::SetLength"); \
213         char *l__p = ((char *) _vec__rep) - sizeof(_ntl_AlignedVectorHeader); \
214         l__p = (char *) NTL_SNS realloc(l__p, sizeof(_ntl_AlignedVectorHeader)+sizeof(T)*l__m); \
215         if (!l__p) {  \
216            NTL_NNS Error("out of memory in vector::SetLength()");  \
217         }  \
218         _vec__rep = (T *) (l__p + sizeof(_ntl_AlignedVectorHeader)); \
219         NTL_VEC_HEAD(_vec__rep)->alloc = l__m;  \
220      }  \
221      BlockConstruct(_vec__rep + NTL_VEC_HEAD(_vec__rep)->init, l__n - NTL_VEC_HEAD(_vec__rep)->init); \
222      NTL_VEC_HEAD(_vec__rep)->length = l__n;  \
223      NTL_VEC_HEAD(_vec__rep)->init = l__n;  \
224   }  \
225}  \
226 \
227 \
228void vec_T::SetMaxLength(long l__n) \
229{ \
230   long l__OldLength = length(); \
231   SetLength(l__n); \
232   SetLength(l__OldLength); \
233} \
234 \
235void vec_T::FixLength(long l__n) \
236{ \
237   if (_vec__rep) NTL_NNS Error("FixLength: can't fix this vector"); \
238   if (l__n < 0) NTL_NNS Error("FixLength: negative length"); \
239   if (l__n > 0) \
240      SetLength(l__n); \
241   else { \
242      char *l__p = (char *) NTL_SNS malloc(sizeof(_ntl_AlignedVectorHeader)); \
243      if (!l__p) {  \
244         NTL_NNS Error("out of memory in vector::FixLength()");  \
245      }  \
246      _vec__rep = (T *) (l__p + sizeof(_ntl_AlignedVectorHeader)); \
247  \
248      NTL_VEC_HEAD(_vec__rep)->length = 0;  \
249      NTL_VEC_HEAD(_vec__rep)->init = 0;  \
250      NTL_VEC_HEAD(_vec__rep)->alloc = 0;  \
251   } \
252   NTL_VEC_HEAD(_vec__rep)->fixed = 1; \
253} \
254  \
255vec_T& vec_T::operator=(const vec_T& l__a)  \
256{  \
257   long l__i, l__n;  \
258   T *l__p;  \
259   const T *l__ap;  \
260  \
261   l__n = l__a.length();  \
262   SetLength(l__n);  \
263   l__ap = l__a.elts();  \
264   l__p = elts();  \
265  \
266   for (l__i = 0; l__i < l__n; l__i++)  \
267      l__p[l__i] = l__ap[l__i];  \
268   return *this;  \
269}  \
270       \
271  \
272vec_T::~vec_T()  \
273{  \
274   if (!_vec__rep) return;  \
275   BlockDestroy(_vec__rep, NTL_VEC_HEAD(_vec__rep)->init); \
276   NTL_SNS free(((char *) _vec__rep) - sizeof(_ntl_AlignedVectorHeader));  \
277}  \
278   \
279void vec_T::kill()  \
280{  \
281   if (!_vec__rep) return;  \
282   if (NTL_VEC_HEAD(_vec__rep)->fixed) NTL_NNS Error("can't kill this vector"); \
283   BlockDestroy(_vec__rep, NTL_VEC_HEAD(_vec__rep)->init); \
284   NTL_SNS free(((char *) _vec__rep) - sizeof(_ntl_AlignedVectorHeader));  \
285   _vec__rep = 0; \
286}  \
287  \
288void vec_T::RangeError(long l__i) const  \
289{  \
290   NTL_SNS cerr << "index out of range in vector: ";  \
291   NTL_SNS cerr << l__i;  \
292   if (!_vec__rep)  \
293      NTL_SNS cerr << "(0)\n";  \
294   else  \
295      NTL_SNS cerr << "(" << NTL_VEC_HEAD(_vec__rep)->length << ")\n";  \
296   abort();  \
297}  \
298  \
299long vec_T::position(const T& l__a) const  \
300{  \
301   if (!_vec__rep) return -1;  \
302   long l__num_alloc = NTL_VEC_HEAD(_vec__rep)->alloc;  \
303   long l__num_init = NTL_VEC_HEAD(_vec__rep)->init;  \
304   if (&l__a < _vec__rep || &l__a >= _vec__rep + l__num_alloc) return -1;  \
305   long l__res = (&l__a) - _vec__rep;  \
306   \
307   /* the next test ensures that we conform to the C/C++ standard,  \
308      which only guarantees that relational operators are meaningful when  \
309      pointers point to objects in the same array...I don't know  \
310      if it ever *really* makes a diiference...  */  \
311   \
312   if (l__res < 0 || l__res >= l__num_alloc ||   \
313       _vec__rep + l__res != &l__a) return -1;  \
314   \
315   if (l__res >= l__num_init)  \
316       NTL_NNS Error("position: reference to uninitialized object"); \
317   return l__res;  \
318}  \
319 \
320void swap(vec_T& l__x, vec_T& l__y)  \
321{  \
322   T* l__t;  \
323   long l__xf = l__x.fixed();  \
324   long l__yf = l__y.fixed();  \
325   if (l__xf != l__yf ||   \
326       (l__xf && NTL_VEC_HEAD(l__x._vec__rep)->length != NTL_VEC_HEAD(l__y._vec__rep)->length))  \
327      NTL_NNS Error("swap: can't swap these vectors");  \
328   l__t = l__x._vec__rep;  \
329   l__x._vec__rep = l__y._vec__rep;  \
330   l__y._vec__rep = l__t;  \
331} \
332 \
333void append(vec_T& l__v, const T& l__a)  \
334{  \
335   long l__l = l__v.length(); \
336   long l__pos = l__v.position(l__a);  \
337   l__v.SetLength(l__l+1);  \
338   if (l__pos != -1)  \
339      l__v[l__l] = l__v.RawGet(l__pos);  \
340   else  \
341      l__v[l__l] = l__a;  \
342}  \
343  \
344void append(vec_T& l__v, const vec_T& l__w)  \
345{  \
346   long l__l = l__v.length();  \
347   long l__m = l__w.length();  \
348   long l__i;  \
349   l__v.SetLength(l__l+l__m);  \
350   for (l__i = 0; l__i < l__m; l__i++)  \
351      l__v[l__l+l__i] = l__w[l__i];  \
352}
353
354
355
356
357
358#define NTL_io_vector_impl(T,vec_T)  \
359NTL_SNS istream & operator>>(NTL_SNS istream& l__s, vec_T& l__a)   \
360{   \
361   vec_T l__ibuf;  \
362   long l__c;   \
363   long l__n;   \
364   if (!l__s) NTL_NNS Error("bad vector input"); \
365   \
366   l__c = l__s.peek();  \
367   while (l__c == ' ' || l__c == '\n' || l__c == '\t') {  \
368      l__s.get();  \
369      l__c = l__s.peek();  \
370   }  \
371   if (l__c != '[') {  \
372      NTL_NNS Error("bad vector input");  \
373   }  \
374   \
375   l__n = 0;   \
376   l__ibuf.SetLength(0);  \
377      \
378   l__s.get();  \
379   l__c = l__s.peek();  \
380   while (l__c == ' ' || l__c == '\n' || l__c == '\t') {  \
381      l__s.get();  \
382      l__c = l__s.peek();  \
383   }  \
384   while (l__c != ']' && l__c != EOF) {   \
385      if (l__n % NTL_VectorInputBlock == 0) l__ibuf.SetMaxLength(l__n + NTL_VectorInputBlock); \
386      l__n++;   \
387      l__ibuf.SetLength(l__n);   \
388      if (!(l__s >> l__ibuf[l__n-1])) NTL_NNS Error("bad vector input");   \
389      l__c = l__s.peek();  \
390      while (l__c == ' ' || l__c == '\n' || l__c == '\t') {  \
391         l__s.get();  \
392         l__c = l__s.peek();  \
393      }  \
394   }   \
395   if (l__c == EOF) NTL_NNS Error("bad vector input");  \
396   l__s.get(); \
397   \
398   l__a = l__ibuf; \
399   return l__s;   \
400}    \
401   \
402   \
403NTL_SNS ostream& operator<<(NTL_SNS ostream& l__s, const vec_T& l__a)   \
404{   \
405   long l__i, l__n;   \
406  \
407   l__n = l__a.length();  \
408   \
409   l__s << '[';   \
410   \
411   for (l__i = 0; l__i < l__n; l__i++) {   \
412      l__s << l__a[l__i];   \
413      if (l__i < l__n-1) l__s << " ";   \
414   }   \
415   \
416   l__s << ']';   \
417      \
418   return l__s;   \
419}   \
420
421#define NTL_eq_vector_impl(T,vec_T) \
422long operator==(const vec_T& l__a, const vec_T& l__b) \
423{  \
424   long l__n = l__a.length();  \
425   if (l__b.length() != l__n) return 0;  \
426   const T* l__ap = l__a.elts(); \
427   const T* l__bp = l__b.elts(); \
428   long l__i;  \
429   for (l__i = 0; l__i < l__n; l__i++) if (l__ap[l__i] != l__bp[l__i]) return 0;  \
430   return 1;  \
431} \
432long operator!=(const vec_T& l__a, const vec_T& l__b) \
433{  return !(l__a == l__b); }
434
435   
436
437
438#endif
439
Note: See TracBrowser for help on using the repository browser.