1 | /* |
---|
2 | * |
---|
3 | * Template Numerical Toolkit (TNT) |
---|
4 | * |
---|
5 | * Mathematical and Computational Sciences Division |
---|
6 | * National Institute of Technology, |
---|
7 | * Gaithersburg, MD USA |
---|
8 | * |
---|
9 | * |
---|
10 | * This software was developed at the National Institute of Standards and |
---|
11 | * Technology (NIST) by employees of the Federal Government in the course |
---|
12 | * of their official duties. Pursuant to title 17 Section 105 of the |
---|
13 | * United States Code, this software is not subject to copyright protection |
---|
14 | * and is in the public domain. NIST assumes no responsibility whatsoever for |
---|
15 | * its use by other parties, and makes no guarantees, expressed or implied, |
---|
16 | * about its quality, reliability, or any other characteristic. |
---|
17 | * |
---|
18 | */ |
---|
19 | |
---|
20 | |
---|
21 | |
---|
22 | #ifndef TNT_I_REFVEC_H |
---|
23 | #define TNT_I_REFVEC_H |
---|
24 | |
---|
25 | #include <cstdlib> |
---|
26 | #include <iostream> |
---|
27 | |
---|
28 | #ifdef TNT_BOUNDS_CHECK |
---|
29 | #include <assert.h> |
---|
30 | #endif |
---|
31 | |
---|
32 | #ifndef NULL |
---|
33 | #define NULL 0 |
---|
34 | #endif |
---|
35 | |
---|
36 | namespace TNT |
---|
37 | { |
---|
38 | /* |
---|
39 | Internal representation of ref-counted array. The TNT |
---|
40 | arrays all use this building block. |
---|
41 | |
---|
42 | <p> |
---|
43 | If an array block is created by TNT, then every time |
---|
44 | an assignment is made, the left-hand-side reference |
---|
45 | is decreased by one, and the right-hand-side refernce |
---|
46 | count is increased by one. If the array block was |
---|
47 | external to TNT, the refernce count is a NULL pointer |
---|
48 | regardless of how many references are made, since the |
---|
49 | memory is not freed by TNT. |
---|
50 | |
---|
51 | |
---|
52 | |
---|
53 | */ |
---|
54 | template <class T> |
---|
55 | class i_refvec |
---|
56 | { |
---|
57 | |
---|
58 | |
---|
59 | private: |
---|
60 | T* data_; |
---|
61 | int *ref_count_; |
---|
62 | |
---|
63 | |
---|
64 | public: |
---|
65 | |
---|
66 | i_refvec(); |
---|
67 | explicit i_refvec(int n); |
---|
68 | inline i_refvec(T* data); |
---|
69 | inline i_refvec(const i_refvec &v); |
---|
70 | inline T* begin(); |
---|
71 | inline const T* begin() const; |
---|
72 | inline T& operator[](int i); |
---|
73 | inline const T& operator[](int i) const; |
---|
74 | inline i_refvec<T> & operator=(const i_refvec<T> &V); |
---|
75 | void copy_(T* p, const T* q, const T* e); |
---|
76 | void set_(T* p, const T* b, const T* e); |
---|
77 | inline int ref_count() const; |
---|
78 | inline int is_null() const; |
---|
79 | inline void destroy(); |
---|
80 | ~i_refvec(); |
---|
81 | |
---|
82 | }; |
---|
83 | |
---|
84 | template <class T> |
---|
85 | void i_refvec<T>::copy_(T* p, const T* q, const T* e) |
---|
86 | { |
---|
87 | for (T* t=p; q<e; t++, q++) |
---|
88 | *t= *q; |
---|
89 | } |
---|
90 | |
---|
91 | template <class T> |
---|
92 | i_refvec<T>::i_refvec() : data_(NULL), ref_count_(NULL) {} |
---|
93 | |
---|
94 | /** |
---|
95 | In case n is 0 or negative, it does NOT call new. |
---|
96 | */ |
---|
97 | template <class T> |
---|
98 | i_refvec<T>::i_refvec(int n) : data_(NULL), ref_count_(NULL) |
---|
99 | { |
---|
100 | if (n >= 1) |
---|
101 | { |
---|
102 | #ifdef TNT_DEBUG |
---|
103 | std::cout << "new data storage.\n"; |
---|
104 | #endif |
---|
105 | data_ = new T[n]; |
---|
106 | ref_count_ = new int; |
---|
107 | *ref_count_ = 1; |
---|
108 | } |
---|
109 | } |
---|
110 | |
---|
111 | template <class T> |
---|
112 | inline i_refvec<T>::i_refvec(const i_refvec<T> &V): data_(V.data_), |
---|
113 | ref_count_(V.ref_count_) |
---|
114 | { |
---|
115 | if (V.ref_count_ != NULL) |
---|
116 | (*(V.ref_count_))++; |
---|
117 | } |
---|
118 | |
---|
119 | |
---|
120 | template <class T> |
---|
121 | i_refvec<T>::i_refvec(T* data) : data_(data), ref_count_(NULL) {} |
---|
122 | |
---|
123 | template <class T> |
---|
124 | inline T* i_refvec<T>::begin() |
---|
125 | { |
---|
126 | return data_; |
---|
127 | } |
---|
128 | |
---|
129 | template <class T> |
---|
130 | inline const T& i_refvec<T>::operator[](int i) const |
---|
131 | { |
---|
132 | return data_[i]; |
---|
133 | } |
---|
134 | |
---|
135 | template <class T> |
---|
136 | inline T& i_refvec<T>::operator[](int i) |
---|
137 | { |
---|
138 | return data_[i]; |
---|
139 | } |
---|
140 | |
---|
141 | |
---|
142 | template <class T> |
---|
143 | inline const T* i_refvec<T>::begin() const |
---|
144 | { |
---|
145 | return data_; |
---|
146 | } |
---|
147 | |
---|
148 | |
---|
149 | |
---|
150 | template <class T> |
---|
151 | i_refvec<T> & i_refvec<T>::operator=(const i_refvec<T> &V) |
---|
152 | { |
---|
153 | if (this == &V) |
---|
154 | return *this; |
---|
155 | |
---|
156 | |
---|
157 | if (ref_count_ != NULL) |
---|
158 | { |
---|
159 | (*ref_count_) --; |
---|
160 | if ((*ref_count_) == 0) |
---|
161 | destroy(); |
---|
162 | } |
---|
163 | |
---|
164 | data_ = V.data_; |
---|
165 | ref_count_ = V.ref_count_; |
---|
166 | |
---|
167 | if (V.ref_count_ != NULL) |
---|
168 | (*(V.ref_count_))++; |
---|
169 | |
---|
170 | return *this; |
---|
171 | } |
---|
172 | |
---|
173 | template <class T> |
---|
174 | void i_refvec<T>::destroy() |
---|
175 | { |
---|
176 | if (ref_count_ != NULL) |
---|
177 | { |
---|
178 | #ifdef TNT_DEBUG |
---|
179 | std::cout << "destorying data... \n"; |
---|
180 | #endif |
---|
181 | delete ref_count_; |
---|
182 | |
---|
183 | #ifdef TNT_DEBUG |
---|
184 | std::cout << "deleted ref_count_ ...\n"; |
---|
185 | #endif |
---|
186 | if (data_ != NULL) |
---|
187 | delete []data_; |
---|
188 | #ifdef TNT_DEBUG |
---|
189 | std::cout << "deleted data_[] ...\n"; |
---|
190 | #endif |
---|
191 | data_ = NULL; |
---|
192 | } |
---|
193 | } |
---|
194 | |
---|
195 | /* |
---|
196 | * return 1 is vector is empty, 0 otherwise |
---|
197 | * |
---|
198 | * if is_null() is false and ref_count() is 0, then |
---|
199 | * |
---|
200 | */ |
---|
201 | template<class T> |
---|
202 | int i_refvec<T>::is_null() const |
---|
203 | { |
---|
204 | return (data_ == NULL ? 1 : 0); |
---|
205 | } |
---|
206 | |
---|
207 | /* |
---|
208 | * returns -1 if data is external, |
---|
209 | * returns 0 if a is NULL array, |
---|
210 | * otherwise returns the positive number of vectors sharing |
---|
211 | * this data space. |
---|
212 | */ |
---|
213 | template <class T> |
---|
214 | int i_refvec<T>::ref_count() const |
---|
215 | { |
---|
216 | if (data_ == NULL) |
---|
217 | return 0; |
---|
218 | else |
---|
219 | return (ref_count_ != NULL ? *ref_count_ : -1) ; |
---|
220 | } |
---|
221 | |
---|
222 | template <class T> |
---|
223 | i_refvec<T>::~i_refvec() |
---|
224 | { |
---|
225 | if (ref_count_ != NULL) |
---|
226 | { |
---|
227 | (*ref_count_)--; |
---|
228 | |
---|
229 | if (*ref_count_ == 0) |
---|
230 | destroy(); |
---|
231 | } |
---|
232 | } |
---|
233 | |
---|
234 | |
---|
235 | } /* namespace TNT */ |
---|
236 | |
---|
237 | |
---|
238 | |
---|
239 | |
---|
240 | |
---|
241 | #endif |
---|
242 | /* TNT_I_REFVEC_H */ |
---|
243 | |
---|