00001 00030 #ifndef ARRAY_H 00031 #define ARRAY_H 00032 00033 #include <itpp/base/itassert.h> 00034 #include <itpp/base/math/misc.h> 00035 #include <itpp/base/factory.h> 00036 #include <itpp/base/copy_vector.h> 00037 00038 00039 namespace itpp { 00040 00041 // Forward declarations 00042 template<class T> class Array; 00044 template<class T> const Array<T> concat(const Array<T> &a, const T e); 00046 template<class T> const Array<T> concat(const T e, const Array<T> &a); 00048 template<class T> const Array<T> concat(const Array<T> &a1, 00049 const Array<T> &a2); 00051 template<class T> const Array<T> concat(const Array<T> &a1, 00052 const Array<T> &a2, 00053 const Array<T> &a3); 00054 00103 template<class T> 00104 class Array { 00105 public: 00107 explicit Array(const Factory &f = DEFAULT_FACTORY); 00109 Array(int n, const Factory &f = DEFAULT_FACTORY); 00111 Array(const Array<T> &a, const Factory &f = DEFAULT_FACTORY); 00113 Array(const std::string& values, const Factory &f = DEFAULT_FACTORY); 00115 Array(const char* values, const Factory &f = DEFAULT_FACTORY); 00116 00118 virtual ~Array(); 00119 00121 T &operator()(int i); 00123 const T &operator()(int i) const; 00125 const Array<T> operator()(int i1, int i2) const; 00127 const Array<T> operator()(const Array<int> &indices) const; 00128 00130 Array<T> left(int n) const; 00132 Array<T> right(int n) const; 00134 Array<T> mid(int pos, int n) const; 00135 00137 Array<T>& operator=(const T &e); 00139 Array<T>& operator=(const Array<T> &a); 00141 Array<T>& operator=(const char* values); 00142 00144 friend const Array<T> concat <>(const Array<T> &a1, const T e); 00146 friend const Array<T> concat <>(const T e, const Array<T> &a); 00148 friend const Array<T> concat <>(const Array<T> &a1,const Array<T> &a2); 00150 friend const Array<T> concat <>(const Array<T> &a1, const Array<T> &a2, 00151 const Array<T> &a3); 00152 00154 int size() const { return ndata; } 00156 int length() const { return ndata; } 00158 void set_size(int n, bool copy = false); 00160 void set_length(int n, bool copy = false) { set_size(n, copy); } 00161 00163 T shift_right(const T& e); 00165 const Array<T> shift_right(const Array<T> &a); 00167 T shift_left(const T& e); 00169 const Array<T> shift_left(const Array<T> &a); 00171 void swap(int i, int j); 00172 00174 void set_subarray(int i1, int i2, const Array<T> &a); 00176 void set_subarray(int i1, int i2, const T t); 00177 00178 protected: 00180 void alloc(int n); 00182 void free(); 00184 bool in_range(int i) const { return ((i < ndata) && (i >= 0)); } 00186 int ndata; 00188 T *data; 00190 const Factory &factory; 00191 }; 00192 00193 // -------------------- Implementation starts here -------------------- 00194 00195 template<class T> inline 00196 void Array<T>::alloc(int n) 00197 { 00198 if (n > 0) { 00199 create_elements(data, n, factory); 00200 ndata = n; 00201 } 00202 else { 00203 data = 0; 00204 ndata = 0; 00205 } 00206 } 00207 00208 template<class T> inline 00209 void Array<T>::free() 00210 { 00211 destroy_elements(data, ndata); 00212 ndata = 0; 00213 } 00214 00215 template<class T> inline 00216 Array<T>::Array(const Factory &f) : ndata(0), data(0), factory(f) {} 00217 00218 template<class T> inline 00219 Array<T>::Array(const int n, const Factory &f) : ndata(0), data(0), factory(f) 00220 { 00221 alloc(n); 00222 } 00223 00224 template<class T> inline 00225 Array<T>::Array(const Array<T> &a, const Factory &f) 00226 : ndata(0), data(0), factory(f) 00227 { 00228 alloc(a.ndata); 00229 for (int i = 0; i < a.ndata; i++) 00230 data[i] = a.data[i]; 00231 } 00232 00233 template<class T> inline 00234 Array<T>::Array(const std::string& values, const Factory &f) 00235 : ndata(0), data(0), factory(f) 00236 { 00237 std::istringstream buffer(values); 00238 buffer >> *this; 00239 } 00240 00241 template<class T> inline 00242 Array<T>::Array(const char* values, const Factory &f) 00243 : ndata(0), data(0), factory(f) 00244 { 00245 std::istringstream buffer(values); 00246 buffer >> *this; 00247 } 00248 00249 template<class T> 00250 Array<T>::~Array() 00251 { 00252 free(); 00253 } 00254 00255 template<class T> 00256 void Array<T>::set_size(int size, bool copy) 00257 { 00258 it_assert_debug(size >= 0, "Array::set_size(): New size must not be negative"); 00259 if (ndata == size) 00260 return; 00261 if (copy) { 00262 // create a temporary pointer to the allocated data 00263 T* tmp = data; 00264 // store the current number of elements 00265 int old_ndata = ndata; 00266 // check how many elements we need to copy 00267 int min = (ndata < size) ? ndata : size; 00268 // allocate new memory 00269 alloc(size); 00270 // copy old elements into a new memory region 00271 for (int i = 0; i < min; ++i) { 00272 data[i] = tmp[i]; 00273 } 00274 // initialize the rest of resized array 00275 for (int i = min; i < size; ++i) { 00276 data[i] = T(); 00277 } 00278 // delete old elements 00279 destroy_elements(tmp, old_ndata); 00280 } 00281 else { 00282 free(); 00283 alloc(size); 00284 } 00285 } 00286 00287 00288 template<class T> inline 00289 T& Array<T>::operator()(int i) 00290 { 00291 it_assert_debug(in_range(i), "Array::operator(): Improper index"); 00292 return data[i]; 00293 } 00294 00295 template<class T> inline 00296 const T& Array<T>::operator()(int i) const 00297 { 00298 it_assert_debug(in_range(i), "Array::operator(): Improper index"); 00299 return data[i]; 00300 } 00301 00302 template<class T> inline 00303 const Array<T> Array<T>::operator()(int i1, int i2) const 00304 { 00305 it_assert_debug(in_range(i1) && in_range(i2) && (i2 >= i1), 00306 "Array::operator()(i1, i2): Improper indexes."); 00307 Array<T> s(i2-i1+1); 00308 for (int i = 0; i < s.ndata; i++) 00309 s.data[i] = data[i1+i]; 00310 return s; 00311 } 00312 00313 template<class T> inline 00314 const Array<T> Array<T>::operator()(const Array<int> &indices) const 00315 { 00316 Array<T> a(indices.size()); 00317 for (int i = 0; i < a.size(); i++) { 00318 it_assert_debug(in_range(indices(i)), 00319 "Array::operator()(indices): Improper indices."); 00320 a(i) = data[indices(i)]; 00321 } 00322 return a; 00323 } 00324 00325 template<class T> inline 00326 Array<T>& Array<T>::operator=(const Array<T> &a) 00327 { 00328 if (this != &a) { 00329 set_size(a.ndata); 00330 for (int i=0; i<ndata; i++) 00331 data[i] = a.data[i]; 00332 } 00333 return *this; 00334 } 00335 00336 template<class T> inline 00337 Array<T>& Array<T>::operator=(const T &e) 00338 { 00339 if (ndata == 0) 00340 set_size(1); 00341 for (int i = 0; i < ndata; i++) 00342 data[i] = e; 00343 return *this; 00344 } 00345 00346 template<class T> 00347 Array<T>& Array<T>::operator=(const char* values) 00348 { 00349 std::istringstream buffer(values); 00350 buffer >> *this; 00351 return *this; 00352 } 00353 00354 00355 template<class T> 00356 Array<T> Array<T>::left(int n) const 00357 { 00358 it_assert_debug(in_range(n), "Array::left(): Index out of range"); 00359 Array<T> tmp(n); 00360 for (int i = 0; i < n; ++i) 00361 tmp.data[i] = data[i]; 00362 return tmp; 00363 } 00364 00365 template<class T> 00366 Array<T> Array<T>::right(int n) const 00367 { 00368 it_assert_debug(in_range(n), "Array::right(): Index out of range"); 00369 Array<T> tmp(n); 00370 for (int i = 0; i < n; ++i) 00371 tmp.data[i] = data[ndata-n+i]; 00372 return tmp; 00373 } 00374 00375 template<class T> 00376 Array<T> Array<T>::mid(int pos, int n) const 00377 { 00378 it_assert_debug((pos >= 0) && (n > 0) && (pos + n <= ndata), "Array::mid(): Indexing out of range"); 00379 Array<T> tmp(n); 00380 for (int i = 0; i < n; ++i) 00381 tmp.data[i] = data[pos+i]; 00382 return tmp; 00383 } 00384 00385 00386 template<class T> 00387 T Array<T>::shift_right(const T& x) 00388 { 00389 it_assert_debug(ndata > 0, "Array::shift_right(x): Array empty!"); 00390 T ret; 00391 00392 ret = data[ndata-1]; 00393 for (int i = ndata-1; i > 0; i--) 00394 data[i] = data[i-1]; 00395 data[0] = x; 00396 00397 return ret; 00398 } 00399 00400 00401 template<class T> 00402 const Array<T> Array<T>::shift_right(const Array<T> &a) 00403 { 00404 it_assert_debug(a.ndata <= ndata, "Array::shift_right(): Shift Array too large"); 00405 Array<T> out(a.ndata); 00406 00407 for (int i = 0; i < a.ndata; i++) 00408 out.data[i] = data[ndata-a.ndata+i]; 00409 for (int i = ndata-1; i >= a.ndata; i--) 00410 data[i] = data[i-a.ndata]; 00411 for (int i = 0; i < a.ndata; i++) 00412 data[i] = a.data[i]; 00413 00414 return out; 00415 } 00416 00417 template<class T> 00418 T Array<T>::shift_left(const T& x) 00419 { 00420 T temp = data[0]; 00421 00422 for (int i = 0; i < ndata-1; i++) 00423 data[i] = data[i+1]; 00424 data[ndata-1] = x; 00425 00426 return temp; 00427 } 00428 00429 template<class T> 00430 const Array<T> Array<T>::shift_left(const Array<T> &a) 00431 { 00432 it_assert_debug(a.ndata <= ndata, "Array::shift_left(): Shift Array too large"); 00433 Array<T> out(a.ndata); 00434 00435 for (int i = 0; i < a.ndata; i++) 00436 out.data[i] = data[i]; 00437 for (int i = 0; i < ndata-a.ndata; i++) 00438 data[i] = data[i+a.ndata]; 00439 for (int i = ndata-a.ndata; i < ndata; i++) 00440 data[i] = a.data[i-ndata+a.ndata]; 00441 00442 return out; 00443 } 00444 00445 template<class T> 00446 void Array<T>::swap(int i, int j) 00447 { 00448 it_assert_debug(in_range(i) && in_range(j), 00449 "Array::swap(): Indices out of range."); 00450 00451 T temp = data[i]; 00452 data[i] = data[j]; 00453 data[j] = temp; 00454 } 00455 00456 template<class T> 00457 void Array<T>::set_subarray(int i1, int i2, const Array<T> &a) 00458 { 00459 if (i1 == -1) i1 = ndata-1; 00460 if (i2 == -1) i2 = ndata-1; 00461 00462 it_assert_debug(in_range(i1) && in_range(i2), 00463 "Array<T>::set_subarray(): Indices out of range."); 00464 it_assert_debug(i2 >= i1, "Array<T>::set_subarray(): i2 >= i1 necessary."); 00465 it_assert_debug(i2-i1+1 == a.ndata, "Array<T>::set_subarray(): Wrong sizes."); 00466 00467 copy_vector(a.ndata, a.data, data+i1); 00468 } 00469 00470 template<class T> 00471 void Array<T>::set_subarray(int i1, int i2, const T t) 00472 { 00473 if (i1 == -1) i1 = ndata-1; 00474 if (i2 == -1) i2 = ndata-1; 00475 00476 it_assert_debug(in_range(i1) && in_range(i2), 00477 "Array<T>::set_subarray(): Indices out of range"); 00478 it_assert_debug(i2 >= i1, "Array<T>::set_subarray(): i2 >= i1 necessary"); 00479 00480 for (int i = i1; i <= i2; i++) 00481 data[i] = t; 00482 } 00483 00484 template<class T> 00485 const Array<T> concat(const Array<T> &a, const T e) 00486 { 00487 Array<T> temp(a.size()+1); 00488 00489 for (int i = 0; i < a.size(); i++) 00490 temp(i) = a(i); 00491 temp(a.size()) = e; 00492 00493 return temp; 00494 } 00495 00496 template<class T> 00497 const Array<T> concat(const T e, const Array<T> &a) 00498 { 00499 Array<T> temp(a.size()+1); 00500 00501 temp(0) = e; 00502 00503 for (int i = 0; i < a.size(); i++) 00504 temp(i+1) = a(i); 00505 00506 return temp; 00507 } 00508 00509 template<class T> 00510 const Array<T> concat(const Array<T> &a1, const Array<T> &a2) 00511 { 00512 Array<T> temp(a1.size()+a2.size()); 00513 00514 for (int i = 0; i < a1.size(); i++) 00515 temp(i) = a1(i); 00516 for (int i = 0; i < a2.size(); i++) 00517 temp(a1.size()+i) = a2(i); 00518 00519 return temp; 00520 } 00521 00522 template<class T> 00523 const Array<T> concat(const Array<T> &a1, const Array<T> &a2, 00524 const Array<T> &a3) 00525 { 00526 // There should be some error control? 00527 Array<T> temp(a1.size()+a2.size()+a3.size()); 00528 00529 for (int i = 0; i < a1.size(); i++) 00530 temp(i) = a1(i); 00531 for (int i = 0; i < a2.size(); i++) 00532 temp(a1.size()+i) = a2(i); 00533 for (int i = 0; i < a3.size(); i++) 00534 temp(a1.size()+a2.size()+i) = a3(i); 00535 00536 return temp; 00537 } 00538 00543 template<class T> 00544 std::ostream &operator<<(std::ostream &os, const Array<T> &a) 00545 { 00546 os << "{"; 00547 for (int i = 0; i < a.size()-1; i++) 00548 os << a(i) << " "; 00549 if (a.size() > 0) 00550 os << a(a.size()-1); 00551 os << "}"; 00552 00553 return os; 00554 } 00555 00560 template<class T> 00561 std::istream &operator>>(std::istream &is, Array<T> &a) 00562 { 00563 int nrof_elements = 0; 00564 char c; 00565 is >> c; 00566 if (c == '{') { 00567 is >> c; 00568 while (c != '}') { 00569 if (is.eof()) { 00570 is.setstate(std::ios_base::failbit); 00571 break; 00572 } 00573 if (c != ',') { // Discard comma signs between elements 00574 is.putback(c); 00575 } 00576 if (++nrof_elements > a.size()) { 00577 a.set_size(nrof_elements, true); // Too slow? 00578 } 00579 is >> a(nrof_elements-1); 00580 is >> c; 00581 } 00582 if (a.size() > nrof_elements) { 00583 a.set_size(nrof_elements, true); 00584 } 00585 } else { 00586 is.setstate(std::ios_base::failbit); 00587 } 00588 00589 return is; 00590 } 00591 00597 template<class T> 00598 void set_array(Array<T> &a, const char *values) 00599 { 00600 std::istringstream buffer(values); 00601 buffer >> a; 00602 } 00603 00609 template<class T> 00610 void set_array(Array<T> &a, const std::string &str) 00611 { 00612 set_array(a, str.c_str()); 00613 } 00614 00615 } // namespace itpp 00616 00617 #endif // #ifndef ARRAY_H
Generated on Sat Apr 19 10:57:50 2008 for IT++ by Doxygen 1.5.5