[f2d6445] | 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 | |
---|