root/win32/itpp-4.0.1/itpp/base/array.h @ 44

Revision 35, 16.7 kB (checked in by mido, 16 years ago)

zasadni zmeny ve /win32

Line 
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
39namespace 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
Note: See TracBrowser for help on using the browser.