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