00001 00039 #ifndef ARRAY_H 00040 #define ARRAY_H 00041 00042 #include <itpp/itconfig.h> 00043 #include <itpp/base/itassert.h> 00044 #include <itpp/base/factory.h> 00045 #include <itpp/base/copy_vector.h> 00046 00047 00048 namespace itpp { 00049 00050 // Forward declarations 00051 template<class T> class Array; 00052 template<class T> const Array<T> concat(const Array<T> &a, const T e); 00053 template<class T> const Array<T> concat(const T e, const Array<T> &a); 00054 template<class T> const Array<T> concat(const Array<T> &a1, const Array<T> &a2); 00055 template<class T> const Array<T> concat(const Array<T> &a1, const Array<T> &a2, const Array<T> &a3); 00056 00096 template<class T> 00097 class Array { 00098 public: 00100 explicit Array(const Factory &f = DEFAULT_FACTORY); 00102 Array(const int n, const Factory &f = DEFAULT_FACTORY); 00104 Array(const Array<T> &a); 00106 Array(const Array<T> &a, const Factory &f); 00107 00109 virtual ~Array(); 00110 00112 T &operator()(const int i) { 00113 it_assert0(i>=0&&i<ndata,"Array::operator()"); return data[i]; } 00115 const T &operator()(const int i) const { 00116 it_assert0(i>=0&&i<ndata,"Array::operator()"); return data[i]; } 00118 const Array<T> operator()(const int i1, const int i2) const; 00120 const Array<T> operator()(const Array<int> &indices) const; 00121 00123 Array<T>& operator=(const T &e); 00125 Array<T>& operator=(const Array<T> &a); 00126 00128 friend const Array<T> concat <>(const Array<T> &a1, const T e); 00130 friend const Array<T> concat <>(const T e, const Array<T> &a); 00132 friend const Array<T> concat <>(const Array<T> &a1,const Array<T> &a2); 00134 friend const Array<T> concat <>(const Array<T> &a1, const Array<T> &a2, const Array<T> &a3); 00135 00137 int size() const { return ndata; } 00139 int length() const { return ndata; } 00141 void set_size(const int n, const bool copy=false); 00143 void set_length(const int n, const bool copy=false) { set_size(n, copy); } 00144 00146 T shift_right(const T e); 00148 const Array<T> shift_right(const Array<T> &a); 00150 T shift_left(const T e); 00152 const Array<T> shift_left(const Array<T> &a); 00154 void swap(const int i, const int j); 00155 00157 void set_subarray(int i1, int i2, const Array<T> &a); 00159 void set_subarray(int i1, int i2, const T t); 00160 00161 protected: 00163 bool in_range(const int i) { return ((i<ndata) && (i>=0)); } 00165 int ndata; 00167 T *data; 00169 const Factory &factory; 00170 00171 private: 00172 void alloc(int n); 00173 void free(); 00174 }; 00175 00176 // --------------------------- Implementation starts here ---------------------------------- 00177 00178 template<class T> 00179 Array<T>::Array(const Factory &f) : factory(f) 00180 { 00181 data=NULL; 00182 ndata=0; 00183 } 00184 00185 template<class T> 00186 Array<T>::Array(const int n, const Factory &f) : factory(f) 00187 { 00188 alloc(n); 00189 } 00190 00191 template<class T> 00192 Array<T>::Array(const Array<T> &a) : factory(a.factory) 00193 { 00194 alloc(a.ndata); 00195 for (int i=0; i<a.ndata; i++) 00196 data[i] = a.data[i]; 00197 } 00198 00199 template<class T> 00200 Array<T>::Array(const Array<T> &a, const Factory &f) : factory(f) 00201 { 00202 alloc(a.ndata); 00203 for (int i=0; i<a.ndata; i++) 00204 data[i] = a.data[i]; 00205 } 00206 00207 template<class T> 00208 Array<T>::~Array() 00209 { 00210 free(); 00211 } 00212 00213 template<class T> 00214 void Array<T>::alloc(const int n) 00215 { 00216 if (n == 0) { 00217 data = NULL; 00218 ndata = 0; 00219 } 00220 else { 00221 create_elements(data, n, factory); 00222 it_assert1(data!=0, "Out of memory in Array::alloc"); 00223 } 00224 ndata = n; 00225 } 00226 00227 template<class T> 00228 void Array<T>::free() 00229 { 00230 delete [] data; 00231 00232 data = 0; 00233 ndata = 0; 00234 } 00235 00236 template<class T> 00237 const Array<T> Array<T>::operator()(const int i1, const int i2) const 00238 { 00239 it_assert0(i1>=0 && i2>=0 && i1<ndata && i2<ndata && i2>=i1, 00240 "Array::operator()(i1,i2)"); 00241 Array<T> s(i2-i1+1); 00242 int i; 00243 00244 for (i=0; i<s.ndata; i++) 00245 s.data[i] = data[i1+i]; 00246 00247 return s; 00248 } 00249 00250 template<class T> 00251 const Array<T> Array<T>::operator()(const Array<int> &indices) const 00252 { 00253 Array<T> a(indices.size()); 00254 00255 for (int i=0; i<a.size(); i++) { 00256 it_assert0(indices(i)>=0&&indices(i)<ndata,"Array::operator()(indicies)"); 00257 a(i) = data[indices(i)]; 00258 } 00259 00260 return a; 00261 } 00262 00263 template<class T> 00264 Array<T>& Array<T>::operator=(const Array<T> &a) 00265 { 00266 if (this != &a) { 00267 set_size(a.ndata); 00268 for (int i=0; i<ndata; i++) 00269 data[i] = a.data[i]; 00270 } 00271 return *this; 00272 } 00273 00274 template<class T> 00275 Array<T>& Array<T>::operator=(const T &e) 00276 { 00277 if (ndata==0) 00278 set_size(1); 00279 00280 for (int i=0; i<ndata; i++) 00281 data[i] = e; 00282 return *this; 00283 } 00284 00285 template<class T> 00286 void Array<T>::set_size(const int sz, const bool copy) 00287 { 00288 int i, min; 00289 T *tmp; 00290 00291 if (ndata == sz) 00292 return; 00293 00294 if (copy) { 00295 tmp = data; 00296 min = ndata < sz ? ndata : sz; 00297 alloc(sz); 00298 for (i=0; i<min; i++) 00299 data[i] = tmp[i]; 00300 delete [] tmp; 00301 } else { 00302 free(); 00303 alloc(sz); 00304 } 00305 ndata = sz; 00306 } 00307 00308 template<class T> 00309 T Array<T>::shift_right(const T x) 00310 { 00311 T ret; 00312 00313 it_assert1(ndata>0, "shift_right"); 00314 ret = data[ndata-1]; 00315 for (int i=ndata-1; i>0; i--) 00316 data[i] = data[i-1]; 00317 data[0] = x; 00318 00319 return ret; 00320 } 00321 00322 00323 template<class T> 00324 const Array<T> Array<T>::shift_right(const Array<T> &a) 00325 { 00326 int i; 00327 Array<T> out(a.ndata); 00328 00329 it_assert1(a.ndata<=ndata, "Shift Array too large"); 00330 for (i=0; i<a.ndata; i++) 00331 out.data[i] = data[ndata-a.ndata+i]; 00332 for (i=ndata-1; i>=a.ndata; i--) 00333 data[i] = data[i-a.ndata]; 00334 for (i=0; i<a.ndata; i++) 00335 data[i] = a.data[i]; 00336 00337 return out; 00338 } 00339 00340 template<class T> 00341 T Array<T>::shift_left(const T x) 00342 { 00343 T temp = data[0]; 00344 00345 for (int i=0; i<ndata-1; i++) 00346 data[i]=data[i+1]; 00347 data[ndata-1] = x; 00348 00349 return temp; 00350 } 00351 00352 template<class T> 00353 const Array<T> Array<T>::shift_left(const Array<T> &a) 00354 { 00355 int i; 00356 Array<T> out(a.ndata); 00357 00358 it_assert1(a.ndata<=ndata, "Shift Array too large"); 00359 for (i=0; i<a.ndata; i++) 00360 out.data[i] = data[i]; 00361 for (i=0; i<ndata-a.ndata; i++) { 00362 // out.data[i] = data[i]; removed. Is not necessary 00363 data[i] = data[i+a.ndata]; 00364 } 00365 for (i=ndata-a.ndata; i<ndata; i++) 00366 data[i] = a.data[i-ndata+a.ndata]; 00367 00368 return out; 00369 } 00370 00371 template<class T> 00372 void Array<T>::swap(const int i, const int j) 00373 { 00374 it_assert1(in_range(i) && in_range(j) , "Shift Array too large"); 00375 00376 T temp = data[i]; 00377 data[i] = data[j]; 00378 data[j] = temp; 00379 } 00380 00381 template<class T> 00382 void Array<T>::set_subarray(int i1, int i2, const Array<T> &a) 00383 { 00384 if (i1 == -1) i1 = ndata-1; 00385 if (i2 == -1) i2 = ndata-1; 00386 00387 it_assert1(in_range(i1) && in_range(i2), "Array<T>::set_subarray(): indicies out of range"); 00388 it_assert1(i2>=i1, "Array<T>::set_subarray(): i2 >= i1 necessary"); 00389 it_assert1(i2-i1+1 == a.ndata, "Array<T>::set_subarray(): wrong sizes"); 00390 00391 copy_vector(a.ndata, a.data, data+i1); 00392 } 00393 00394 template<class T> 00395 void Array<T>::set_subarray(int i1, int i2, const T t) 00396 { 00397 if (i1 == -1) i1 = ndata-1; 00398 if (i2 == -1) i2 = ndata-1; 00399 00400 it_assert1(in_range(i1) && in_range(i2), "Array<T>::set_subarray(): indicies out of range"); 00401 it_assert1(i2>=i1, "Array<T>::set_subarray(): i2 >= i1 necessary"); 00402 00403 for (int i=i1;i<=i2;i++) 00404 data[i] = t; 00405 } 00406 00407 template<class T> 00408 const Array<T> concat(const Array<T> &a, const T e) 00409 { 00410 Array<T> temp(a.size()+1); 00411 00412 for (int i=0; i<a.size(); i++) 00413 temp(i) = a(i); 00414 temp(a.size()) = e; 00415 00416 return temp; 00417 } 00418 00419 template<class T> 00420 const Array<T> concat(const T e, const Array<T> &a) 00421 { 00422 Array<T> temp(a.size()+1); 00423 00424 temp(0) = e; 00425 00426 for (int i=0; i<a.size(); i++) 00427 temp(i+1) = a(i); 00428 00429 return temp; 00430 } 00431 00432 template<class T> 00433 const Array<T> concat(const Array<T> &a1, const Array<T> &a2) 00434 { 00435 int i; 00436 Array<T> temp(a1.size()+a2.size()); 00437 00438 for (i=0;i<a1.size();i++) { 00439 temp(i) = a1(i); 00440 } 00441 for (i=0;i<a2.size();i++) { 00442 temp(a1.size()+i) = a2(i); 00443 } 00444 return temp; 00445 } 00446 00447 template<class T> 00448 const Array<T> concat(const Array<T> &a1, const Array<T> &a2, const Array<T> &a3) 00449 { 00450 // There should be some error control? 00451 int i; 00452 Array<T> temp(a1.size()+a2.size()+a3.size()); 00453 00454 for (i=0;i<a1.size();i++) { 00455 temp(i) = a1(i); 00456 } 00457 for (i=0;i<a2.size();i++) { 00458 temp(a1.size()+i) = a2(i); 00459 } 00460 for (i=0;i<a3.size();i++) { 00461 temp(a1.size()+a2.size()+i) = a3(i); 00462 } 00463 return temp; 00464 } 00465 00470 template<class T> 00471 std::ostream &operator<<(std::ostream &os, const Array<T> &a) 00472 { 00473 os << "{"; 00474 for (int i=0; i<a.size()-1; i++) 00475 os << a(i) << " "; 00476 if (a.size() > 0) 00477 os << a(a.size()-1); 00478 os << "}"; 00479 00480 return os; 00481 } 00482 00487 template<class T> 00488 std::istream &operator>>(std::istream &is, Array<T> &a) 00489 { 00490 int nrof_elements = 0; 00491 char c; 00492 is >> c; 00493 if (c == '{') { 00494 is >> c; 00495 while (c != '}') { 00496 if (is.eof()) { 00497 is.setstate(std::ios_base::failbit); 00498 break; 00499 } 00500 if (c != ',') { // Discard comma signs between elements 00501 is.putback(c); 00502 } 00503 if (++nrof_elements > a.size()) { 00504 a.set_size(nrof_elements, true); // Too slow? 00505 } 00506 is >> a(nrof_elements-1); 00507 is >> c; 00508 } 00509 if (a.size() > nrof_elements) { 00510 a.set_size(nrof_elements, true); 00511 } 00512 } else { 00513 is.setstate(std::ios_base::failbit); 00514 } 00515 00516 return is; 00517 } 00518 00523 template<class T> 00524 void set_array(Array<T> &a, const char *values) 00525 { 00526 std::istringstream buffer(values); 00527 buffer >> a; 00528 } 00529 00534 template<class T> 00535 void set_array(Array<T> &a, const std::string &str) 00536 { 00537 set_array(a, str.c_str()); 00538 } 00539 00540 } // namespace itpp 00541 00542 #endif // #ifndef ARRAY_H
Generated on Wed Apr 18 11:45:32 2007 for IT++ by Doxygen 1.5.2