[35] | 1 | /*! |
---|
| 2 | * \file |
---|
| 3 | * \brief Definition of Array class (container) |
---|
| 4 | * \author Tobias Ringstrom and Adam Piatyszek |
---|
| 5 | * |
---|
| 6 | * ------------------------------------------------------------------------- |
---|
| 7 | * |
---|
| 8 | * IT++ - C++ library of mathematical, signal processing, speech processing, |
---|
| 9 | * and communications classes and functions |
---|
| 10 | * |
---|
| 11 | * Copyright (C) 1995-2007 (see AUTHORS file for a list of contributors) |
---|
| 12 | * |
---|
| 13 | * This program is free software; you can redistribute it and/or modify |
---|
| 14 | * it under the terms of the GNU General Public License as published by |
---|
| 15 | * the Free Software Foundation; either version 2 of the License, or |
---|
| 16 | * (at your option) any later version. |
---|
| 17 | * |
---|
| 18 | * This program is distributed in the hope that it will be useful, |
---|
| 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
| 21 | * GNU General Public License for more details. |
---|
| 22 | * |
---|
| 23 | * You should have received a copy of the GNU General Public License |
---|
| 24 | * along with this program; if not, write to the Free Software |
---|
| 25 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
---|
| 26 | * |
---|
| 27 | * ------------------------------------------------------------------------- |
---|
| 28 | */ |
---|
| 29 | |
---|
| 30 | #ifndef ARRAY_H |
---|
| 31 | #define ARRAY_H |
---|
| 32 | |
---|
| 33 | #include <itpp/base/itassert.h> |
---|
| 34 | #include <itpp/base/math/misc.h> |
---|
| 35 | #include <itpp/base/factory.h> |
---|
| 36 | #include <itpp/base/copy_vector.h> |
---|
| 37 | |
---|
| 38 | |
---|
| 39 | namespace itpp { |
---|
| 40 | |
---|
| 41 | // Forward declarations |
---|
| 42 | template<class T> class Array; |
---|
| 43 | //! Append element \c e to the end of the Array \c a |
---|
| 44 | template<class T> const Array<T> concat(const Array<T> &a, const T e); |
---|
| 45 | //! Append element \c e to the beginning of the Array \c a |
---|
| 46 | template<class T> const Array<T> concat(const T e, const Array<T> &a); |
---|
| 47 | //! Concat Arrays \c a1 and \c a2 |
---|
| 48 | template<class T> const Array<T> concat(const Array<T> &a1, |
---|
| 49 | const Array<T> &a2); |
---|
| 50 | //! Concat Arrays \c a1, \c a2 and \c a3 |
---|
| 51 | template<class T> const Array<T> concat(const Array<T> &a1, |
---|
| 52 | const Array<T> &a2, |
---|
| 53 | const Array<T> &a3); |
---|
| 54 | |
---|
| 55 | /*! |
---|
| 56 | \ingroup arr_vec_mat |
---|
| 57 | \brief General array class |
---|
| 58 | \author Tobias Ringstrom and Adam Piatyszek |
---|
| 59 | |
---|
| 60 | This class is a general linear array class for arbitrary types. The |
---|
| 61 | operations and functions are the same as for the vector \c Vec class |
---|
| 62 | (except for the arithmetics). |
---|
| 63 | |
---|
| 64 | For rarely used types you will need to instantiate the class by |
---|
| 65 | \code |
---|
| 66 | template class Array<type>; |
---|
| 67 | \endcode |
---|
| 68 | |
---|
| 69 | The following example shows how to define an Array of vectors: |
---|
| 70 | \code |
---|
| 71 | vec a = randn(10); |
---|
| 72 | vec b = randn(20); |
---|
| 73 | vec c = randn(30); |
---|
| 74 | Array<vec> my_array(3); |
---|
| 75 | my_array(0) = a; |
---|
| 76 | my_array(1) = b; |
---|
| 77 | my_array(2) = c; |
---|
| 78 | \endcode |
---|
| 79 | |
---|
| 80 | For types T with istream \c operator>> defined special constructor or |
---|
| 81 | \c operator= or \c set_array functions (see Related Functions) can be |
---|
| 82 | used to assign a string literal to an Array. The string literal has the |
---|
| 83 | same format that is used by the istream/ostream operators: |
---|
| 84 | |
---|
| 85 | \code |
---|
| 86 | // Initialise an array with three bit vectors |
---|
| 87 | Array<bvec> B = "{[1 0 1] [0 0 1] [1 0 0 0 1]}"; |
---|
| 88 | |
---|
| 89 | // Declare an Array of Arrays of vectors |
---|
| 90 | Array<Array<ivec> > an_array; |
---|
| 91 | |
---|
| 92 | // Assign with an Array containing 2 Arrays, |
---|
| 93 | // the first Array containing [1 2] and |
---|
| 94 | // the second Array containing [3 4 5] and [6 7] |
---|
| 95 | set_array(an_array, "{{[1 2]} {[3 4 5] [6 7]}}"); |
---|
| 96 | \endcode |
---|
| 97 | |
---|
| 98 | By default, Array elements are created using the default constructor |
---|
| 99 | for the element type. This can be changed by specifying a suitable |
---|
| 100 | Factory in the Array constructor call (see Detailed Description for |
---|
| 101 | Factory). |
---|
| 102 | */ |
---|
| 103 | template<class T> |
---|
| 104 | class Array { |
---|
| 105 | public: |
---|
| 106 | //! Default constructor. An element factory \c f can be specified. |
---|
| 107 | explicit Array(const Factory &f = DEFAULT_FACTORY); |
---|
| 108 | //! Create an Array of size \c n. An element factory \c f can be specified. |
---|
| 109 | Array(int n, const Factory &f = DEFAULT_FACTORY); |
---|
| 110 | //! Copy constructor. An element factory \c f can be specified. |
---|
| 111 | Array(const Array<T> &a, const Factory &f = DEFAULT_FACTORY); |
---|
| 112 | //! Create an Array from string. An element factory \c f can be specified. |
---|
| 113 | Array(const std::string& values, const Factory &f = DEFAULT_FACTORY); |
---|
| 114 | //! Create an Array from char*. An element factory \c f can be specified. |
---|
| 115 | Array(const char* values, const Factory &f = DEFAULT_FACTORY); |
---|
| 116 | |
---|
| 117 | //! Destructor |
---|
| 118 | virtual ~Array(); |
---|
| 119 | |
---|
| 120 | //! Get the \c i element |
---|
| 121 | T &operator()(int i); |
---|
| 122 | //! Get the \c i element |
---|
| 123 | const T &operator()(int i) const; |
---|
| 124 | //! Sub-array from element \c i1 to element \c i2 |
---|
| 125 | const Array<T> operator()(int i1, int i2) const; |
---|
| 126 | //! Sub-array with the elements given by the integer Array |
---|
| 127 | const Array<T> operator()(const Array<int> &indices) const; |
---|
| 128 | |
---|
| 129 | //! Get \c n left elements of the array |
---|
| 130 | Array<T> left(int n) const; |
---|
| 131 | //! Get \c n right elements of the array |
---|
| 132 | Array<T> right(int n) const; |
---|
| 133 | //! Get \c n elements of the array starting from \c pos |
---|
| 134 | Array<T> mid(int pos, int n) const; |
---|
| 135 | |
---|
| 136 | //! Assignment operator |
---|
| 137 | Array<T>& operator=(const T &e); |
---|
| 138 | //! Assignment operator |
---|
| 139 | Array<T>& operator=(const Array<T> &a); |
---|
| 140 | //! Assignment operator |
---|
| 141 | Array<T>& operator=(const char* values); |
---|
| 142 | |
---|
| 143 | //! Append element \c e to the end of the Array \c a |
---|
| 144 | friend const Array<T> concat <>(const Array<T> &a1, const T e); |
---|
| 145 | //! Concat element \c e to the beginning of the Array \c a |
---|
| 146 | friend const Array<T> concat <>(const T e, const Array<T> &a); |
---|
| 147 | //! Concat Arrays \c a1 and \c a2 |
---|
| 148 | friend const Array<T> concat <>(const Array<T> &a1,const Array<T> &a2); |
---|
| 149 | //! Concat Arrays \c a1, \c a2 and \c a3 |
---|
| 150 | friend const Array<T> concat <>(const Array<T> &a1, const Array<T> &a2, |
---|
| 151 | const Array<T> &a3); |
---|
| 152 | |
---|
| 153 | //! Returns the number of data elements in the array object |
---|
| 154 | int size() const { return ndata; } |
---|
| 155 | //! Returns the number of data elements in the array object |
---|
| 156 | int length() const { return ndata; } |
---|
| 157 | //! Resizing an Array<T>. |
---|
| 158 | void set_size(int n, bool copy = false); |
---|
| 159 | //! Resizing an Array<T>. |
---|
| 160 | void set_length(int n, bool copy = false) { set_size(n, copy); } |
---|
| 161 | |
---|
| 162 | //! Shift in data at position 0. Return data from the last position. |
---|
| 163 | T shift_right(const T& e); |
---|
| 164 | //! Shift in array at position 0. Return data from the last position. |
---|
| 165 | const Array<T> shift_right(const Array<T> &a); |
---|
| 166 | //! Shift in data at the last position. Return data from position 0. |
---|
| 167 | T shift_left(const T& e); |
---|
| 168 | //! Shift in array at the last position. Return data from position 0. |
---|
| 169 | const Array<T> shift_left(const Array<T> &a); |
---|
| 170 | //! Swap elements i and j. |
---|
| 171 | void swap(int i, int j); |
---|
| 172 | |
---|
| 173 | //! Set the subarray defined by indicies i1 to i2 to Array<T> a. |
---|
| 174 | void set_subarray(int i1, int i2, const Array<T> &a); |
---|
| 175 | //! Set the subarray defined by indicies i1 to i2 the element value t. |
---|
| 176 | void set_subarray(int i1, int i2, const T t); |
---|
| 177 | |
---|
| 178 | protected: |
---|
| 179 | //! Allocate storage for an array of length \c n |
---|
| 180 | void alloc(int n); |
---|
| 181 | //! Free the storage space allocated by the array |
---|
| 182 | void free(); |
---|
| 183 | //! Check whether index \c i is in the allowed range |
---|
| 184 | bool in_range(int i) const { return ((i < ndata) && (i >= 0)); } |
---|
| 185 | //! The current number of elements in the Array |
---|
| 186 | int ndata; |
---|
| 187 | //! A pointer to the data area |
---|
| 188 | T *data; |
---|
| 189 | //! Element factory (by default set to DEFAULT_FACTORY) |
---|
| 190 | const Factory &factory; |
---|
| 191 | }; |
---|
| 192 | |
---|
| 193 | // -------------------- Implementation starts here -------------------- |
---|
| 194 | |
---|
| 195 | template<class T> inline |
---|
| 196 | void Array<T>::alloc(int n) |
---|
| 197 | { |
---|
| 198 | if (n > 0) { |
---|
| 199 | create_elements(data, n, factory); |
---|
| 200 | ndata = n; |
---|
| 201 | } |
---|
| 202 | else { |
---|
| 203 | data = 0; |
---|
| 204 | ndata = 0; |
---|
| 205 | } |
---|
| 206 | } |
---|
| 207 | |
---|
| 208 | template<class T> inline |
---|
| 209 | void Array<T>::free() |
---|
| 210 | { |
---|
| 211 | destroy_elements(data, ndata); |
---|
| 212 | ndata = 0; |
---|
| 213 | } |
---|
| 214 | |
---|
| 215 | template<class T> inline |
---|
| 216 | Array<T>::Array(const Factory &f) : ndata(0), data(0), factory(f) {} |
---|
| 217 | |
---|
| 218 | template<class T> inline |
---|
| 219 | Array<T>::Array(const int n, const Factory &f) : ndata(0), data(0), factory(f) |
---|
| 220 | { |
---|
| 221 | alloc(n); |
---|
| 222 | } |
---|
| 223 | |
---|
| 224 | template<class T> inline |
---|
| 225 | Array<T>::Array(const Array<T> &a, const Factory &f) |
---|
| 226 | : ndata(0), data(0), factory(f) |
---|
| 227 | { |
---|
| 228 | alloc(a.ndata); |
---|
| 229 | for (int i = 0; i < a.ndata; i++) |
---|
| 230 | data[i] = a.data[i]; |
---|
| 231 | } |
---|
| 232 | |
---|
| 233 | template<class T> inline |
---|
| 234 | Array<T>::Array(const std::string& values, const Factory &f) |
---|
| 235 | : ndata(0), data(0), factory(f) |
---|
| 236 | { |
---|
| 237 | std::istringstream buffer(values); |
---|
| 238 | buffer >> *this; |
---|
| 239 | } |
---|
| 240 | |
---|
| 241 | template<class T> inline |
---|
| 242 | Array<T>::Array(const char* values, const Factory &f) |
---|
| 243 | : ndata(0), data(0), factory(f) |
---|
| 244 | { |
---|
| 245 | std::istringstream buffer(values); |
---|
| 246 | buffer >> *this; |
---|
| 247 | } |
---|
| 248 | |
---|
| 249 | template<class T> |
---|
| 250 | Array<T>::~Array() |
---|
| 251 | { |
---|
| 252 | free(); |
---|
| 253 | } |
---|
| 254 | |
---|
| 255 | template<class T> |
---|
| 256 | void Array<T>::set_size(int size, bool copy) |
---|
| 257 | { |
---|
| 258 | it_assert_debug(size >= 0, "Array::set_size(): New size must not be negative"); |
---|
| 259 | if (ndata == size) |
---|
| 260 | return; |
---|
| 261 | if (copy) { |
---|
| 262 | // create a temporary pointer to the allocated data |
---|
| 263 | T* tmp = data; |
---|
| 264 | // store the current number of elements |
---|
| 265 | int old_ndata = ndata; |
---|
| 266 | // check how many elements we need to copy |
---|
| 267 | int min = (ndata < size) ? ndata : size; |
---|
| 268 | // allocate new memory |
---|
| 269 | alloc(size); |
---|
| 270 | // copy old elements into a new memory region |
---|
| 271 | for (int i = 0; i < min; ++i) { |
---|
| 272 | data[i] = tmp[i]; |
---|
| 273 | } |
---|
| 274 | // initialize the rest of resized array |
---|
| 275 | for (int i = min; i < size; ++i) { |
---|
| 276 | data[i] = T(); |
---|
| 277 | } |
---|
| 278 | // delete old elements |
---|
| 279 | destroy_elements(tmp, old_ndata); |
---|
| 280 | } |
---|
| 281 | else { |
---|
| 282 | free(); |
---|
| 283 | alloc(size); |
---|
| 284 | } |
---|
| 285 | } |
---|
| 286 | |
---|
| 287 | |
---|
| 288 | template<class T> inline |
---|
| 289 | T& Array<T>::operator()(int i) |
---|
| 290 | { |
---|
| 291 | it_assert_debug(in_range(i), "Array::operator(): Improper index"); |
---|
| 292 | return data[i]; |
---|
| 293 | } |
---|
| 294 | |
---|
| 295 | template<class T> inline |
---|
| 296 | const T& Array<T>::operator()(int i) const |
---|
| 297 | { |
---|
| 298 | it_assert_debug(in_range(i), "Array::operator(): Improper index"); |
---|
| 299 | return data[i]; |
---|
| 300 | } |
---|
| 301 | |
---|
| 302 | template<class T> inline |
---|
| 303 | const Array<T> Array<T>::operator()(int i1, int i2) const |
---|
| 304 | { |
---|
| 305 | it_assert_debug(in_range(i1) && in_range(i2) && (i2 >= i1), |
---|
| 306 | "Array::operator()(i1, i2): Improper indexes."); |
---|
| 307 | Array<T> s(i2-i1+1); |
---|
| 308 | for (int i = 0; i < s.ndata; i++) |
---|
| 309 | s.data[i] = data[i1+i]; |
---|
| 310 | return s; |
---|
| 311 | } |
---|
| 312 | |
---|
| 313 | template<class T> inline |
---|
| 314 | const Array<T> Array<T>::operator()(const Array<int> &indices) const |
---|
| 315 | { |
---|
| 316 | Array<T> a(indices.size()); |
---|
| 317 | for (int i = 0; i < a.size(); i++) { |
---|
| 318 | it_assert_debug(in_range(indices(i)), |
---|
| 319 | "Array::operator()(indices): Improper indices."); |
---|
| 320 | a(i) = data[indices(i)]; |
---|
| 321 | } |
---|
| 322 | return a; |
---|
| 323 | } |
---|
| 324 | |
---|
| 325 | template<class T> inline |
---|
| 326 | Array<T>& Array<T>::operator=(const Array<T> &a) |
---|
| 327 | { |
---|
| 328 | if (this != &a) { |
---|
| 329 | set_size(a.ndata); |
---|
| 330 | for (int i=0; i<ndata; i++) |
---|
| 331 | data[i] = a.data[i]; |
---|
| 332 | } |
---|
| 333 | return *this; |
---|
| 334 | } |
---|
| 335 | |
---|
| 336 | template<class T> inline |
---|
| 337 | Array<T>& Array<T>::operator=(const T &e) |
---|
| 338 | { |
---|
| 339 | if (ndata == 0) |
---|
| 340 | set_size(1); |
---|
| 341 | for (int i = 0; i < ndata; i++) |
---|
| 342 | data[i] = e; |
---|
| 343 | return *this; |
---|
| 344 | } |
---|
| 345 | |
---|
| 346 | template<class T> |
---|
| 347 | Array<T>& Array<T>::operator=(const char* values) |
---|
| 348 | { |
---|
| 349 | std::istringstream buffer(values); |
---|
| 350 | buffer >> *this; |
---|
| 351 | return *this; |
---|
| 352 | } |
---|
| 353 | |
---|
| 354 | |
---|
| 355 | template<class T> |
---|
| 356 | Array<T> Array<T>::left(int n) const |
---|
| 357 | { |
---|
| 358 | it_assert_debug(in_range(n), "Array::left(): Index out of range"); |
---|
| 359 | Array<T> tmp(n); |
---|
| 360 | for (int i = 0; i < n; ++i) |
---|
| 361 | tmp.data[i] = data[i]; |
---|
| 362 | return tmp; |
---|
| 363 | } |
---|
| 364 | |
---|
| 365 | template<class T> |
---|
| 366 | Array<T> Array<T>::right(int n) const |
---|
| 367 | { |
---|
| 368 | it_assert_debug(in_range(n), "Array::right(): Index out of range"); |
---|
| 369 | Array<T> tmp(n); |
---|
| 370 | for (int i = 0; i < n; ++i) |
---|
| 371 | tmp.data[i] = data[ndata-n+i]; |
---|
| 372 | return tmp; |
---|
| 373 | } |
---|
| 374 | |
---|
| 375 | template<class T> |
---|
| 376 | Array<T> Array<T>::mid(int pos, int n) const |
---|
| 377 | { |
---|
| 378 | it_assert_debug((pos >= 0) && (n > 0) && (pos + n <= ndata), "Array::mid(): Indexing out of range"); |
---|
| 379 | Array<T> tmp(n); |
---|
| 380 | for (int i = 0; i < n; ++i) |
---|
| 381 | tmp.data[i] = data[pos+i]; |
---|
| 382 | return tmp; |
---|
| 383 | } |
---|
| 384 | |
---|
| 385 | |
---|
| 386 | template<class T> |
---|
| 387 | T Array<T>::shift_right(const T& x) |
---|
| 388 | { |
---|
| 389 | it_assert_debug(ndata > 0, "Array::shift_right(x): Array empty!"); |
---|
| 390 | T ret; |
---|
| 391 | |
---|
| 392 | ret = data[ndata-1]; |
---|
| 393 | for (int i = ndata-1; i > 0; i--) |
---|
| 394 | data[i] = data[i-1]; |
---|
| 395 | data[0] = x; |
---|
| 396 | |
---|
| 397 | return ret; |
---|
| 398 | } |
---|
| 399 | |
---|
| 400 | |
---|
| 401 | template<class T> |
---|
| 402 | const Array<T> Array<T>::shift_right(const Array<T> &a) |
---|
| 403 | { |
---|
| 404 | it_assert_debug(a.ndata <= ndata, "Array::shift_right(): Shift Array too large"); |
---|
| 405 | Array<T> out(a.ndata); |
---|
| 406 | |
---|
| 407 | for (int i = 0; i < a.ndata; i++) |
---|
| 408 | out.data[i] = data[ndata-a.ndata+i]; |
---|
| 409 | for (int i = ndata-1; i >= a.ndata; i--) |
---|
| 410 | data[i] = data[i-a.ndata]; |
---|
| 411 | for (int i = 0; i < a.ndata; i++) |
---|
| 412 | data[i] = a.data[i]; |
---|
| 413 | |
---|
| 414 | return out; |
---|
| 415 | } |
---|
| 416 | |
---|
| 417 | template<class T> |
---|
| 418 | T Array<T>::shift_left(const T& x) |
---|
| 419 | { |
---|
| 420 | T temp = data[0]; |
---|
| 421 | |
---|
| 422 | for (int i = 0; i < ndata-1; i++) |
---|
| 423 | data[i] = data[i+1]; |
---|
| 424 | data[ndata-1] = x; |
---|
| 425 | |
---|
| 426 | return temp; |
---|
| 427 | } |
---|
| 428 | |
---|
| 429 | template<class T> |
---|
| 430 | const Array<T> Array<T>::shift_left(const Array<T> &a) |
---|
| 431 | { |
---|
| 432 | it_assert_debug(a.ndata <= ndata, "Array::shift_left(): Shift Array too large"); |
---|
| 433 | Array<T> out(a.ndata); |
---|
| 434 | |
---|
| 435 | for (int i = 0; i < a.ndata; i++) |
---|
| 436 | out.data[i] = data[i]; |
---|
| 437 | for (int i = 0; i < ndata-a.ndata; i++) |
---|
| 438 | data[i] = data[i+a.ndata]; |
---|
| 439 | for (int i = ndata-a.ndata; i < ndata; i++) |
---|
| 440 | data[i] = a.data[i-ndata+a.ndata]; |
---|
| 441 | |
---|
| 442 | return out; |
---|
| 443 | } |
---|
| 444 | |
---|
| 445 | template<class T> |
---|
| 446 | void Array<T>::swap(int i, int j) |
---|
| 447 | { |
---|
| 448 | it_assert_debug(in_range(i) && in_range(j), |
---|
| 449 | "Array::swap(): Indices out of range."); |
---|
| 450 | |
---|
| 451 | T temp = data[i]; |
---|
| 452 | data[i] = data[j]; |
---|
| 453 | data[j] = temp; |
---|
| 454 | } |
---|
| 455 | |
---|
| 456 | template<class T> |
---|
| 457 | void Array<T>::set_subarray(int i1, int i2, const Array<T> &a) |
---|
| 458 | { |
---|
| 459 | if (i1 == -1) i1 = ndata-1; |
---|
| 460 | if (i2 == -1) i2 = ndata-1; |
---|
| 461 | |
---|
| 462 | it_assert_debug(in_range(i1) && in_range(i2), |
---|
| 463 | "Array<T>::set_subarray(): Indices out of range."); |
---|
| 464 | it_assert_debug(i2 >= i1, "Array<T>::set_subarray(): i2 >= i1 necessary."); |
---|
| 465 | it_assert_debug(i2-i1+1 == a.ndata, "Array<T>::set_subarray(): Wrong sizes."); |
---|
| 466 | |
---|
| 467 | copy_vector(a.ndata, a.data, data+i1); |
---|
| 468 | } |
---|
| 469 | |
---|
| 470 | template<class T> |
---|
| 471 | void Array<T>::set_subarray(int i1, int i2, const T t) |
---|
| 472 | { |
---|
| 473 | if (i1 == -1) i1 = ndata-1; |
---|
| 474 | if (i2 == -1) i2 = ndata-1; |
---|
| 475 | |
---|
| 476 | it_assert_debug(in_range(i1) && in_range(i2), |
---|
| 477 | "Array<T>::set_subarray(): Indices out of range"); |
---|
| 478 | it_assert_debug(i2 >= i1, "Array<T>::set_subarray(): i2 >= i1 necessary"); |
---|
| 479 | |
---|
| 480 | for (int i = i1; i <= i2; i++) |
---|
| 481 | data[i] = t; |
---|
| 482 | } |
---|
| 483 | |
---|
| 484 | template<class T> |
---|
| 485 | const Array<T> concat(const Array<T> &a, const T e) |
---|
| 486 | { |
---|
| 487 | Array<T> temp(a.size()+1); |
---|
| 488 | |
---|
| 489 | for (int i = 0; i < a.size(); i++) |
---|
| 490 | temp(i) = a(i); |
---|
| 491 | temp(a.size()) = e; |
---|
| 492 | |
---|
| 493 | return temp; |
---|
| 494 | } |
---|
| 495 | |
---|
| 496 | template<class T> |
---|
| 497 | const Array<T> concat(const T e, const Array<T> &a) |
---|
| 498 | { |
---|
| 499 | Array<T> temp(a.size()+1); |
---|
| 500 | |
---|
| 501 | temp(0) = e; |
---|
| 502 | |
---|
| 503 | for (int i = 0; i < a.size(); i++) |
---|
| 504 | temp(i+1) = a(i); |
---|
| 505 | |
---|
| 506 | return temp; |
---|
| 507 | } |
---|
| 508 | |
---|
| 509 | template<class T> |
---|
| 510 | const Array<T> concat(const Array<T> &a1, const Array<T> &a2) |
---|
| 511 | { |
---|
| 512 | Array<T> temp(a1.size()+a2.size()); |
---|
| 513 | |
---|
| 514 | for (int i = 0; i < a1.size(); i++) |
---|
| 515 | temp(i) = a1(i); |
---|
| 516 | for (int i = 0; i < a2.size(); i++) |
---|
| 517 | temp(a1.size()+i) = a2(i); |
---|
| 518 | |
---|
| 519 | return temp; |
---|
| 520 | } |
---|
| 521 | |
---|
| 522 | template<class T> |
---|
| 523 | const Array<T> concat(const Array<T> &a1, const Array<T> &a2, |
---|
| 524 | const Array<T> &a3) |
---|
| 525 | { |
---|
| 526 | // There should be some error control? |
---|
| 527 | Array<T> temp(a1.size()+a2.size()+a3.size()); |
---|
| 528 | |
---|
| 529 | for (int i = 0; i < a1.size(); i++) |
---|
| 530 | temp(i) = a1(i); |
---|
| 531 | for (int i = 0; i < a2.size(); i++) |
---|
| 532 | temp(a1.size()+i) = a2(i); |
---|
| 533 | for (int i = 0; i < a3.size(); i++) |
---|
| 534 | temp(a1.size()+a2.size()+i) = a3(i); |
---|
| 535 | |
---|
| 536 | return temp; |
---|
| 537 | } |
---|
| 538 | |
---|
| 539 | /*! |
---|
| 540 | \relates Array |
---|
| 541 | \brief Output stream for Array<T>. T must have ostream operator<< defined. |
---|
| 542 | */ |
---|
| 543 | template<class T> |
---|
| 544 | std::ostream &operator<<(std::ostream &os, const Array<T> &a) |
---|
| 545 | { |
---|
| 546 | os << "{"; |
---|
| 547 | for (int i = 0; i < a.size()-1; i++) |
---|
| 548 | os << a(i) << " "; |
---|
| 549 | if (a.size() > 0) |
---|
| 550 | os << a(a.size()-1); |
---|
| 551 | os << "}"; |
---|
| 552 | |
---|
| 553 | return os; |
---|
| 554 | } |
---|
| 555 | |
---|
| 556 | /*! |
---|
| 557 | \relates Array |
---|
| 558 | \brief Input stream for Array<T>. T must have istream operator>> defined. |
---|
| 559 | */ |
---|
| 560 | template<class T> |
---|
| 561 | std::istream &operator>>(std::istream &is, Array<T> &a) |
---|
| 562 | { |
---|
| 563 | int nrof_elements = 0; |
---|
| 564 | char c; |
---|
| 565 | is >> c; |
---|
| 566 | if (c == '{') { |
---|
| 567 | is >> c; |
---|
| 568 | while (c != '}') { |
---|
| 569 | if (is.eof()) { |
---|
| 570 | is.setstate(std::ios_base::failbit); |
---|
| 571 | break; |
---|
| 572 | } |
---|
| 573 | if (c != ',') { // Discard comma signs between elements |
---|
| 574 | is.putback(c); |
---|
| 575 | } |
---|
| 576 | if (++nrof_elements > a.size()) { |
---|
| 577 | a.set_size(nrof_elements, true); // Too slow? |
---|
| 578 | } |
---|
| 579 | is >> a(nrof_elements-1); |
---|
| 580 | is >> c; |
---|
| 581 | } |
---|
| 582 | if (a.size() > nrof_elements) { |
---|
| 583 | a.set_size(nrof_elements, true); |
---|
| 584 | } |
---|
| 585 | } else { |
---|
| 586 | is.setstate(std::ios_base::failbit); |
---|
| 587 | } |
---|
| 588 | |
---|
| 589 | return is; |
---|
| 590 | } |
---|
| 591 | |
---|
| 592 | /*! |
---|
| 593 | \relates Array |
---|
| 594 | \brief Assign a C-style string to an Array<T>. T must have istream |
---|
| 595 | operator>> defined. |
---|
| 596 | */ |
---|
| 597 | template<class T> |
---|
| 598 | void set_array(Array<T> &a, const char *values) |
---|
| 599 | { |
---|
| 600 | std::istringstream buffer(values); |
---|
| 601 | buffer >> a; |
---|
| 602 | } |
---|
| 603 | |
---|
| 604 | /*! |
---|
| 605 | \relates Array |
---|
| 606 | \brief Assign a string to an Array<T>. T must have istream operator>> |
---|
| 607 | defined. |
---|
| 608 | */ |
---|
| 609 | template<class T> |
---|
| 610 | void set_array(Array<T> &a, const std::string &str) |
---|
| 611 | { |
---|
| 612 | set_array(a, str.c_str()); |
---|
| 613 | } |
---|
| 614 | |
---|
| 615 | } // namespace itpp |
---|
| 616 | |
---|
| 617 | #endif // #ifndef ARRAY_H |
---|