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
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
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
00264 T* tmp = data;
00265
00266 int old_ndata = ndata;
00267
00268 int min = (ndata < size) ? ndata : size;
00269
00270 alloc(size);
00271
00272 for (int i = 0; i < min; ++i) {
00273 data[i] = tmp[i];
00274 }
00275
00276 for (int i = min; i < size; ++i) {
00277 data[i] = T();
00278 }
00279
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
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 != ',') {
00575 is.putback(c);
00576 }
00577 if (++nrof_elements > a.size()) {
00578 a.set_size(nrof_elements, true);
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 }
00618
00619 #endif // #ifndef ARRAY_H