vtf-logo

ArrayContainer.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00008 #if !defined(__ArrayContainer_h__)
00009 #define __ArrayContainer_h__
00010 
00011 // If we are debugging the whole ads package.
00012 #if defined(DEBUG_ads) && !defined(DEBUG_ArrayContainer)
00013 #define DEBUG_ArrayContainer
00014 #endif
00015 
00016 #include "ArrayTypes.h"
00017 
00018 // For Int2Type.
00019 #include "../../third-party/loki/TypeManip.h"
00020 
00021 #include <iosfwd>
00022 #include <iostream>
00023 #include <numeric>
00024 #include <algorithm>
00025 #include <limits>
00026 
00027 #include <cassert>
00028 #include <cmath>
00029 
00030 BEGIN_NAMESPACE_ADS
00031 
00033 
00040 template<typename T = double, bool A = true>
00041 class ArrayContainer
00042 {
00043 private:
00044 
00045   //
00046   // Private types.
00047   //
00048 
00049   typedef ArrayTypes<T> types;
00050 
00051 public:
00052 
00053   //
00054   // Public types.
00055   //
00056 
00058   typedef typename types::value_type value_type;
00060 
00063   typedef typename types::parameter_type parameter_type;
00065 
00068   typedef typename types::unqualified_value_type unqualified_value_type;
00069 
00071   typedef typename types::pointer pointer;
00073   typedef typename types::const_pointer const_pointer;
00074 
00076   typedef typename types::iterator iterator;
00078   typedef typename types::const_iterator const_iterator;
00079 
00081   typedef typename types::reference reference;
00083   typedef typename types::const_reference const_reference;
00084 
00086 
00092   typedef typename types::size_type size_type;
00094   typedef typename types::difference_type difference_type;
00095 
00096 private:
00097 
00098   //
00099   // Private data.
00100   //
00101 
00102   // The start of the data.
00103   pointer _start;
00104   // The end of the data.
00105   pointer _finish;
00106   // Number of elements in the array.
00107   size_type _size;
00108 
00109 protected:
00110 
00111   //--------------------------------------------------------------------------
00113   // @{
00114 
00116   ArrayContainer() :
00117     _start(0),
00118     _finish(0),
00119     _size(0)
00120   {}
00121 
00122   // Copy constructor.
00127   ArrayContainer(const ArrayContainer& x) :
00128     _start(0),
00129     _finish(0),
00130     _size(0) {
00131     copy(x);
00132   }
00133 
00134   // Copy constructor for an array of different type or allocation policy.
00139   template<typename T2, bool A2>
00140   ArrayContainer(const ArrayContainer<T2,A2>& x) :
00141     _start(0),
00142     _finish(0),
00143     _size(0) {
00144     copy(x);
00145   }
00146 
00148 
00152   ArrayContainer& 
00153   operator=(const ArrayContainer& other) {
00154     if (&other != this) {
00155       copy(other);
00156     }
00157     return *this;
00158   }
00159 
00161 
00165   template<typename T2, bool A2>
00166   ArrayContainer& 
00167   operator=(const ArrayContainer<T2,A2>& x) {
00168     // No need to check if *this and x are the same.
00169     copy(x);
00170     return *this;
00171   }
00172 
00174 
00177   template<typename ForwardIterator>
00178   ArrayContainer(ForwardIterator start, ForwardIterator finish) :
00179     _start(0),
00180     _finish(0),
00181     _size(0) {
00182     copy_range(start, finish);
00183   }
00184 
00186 
00189   template<typename ForwardIterator>
00190   void
00191   rebuild(ForwardIterator start, ForwardIterator finish) {
00192     copy_range(start, finish);
00193   }
00194   
00196 
00199   template<typename Type>
00200   ArrayContainer(Type* start, Type* finish) :
00201     _start(0),
00202     _finish(0),
00203     _size(0) {
00204     copy_range(start, finish);
00205   }
00206 
00208 
00211   template<typename Type>
00212   void
00213   rebuild(Type* start, Type* finish) {
00214     copy_range(start, finish);
00215   }
00216   
00218 
00221   explicit
00222   ArrayContainer(const size_type size) :
00223     _start(0),
00224     _finish(0),
00225     _size(size) {
00226     allocate();
00227     _finish = _start + _size;
00228   }
00229 
00231 
00234   void
00235   rebuild(const size_type size) {
00236     _size = size;
00237     allocate();
00238     _finish = _start + _size;
00239   }
00240 
00242   void
00243   swap(ArrayContainer& other) {
00244     if (&other != this) {
00245       std::swap(_start, other._start);
00246       std::swap(_finish, other._finish);
00247       std::swap(_size, other._size);
00248     }
00249   }
00250 
00252   void
00253   resize(const size_type size) {
00254     resize(size, Loki::Int2Type<A>());
00255   }
00256   
00258   ~ArrayContainer() {
00259     destroy();
00260   }
00261 
00262   // @}
00263 
00264 public:
00265 
00266   //--------------------------------------------------------------------------
00268   // @{
00269 
00271   size_type 
00272   size() const {
00273     return _size;
00274   }
00275 
00277   bool 
00278   empty() const { 
00279     return _size == 0;
00280   }
00281 
00283   size_type
00284   max_size() const { 
00285     return std::numeric_limits<int>::max() / sizeof(value_type); 
00286   }
00287 
00289   const_iterator 
00290   begin() const { 
00291     return _start;
00292   }
00293 
00295   const_iterator 
00296   end() const { 
00297     return _finish;
00298   }
00299 
00301 
00306   pointer
00307   data() const { 
00308     return _start;
00309   }
00310 
00312 
00317   parameter_type 
00318   operator[](const int i) const {
00319 #ifdef DEBUG_ArrayContainer
00320     assert(0 <= i && i < _size);
00321 #endif 
00322     return _start[i]; 
00323   }
00324 
00326 
00329   size_type 
00330   getMemoryUsage() const {
00331     return sizeof(ArrayContainer) + size() * sizeof(value_type);
00332   }
00333 
00334   // @}
00335   //--------------------------------------------------------------------------
00337   // @{
00338 
00340   iterator 
00341   begin() { 
00342     return _start;
00343   }
00344 
00346   iterator 
00347   end() { 
00348     return _finish;
00349   }
00350 
00352   pointer
00353   data() { 
00354     return _start;
00355   }
00356 
00358 
00363   reference 
00364   operator[](const int i) { 
00365 #ifdef DEBUG_ArrayIndexing
00366     assert(0 <= i && i < size());
00367 #endif 
00368     return _start[i]; 
00369   }
00370 
00372   void
00373   negate();
00374 
00376   void
00377   fill(parameter_type value);
00378 
00379   // @}
00380   //--------------------------------------------------------------------------
00382   // @{
00383 
00385   ArrayContainer& 
00386   operator=(parameter_type x);
00387 
00388   // @}
00389   //--------------------------------------------------------------------------
00391   // @{
00392 
00393   //CONTINUE: Should I make these free functions?
00395   template<typename T2, bool A2>
00396   bool
00397   operator==(const ArrayContainer<T2,A2>& x) const {
00398     // Check that the arrays have the same size.
00399     if (size() != x.size()) {
00400       return false;
00401     }
00402     // Check each of the components.
00403     return std::equal(begin(), end(), x.begin());
00404   }
00405 
00407   template<typename T2, bool A2>
00408   bool
00409   operator!=(const ArrayContainer<T2,A2>& x) const {
00410     return ! operator==(x);
00411   }
00412 
00413   // @}
00414   //--------------------------------------------------------------------------
00416   // @{
00417 
00419   void
00420   put(std::ostream& out) const {
00421     for (const_iterator iter = begin(); iter != end(); ++iter) {
00422       out << *iter << '\n';
00423     }
00424   }  
00425 
00427   void
00428   get(std::istream& in) {
00429     for (iterator iter = begin(); iter != end(); ++iter) {
00430       in >> *iter;
00431     }
00432   }
00433 
00435   void
00436   write(std::ostream& out) const {
00437     out.write(reinterpret_cast<const char*>(begin()), 
00438                size() * sizeof(value_type));
00439   }
00440 
00442   void
00443   write_elements_ascii(std::ostream& out) const {
00444     put(out);
00445   }
00446 
00448   void
00449   write_elements_binary(std::ostream& out) const {
00450     write(out);
00451   }
00452 
00454   void
00455   read(std::istream& in) {
00456     in.read(reinterpret_cast<char*>(begin()), 
00457              size() * sizeof(value_type));
00458     assert(in.gcount() == size_type(size() * sizeof(value_type)));
00459   }
00460 
00462   void
00463   read_elements_ascii(std::istream& in) {
00464     get(in);
00465   }
00466 
00468   void
00469   read_elements_binary(std::istream& in) {
00470     read(in);
00471   }
00472 
00473   // @}
00474 
00475 private:
00476 
00477   //
00478   // Private member functions.
00479   //
00480 
00481   void
00482   resize(const size_type size, Loki::Int2Type<true>) {
00483     // If we need to resize this array.
00484     if (_size != size) {
00485       // Deallocate the old memory.
00486       destroy();
00487       // Set the size.
00488       _size = size;
00489       // Allocate new memory.
00490       allocate();
00491     }
00492     // Define the end of storage.
00493     _finish = _start + _size;
00494   }
00495   
00496   template<typename T2, bool A2>
00497   void
00498   copy(const ArrayContainer<T2,A2>& x) {
00499     copy_range(x.data(), x.data() + x.size());
00500   }
00501   
00502   template<typename ForwardIterator>
00503   void
00504   copy_range(ForwardIterator start, ForwardIterator finish) {
00505     copy_range(start, finish, Loki::Int2Type<A>());
00506   }
00507 
00508   template<typename ForwardIterator>
00509   void
00510   copy_range(ForwardIterator start, ForwardIterator finish, 
00511              Loki::Int2Type<true>) {
00512     // Resize the array if necessary.
00513     resize(std::distance(start, finish));
00514     // Copy the elements.
00515     std::copy(start, finish, _start);
00516   }
00517 
00518   template<typename RandomAccessIterator>
00519   void
00520   copy_range(RandomAccessIterator start, RandomAccessIterator finish, 
00521              Loki::Int2Type<false>) {
00522     _start = start;
00523     _finish = finish;
00524     _size = size_type(finish - start);
00525   }
00526 
00527   void
00528   allocate() {
00529     allocate(Loki::Int2Type<A>());
00530   }
00531 
00532   // Allocate the memory.
00533   void
00534   allocate(Loki::Int2Type<true>) {
00535     if (_size == 0) {
00536       _start = 0;
00537     }
00538     else {
00539       _start = new value_type[_size];
00540     }
00541   }
00542 
00543   // allocate(Loki::Int2Type<false>) is intentionally not implemented.
00544 
00545   // Allocate the memory.
00546   /*
00547   void
00548   allocate()
00549   {
00550     STATIC_CHECK(A == true, Trying_to_allocate_memory_when_A_is_false);
00551     
00552     if (_size == 0) {
00553       _start = 0;
00554     }
00555     else {
00556       _start = new value_type[ _size ];
00557     }
00558   }
00559   */
00560 
00561   void
00562   destroy() {
00563     deallocate();
00564     _start = 0;
00565     _finish = 0;
00566     _size = 0;
00567   }
00568 
00569   void
00570   deallocate() {
00571     deallocate(Loki::Int2Type<A>());
00572   }
00573 
00574   // Deallocate the memory.
00575   void
00576   deallocate(Loki::Int2Type<true>) {
00577     if (_size != 0) {
00578       delete[] _start;
00579     }
00580   }
00581 
00582   // No need to deallocate memory for array references.
00583   void
00584   deallocate(Loki::Int2Type<false>)
00585   {}
00586 };
00587 
00588 
00589 //-----------------------------------------------------------------------------
00592 
00593 //
00594 // Mathematical functions
00595 //
00596 
00598 
00602 template<typename T, bool A>
00603 inline
00604 T
00605 computeSum(const ArrayContainer<T,A>& x) {
00606   return std::accumulate(x.begin(), x.end(), T(0));
00607 }
00608     
00610 
00614 template<typename T, bool A>
00615 inline
00616 T
00617 computeProduct(const ArrayContainer<T,A>& x) {
00618   return std::accumulate(x.begin(), x.end(), T(1), std::multiplies<T>());
00619 }
00620 
00622 
00626 template<typename T, bool A>
00627 inline
00628 T
00629 computeMinimum(const ArrayContainer<T,A>& x) {
00630   // Check the case that the array is empty.  In this case we can't dereference
00631   // the iterator as we do below.
00632   if (x.empty()) {
00633     return std::numeric_limits<T>::max();
00634   }
00635   return *std::min_element(x.begin(), x.end());
00636 }
00637     
00639 
00643 template<typename T, bool A>
00644 inline
00645 T
00646 computeMaximum(const ArrayContainer<T,A>& x) {
00647   // Check the case that the array is empty.  In this case we can't dereference
00648   // the iterator as we do below.
00649   if (x.empty()) {
00650     return - std::numeric_limits<T>::max();
00651   }
00652   return *std::max_element(x.begin(), x.end());
00653 }
00654 
00655 //
00656 // Apply the standard math functions.
00657 //
00658 
00659 // CONTINUE: Should I relate it to the other classes as well?
00661 
00665 template<typename T, bool A>
00666 inline
00667 void
00668 applyAbs(ArrayContainer<T,A>* x) {
00669   for (typename ArrayContainer<T,A>::iterator i = x->begin(); i != x->end(); 
00670        ++i) {
00671     *i = std::abs(*i);
00672   }
00673 }
00674 
00676 
00680 template<typename T, bool A>
00681 inline
00682 void
00683 applyAcos(ArrayContainer<T,A>* x) {
00684   for (typename ArrayContainer<T,A>::iterator i = x->begin(); i != x->end(); 
00685        ++i) {
00686     *i = std::acos(*i);
00687   }
00688 }
00689 
00691 
00695 template<typename T, bool A>
00696 inline
00697 void
00698 applyAsin(ArrayContainer<T,A>* x) {
00699   for (typename ArrayContainer<T,A>::iterator i = x->begin(); i != x->end(); 
00700        ++i) {
00701     *i = std::asin(*i);
00702   }
00703 }
00704 
00706 
00710 template<typename T, bool A>
00711 inline
00712 void
00713 applyAtan(ArrayContainer<T,A>* x) {
00714   for (typename ArrayContainer<T,A>::iterator i = x->begin(); i != x->end(); 
00715        ++i) {
00716     *i = std::atan(*i);
00717   }
00718 }
00719 
00721 
00725 template<typename T, bool A>
00726 inline
00727 void
00728 applyCeil(ArrayContainer<T,A>* x) {
00729   for (typename ArrayContainer<T,A>::iterator i = x->begin(); i != x->end(); 
00730        ++i) {
00731     *i = std::ceil(*i);
00732   }
00733 }
00734 
00736 
00740 template<typename T, bool A>
00741 inline
00742 void
00743 applyCos(ArrayContainer<T,A>* x) {
00744   for (typename ArrayContainer<T,A>::iterator i = x->begin(); i != x->end(); 
00745        ++i) {
00746     *i = std::cos(*i);
00747   }
00748 }
00749 
00751 
00755 template<typename T, bool A>
00756 inline
00757 void
00758 applyCosh(ArrayContainer<T,A>* x) {
00759   for (typename ArrayContainer<T,A>::iterator i = x->begin(); i != x->end(); 
00760        ++i) {
00761     *i = std::cosh(*i);
00762   }
00763 }
00764 
00766 
00770 template<typename T, bool A>
00771 inline
00772 void
00773 applyExp(ArrayContainer<T,A>* x) {
00774   for (typename ArrayContainer<T,A>::iterator i = x->begin(); i != x->end(); 
00775        ++i) {
00776     *i = std::exp(*i);
00777   }
00778 }
00779 
00781 
00785 template<typename T, bool A>
00786 inline
00787 void
00788 applyFloor(ArrayContainer<T,A>* x) {
00789   for (typename ArrayContainer<T,A>::iterator i = x->begin(); i != x->end(); 
00790        ++i) {
00791     *i = std::floor(*i);
00792   }
00793 }
00794 
00796 
00800 template<typename T, bool A>
00801 inline
00802 void
00803 applyLog(ArrayContainer<T,A>* x) {
00804   for (typename ArrayContainer<T,A>::iterator i = x->begin(); i != x->end(); 
00805        ++i) {
00806     *i = std::log(*i);
00807   }
00808 }
00809 
00811 
00815 template<typename T, bool A>
00816 inline
00817 void
00818 applyLog10(ArrayContainer<T,A>* x) {
00819   for (typename ArrayContainer<T,A>::iterator i = x->begin(); i != x->end(); 
00820        ++i) {
00821     *i = std::log10(*i);
00822   }
00823 }
00824 
00826 
00830 template<typename T, bool A>
00831 inline
00832 void
00833 applySin(ArrayContainer<T,A>* x) {
00834   for (typename ArrayContainer<T,A>::iterator i = x->begin(); i != x->end(); 
00835        ++i) {
00836     *i = std::sin(*i);
00837   }
00838 }
00839 
00841 
00845 template<typename T, bool A>
00846 inline
00847 void
00848 applySinh(ArrayContainer<T,A>* x) {
00849   for (typename ArrayContainer<T,A>::iterator i = x->begin(); i != x->end(); 
00850        ++i) {
00851     *i = std::sinh(*i);
00852   }
00853 }
00854 
00856 
00860 template<typename T, bool A>
00861 inline
00862 void
00863 applySqrt(ArrayContainer<T,A>* x) {
00864   for (typename ArrayContainer<T,A>::iterator i = x->begin(); i != x->end(); 
00865        ++i) {
00866     *i = std::sqrt(*i);
00867   }
00868 }
00869 
00871 
00875 template<typename T, bool A>
00876 inline
00877 void
00878 applyTan(ArrayContainer<T,A>* x) {
00879   for (typename ArrayContainer<T,A>::iterator i = x->begin(); i != x->end(); 
00880        ++i) {
00881     *i = std::tan(*i);
00882   }
00883 }
00884 
00886 
00890 template<typename T, bool A>
00891 inline
00892 void
00893 applyTanh(ArrayContainer<T,A>* x) {
00894   for (typename ArrayContainer<T,A>::iterator i = x->begin(); i != x->end(); 
00895        ++i) {
00896     *i = std::tanh(*i);
00897   }
00898 }
00899 
00900 //
00901 // Assignment operators with scalar operand.
00902 //
00903 
00905 template<typename T, bool A>
00906 ArrayContainer<T,A>& 
00907 operator+=(ArrayContainer<T,A>& array, 
00908            typename ArrayContainer<T,A>::parameter_type x);
00909 
00911 template<typename T, bool A>
00912 ArrayContainer<T,A>& 
00913 operator-=(ArrayContainer<T,A>& array, 
00914            typename ArrayContainer<T,A>::parameter_type x);
00915 
00917 template<typename T, bool A>
00918 ArrayContainer<T,A>& 
00919 operator*=(ArrayContainer<T,A>& array, 
00920            typename ArrayContainer<T,A>::parameter_type x);
00921 
00923 template<typename T, bool A>
00924 ArrayContainer<T,A>& 
00925 operator/=(ArrayContainer<T,A>& array, 
00926            typename ArrayContainer<T,A>::parameter_type x);
00927 
00929 template<typename T, bool A>
00930 ArrayContainer<T,A>& 
00931 operator%=(ArrayContainer<T,A>& array, 
00932            typename ArrayContainer<T,A>::parameter_type x);
00933 
00935 template<typename T, bool A>
00936 ArrayContainer<T*,A>& 
00937 operator+=(ArrayContainer<T*,A>& array, 
00938            typename ArrayContainer<T*,A>::difference_type x);
00939 
00941 template<typename T, bool A>
00942 ArrayContainer<T*,A>& 
00943 operator-=(ArrayContainer<T*,A>& array, 
00944            typename ArrayContainer<T*,A>::difference_type x);
00945 
00946 //--------------------------------------------------------------------------
00947 // Assignment operators with array operand.
00948 //--------------------------------------------------------------------------
00949 
00951 template<typename T1, bool A1, typename T2, bool A2>
00952 ArrayContainer<T1,A1>& 
00953 operator+=(ArrayContainer<T1,A1>& x, const ArrayContainer<T2,A2> & y);
00954 
00956 template<typename T1, bool A1, typename T2, bool A2>
00957 ArrayContainer<T1,A1>& 
00958 operator-=(ArrayContainer<T1,A1>& x, const ArrayContainer<T2,A2> & y);
00959 
00961 template<typename T1, bool A1, typename T2, bool A2>
00962 ArrayContainer<T1,A1>& 
00963 operator*=(ArrayContainer<T1,A1>& x, const ArrayContainer<T2,A2> & y);
00964 
00966 template<typename T1, bool A1, typename T2, bool A2>
00967 ArrayContainer<T1,A1>& 
00968 operator/=(ArrayContainer<T1,A1>& x, const ArrayContainer<T2,A2> & y);
00969 
00971 template<typename T1, bool A1, typename T2, bool A2>
00972 ArrayContainer<T1,A1>& 
00973 operator%=(ArrayContainer<T1,A1>& x, const ArrayContainer<T2,A2> & y);
00974 
00975 //
00976 // Equality Operators
00977 //    
00978 
00979 // CONTINUE
00980 #if 0
00982 
00983 template<typename T1, typename T2, bool A1, bool A2>
00984 bool
00985 operator==(const ArrayContainer<T1,A1>& a, const ArrayContainer<T2,A2>& b) {
00986   return a.operator==(b);
00987 }
00988 
00990 
00991 template<typename T1, typename T2, bool A1, bool A2>
00992 inline
00993 bool
00994 operator!=(const ArrayContainer<T1,A1>& a, const ArrayContainer<T2,A2>& b) { 
00995   return !(a == b); 
00996 }
00997 #endif
00998 
01000 
01001 END_NAMESPACE_ADS
01002 
01003 #define __ArrayContainer_ipp__
01004 #include "ArrayContainer.ipp"
01005 #undef __ArrayContainer_ipp__
01006 
01007 #endif

Generated on Fri Aug 24 12:55:21 2007 for Algorithms and Data Structures Package by  doxygen 1.4.7