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