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 |
|