Simbody  3.4 (development)
Array.h
Go to the documentation of this file.
00001 #ifndef SimTK_SimTKCOMMON_ARRAY_H_
00002 #define SimTK_SimTKCOMMON_ARRAY_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                       Simbody(tm): SimTKcommon                             *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK biosimulation toolkit originating from           *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
00011  *                                                                            *
00012  * Portions copyright (c) 2010-13 Stanford University and the Authors.        *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
00017  * not use this file except in compliance with the License. You may obtain a  *
00018  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
00019  *                                                                            *
00020  * Unless required by applicable law or agreed to in writing, software        *
00021  * distributed under the License is distributed on an "AS IS" BASIS,          *
00022  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
00023  * See the License for the specific language governing permissions and        *
00024  * limitations under the License.                                             *
00025  * -------------------------------------------------------------------------- */
00026 
00033 #include "SimTKcommon/internal/common.h"
00034 #include "SimTKcommon/internal/ExceptionMacros.h"
00035 #include "SimTKcommon/internal/Serialize.h"
00036 
00037 #include <algorithm>
00038 #include <iterator>
00039 #include <vector>
00040 #include <ostream>
00041 #include <climits>
00042 #include <typeinfo>
00043 
00044 namespace SimTK {
00045 
00046 // These are the classes defined in this header.
00047 template <class X>                   struct ArrayIndexTraits;
00048 template <class T, class X=unsigned> class  ArrayViewConst_;
00049 template <class T, class X=unsigned> class  ArrayView_;
00050 template <class T, class X=unsigned> class  Array_;
00051 
00052 
00053 
00054 //==============================================================================
00055 //                           CLASS ArrayIndexTraits
00056 //==============================================================================
00057 
00100 template <class X> struct ArrayIndexTraits {
00103     typedef typename X::size_type       size_type;
00106     typedef typename X::difference_type difference_type;
00109     static size_type max_size() {return X::max_size();}
00110 };
00111 
00114 template <> struct ArrayIndexTraits<unsigned> {
00115     typedef unsigned        size_type;
00116     typedef int             difference_type;
00117     static size_type        max_size() {return (unsigned)INT_MAX;}
00118 };
00119 
00121 template <> struct ArrayIndexTraits<int> {
00122     typedef int             size_type;
00123     typedef int             difference_type;
00124     static size_type        max_size() {return INT_MAX;}
00125 };
00126 
00134 template <> struct ArrayIndexTraits<unsigned long> {
00135     typedef unsigned long       size_type;
00136     typedef long                difference_type;
00137     static size_type            max_size() {return (unsigned long)LONG_MAX;}
00138 };
00139 
00147 template <> struct ArrayIndexTraits<long> {
00148     typedef long                size_type;
00149     typedef long                difference_type;
00150     static size_type            max_size() {return LONG_MAX;}
00151 };
00152 
00158 template <> struct ArrayIndexTraits<unsigned short> {
00159     typedef unsigned short      size_type;
00160     typedef int                 difference_type;
00161     static size_type            max_size() {return USHRT_MAX;}
00162 };
00163 
00168 template <> struct ArrayIndexTraits<short> {
00169     typedef short               size_type;
00170     typedef short               difference_type;
00171     static size_type            max_size() {return SHRT_MAX;}
00172 }; 
00173 
00174 
00179 template <> struct ArrayIndexTraits<unsigned char> {
00180     typedef unsigned char       size_type;
00181     typedef short               difference_type;
00182     static size_type            max_size() {return UCHAR_MAX;} // not CHAR_MAX
00183 };
00184 
00190 template <> struct ArrayIndexTraits<signed char> {
00191     typedef signed char         size_type;
00192     typedef signed char         difference_type;
00193     static size_type            max_size() {return SCHAR_MAX;}
00194 };
00195 
00202 template <> struct ArrayIndexTraits<char> {
00203     typedef char                size_type;
00204     typedef signed char         difference_type;
00205     static size_type            max_size() {return (char)SCHAR_MAX;}
00206 };
00207 
00213 template <> struct ArrayIndexTraits<bool> {
00214     typedef unsigned char       size_type;
00215     typedef signed char         difference_type;
00216     static size_type            max_size() {return 2;}
00217 };
00218 
00221 template <> struct ArrayIndexTraits<unsigned long long> {
00222     typedef unsigned long long  size_type;
00223     typedef long long           difference_type;
00224     static size_type            max_size() 
00225                                     {return (unsigned long long)LLONG_MAX;}
00226 };
00227 
00230 template <> struct ArrayIndexTraits<long long> {
00231     typedef long long           size_type;
00232     typedef long long           difference_type;
00233     static size_type            max_size() {return LLONG_MAX;}
00234 };
00235 
00236 // Don't show this in Doxygen.
00238 // This helper class decides what integral type we should use to best pack
00239 // the index type's size_type representation. The idea is to pack the whole
00240 // Array_ structure into 8 bytes on a 32 bit machine, 16 bytes on a 64 bit
00241 // machine, using the largest integral type that will work, giving a layout
00242 // like this:          |       data pointer     |
00243 //                     |   nUsed   | nAllocated |
00244 
00245 // The default implementation just uses the integral type itself.
00246 template <class Integral, class is64Bit> struct ArrayIndexPackTypeHelper 
00247 {   typedef Integral packed_size_type;};
00248 
00249 // On 32 bit machine, pack anything smaller than a short into a short.
00250 template<> struct ArrayIndexPackTypeHelper<bool,FalseType> 
00251 {   typedef unsigned short packed_size_type;};
00252 template<> struct ArrayIndexPackTypeHelper<char,FalseType> 
00253 {   typedef unsigned short packed_size_type;};
00254 template<> struct ArrayIndexPackTypeHelper<unsigned char,FalseType> 
00255 {   typedef unsigned short packed_size_type;};
00256 template<> struct ArrayIndexPackTypeHelper<signed char,FalseType> 
00257 {   typedef short packed_size_type;};
00258 
00259 // On 64 bit machine, pack anything smaller than an int into an int.
00260 template<> struct ArrayIndexPackTypeHelper<bool,TrueType> 
00261 {   typedef unsigned int packed_size_type;};
00262 template<> struct ArrayIndexPackTypeHelper<char,TrueType> 
00263 {   typedef unsigned int packed_size_type;};
00264 template<> struct ArrayIndexPackTypeHelper<unsigned char,TrueType> 
00265 {   typedef unsigned int packed_size_type;};
00266 template<> struct ArrayIndexPackTypeHelper<signed char,TrueType> 
00267 {   typedef int packed_size_type;};
00268 template<> struct ArrayIndexPackTypeHelper<unsigned short,TrueType> 
00269 {   typedef unsigned int packed_size_type;};
00270 template<> struct ArrayIndexPackTypeHelper<short,TrueType> 
00271 {   typedef int packed_size_type;};
00272 
00273 template <class Integral> struct ArrayIndexPackType
00274 {   typedef typename ArrayIndexPackTypeHelper<Integral,Is64BitPlatformType>
00275                         ::packed_size_type  packed_size_type;};
00283 //==============================================================================
00284 //                            CLASS ArrayViewConst_
00285 //==============================================================================
00312 template <class T, class X> class ArrayViewConst_ {
00313 public:
00314 
00315 
00316 //------------------------------------------------------------------------------
00323 typedef T           value_type;
00325 typedef X           index_type;
00327 typedef T*          pointer;
00329 typedef const T*    const_pointer;
00331 typedef T&          reference;
00333 typedef const T&    const_reference;
00335 typedef T*          iterator;
00337 typedef const T*    const_iterator;
00339 typedef std::reverse_iterator<iterator>                 reverse_iterator;
00341 typedef std::reverse_iterator<const_iterator>           const_reverse_iterator;
00343 typedef typename ArrayIndexTraits<X>::size_type         size_type;
00346 typedef typename ArrayIndexTraits<X>::difference_type   difference_type;
00348 typedef typename ArrayIndexPackType<size_type>::packed_size_type 
00349                                                         packed_size_type;
00353 //------------------------------------------------------------------------------
00359 
00361 ArrayViewConst_() : pData(0), nUsed(0), nAllocated(0) {}
00362 
00372 ArrayViewConst_(const ArrayViewConst_& src) 
00373 :   pData(0), nUsed(src.nUsed), nAllocated(0) {
00374     if (nUsed) pData = const_cast<T*>(src.pData);
00375 } 
00376 
00377 // Copy assignment is suppressed.
00378 
00401 ArrayViewConst_(const T* first, const T* last1) 
00402 :   pData(0),nUsed(0),nAllocated(0) { 
00403     if (last1==first) return; // empty
00404 
00405     SimTK_ERRCHK((first&&last1)||(first==last1), 
00406         "ArrayViewConst_<T>(first,last1)", 
00407         "One of the source pointers was null (0); either both must be"
00408         " non-null or both must be null.");
00409 
00410     SimTK_ERRCHK3(this->isSizeOK(last1-first), 
00411         "ArrayViewConst_<T>(first,last1)",
00412         "The source data's size %llu is too big for this array which"
00413         " is limited to %llu elements by its index type %s.",
00414         this->ull(last1-first), ullMaxSize(), indexName());
00415 
00416     pData = const_cast<T*>(first); 
00417     nUsed = packed_size_type(last1-first); 
00418     // nAllocated is already zero
00419 }
00420 
00448 template <class A>
00449 ArrayViewConst_(const std::vector<T,A>& src) 
00450 :   pData(0),nUsed(0),nAllocated(0) { 
00451     if (src.empty()) return;
00452 
00453     SimTK_ERRCHK3(this->isSizeOK(src.size()),
00454         "ArrayViewConst_<T>::ctor(std::vector<T>)",
00455         "The source std::vector's size %llu is too big for this array which"
00456         " is limited to %llu elements by its index type %s.",
00457         this->ull(src.size()), ullMaxSize(), indexName());
00458 
00459     pData = const_cast<T*>(&src.front()); 
00460     nUsed = packed_size_type(src.size()); 
00461     // nAllocated is already zero
00462 }
00465 operator const ArrayView_<T,X>&() const
00466 {   return *reinterpret_cast<const ArrayView_<T,X>*>(this); }
00469 operator const Array_<T,X>&() const
00470 {   return *reinterpret_cast<const Array_<T,X>*>(this); }
00471 
00477 void disconnect() {
00478     SimTK_ASSERT(nAllocated==0,
00479         "ArrayViewConst_::deallocate(): called on an owner Array_");
00480     nUsed = 0;
00481     pData = 0;
00482 }
00483 
00486 ~ArrayViewConst_() {
00487     disconnect();
00488 }
00492 //------------------------------------------------------------------------------
00499 
00501 size_type size() const {return size_type(nUsed);}
00503 size_type max_size() const {return ArrayIndexTraits<X>::max_size();}
00506 bool empty() const {return nUsed==0;}
00511 size_type capacity() const {return size_type(nAllocated?nAllocated:nUsed);}
00515 size_type allocated() const {return size_type(nAllocated);}
00521 bool isOwner() const {return nAllocated || pData==0;}
00522 /*}*/
00523 
00524 
00525 //------------------------------------------------------------------------------
00532 
00539 const T& operator[](index_type i) const {
00540     SimTK_INDEXCHECK(size_type(i),size(),"ArrayViewConst_<T>::operator[]()");
00541     return pData[i];
00542 }
00547 const T& at(index_type i) const {
00548     SimTK_INDEXCHECK_ALWAYS(size_type(i),size(),"ArrayViewConst_<T>::at()");
00549     return pData[i];
00550 }
00553 const T& getElt(index_type i) const {
00554     SimTK_INDEXCHECK(size_type(i),size(),"ArrayViewConst_<T>::getElt()");
00555     return pData[i];
00556 }
00562 const T& front() const 
00563 {   SimTK_ERRCHK(!empty(), "ArrayViewConst_<T>::front()", "Array was empty.");
00564     return pData[0]; }
00570 const T& back() const 
00571 {   SimTK_ERRCHK(!empty(), "ArrayViewConst_<T>::back()", "Array was empty.");
00572     return pData[nUsed-1]; }
00573 
00592 ArrayViewConst_ operator()(index_type index, size_type length) const {
00593     const size_type ix(index);
00594     SimTK_ERRCHK2(isSizeInRange(ix, size()), "ArrayViewConst_<T>(index,length)",
00595         "For this operator, we must have 0 <= index <= size(), but"
00596         " index==%llu and size==%llu.", this->ull(ix), ullSize());
00597     SimTK_ERRCHK2(isSizeInRange(length, size_type(size()-ix)), 
00598         "ArrayViewConst_<T>(index,length)", 
00599         "This operator requires 0 <= length <= size()-index, but"
00600         " length==%llu and size()-index==%llu.",this->ull(length),this->ull(size()-ix));
00601 
00602     return ArrayViewConst_(pData+ix, pData+ix+length);
00603 }
00606 ArrayViewConst_ getSubArray(index_type index, size_type length) const
00607 {   return (*this)(index,length); }
00608 
00612 //------------------------------------------------------------------------------
00621 
00626 const T* cbegin() const {return pData;}
00631 const T* cend() const {return pData + nUsed;}
00633 const T* begin() const {return pData;}
00635 const T* end() const {return pData + nUsed;}
00636 
00639 const_reverse_iterator crbegin() const {return const_reverse_iterator(cend());}
00643 const_reverse_iterator crend() const {return const_reverse_iterator(cbegin());}
00645 const_reverse_iterator rbegin() const {return crbegin();} 
00647 const_reverse_iterator rend() const {return crend();}
00648 
00655 const T* cdata() const {return pData;}
00657 const T* data() const {return pData;}
00661 //------------------------------------------------------------------------------
00662                                  protected:
00663 //------------------------------------------------------------------------------
00664 // The remainder of this class is for the use of the ArrayView_<T,X> and
00665 // Array_<T,X> derived classes only and should not be documented for users to 
00666 // see. 
00667                                      
00668 // Don't let doxygen see any of this.
00670 packed_size_type psize() const {return nUsed;}
00671 packed_size_type pallocated() const {return nAllocated;}
00672 
00673 // These provide direct access to the data members for our trusted friends.
00674 void setData(const T* p)        {pData = const_cast<T*>(p);}
00675 void setSize(size_type n)       {nUsed = packed_size_type(n);}
00676 void incrSize()                 {++nUsed;}
00677 void decrSize()                 {--nUsed;}
00678 void setAllocated(size_type n)  {nAllocated = packed_size_type(n);}
00679 
00680 // Check whether a given size is the same as the current size of this array,
00681 // avoiding any compiler warnings due to mismatched integral types.
00682 template <class S> 
00683 bool isSameSize(S sz) const
00684 {   return ull(sz) == ullSize(); }
00685 
00686 // Check that a source object's size will fit in the array being careful to
00687 // avoid overflow and warnings in the comparison.
00688 template <class S> 
00689 bool isSizeOK(S srcSz) const
00690 {   return ull(srcSz) <= ullMaxSize(); }
00691 
00692 // This is identical in function to std::distance() (reports how many 
00693 // elements lie between two iterators) but avoids any slow 
00694 // Release-build bugcatchers that Microsoft may have felt compelled to add.
00695 // The implementation is specialized for random access iterators because
00696 // they can measure distance very fast.
00697 template<class Iter> static
00698 typename std::iterator_traits<Iter>::difference_type
00699 iterDistance(const Iter& first, const Iter& last1) {
00700     return iterDistanceImpl(first,last1,
00701                 typename std::iterator_traits<Iter>::iterator_category());
00702 }
00703 
00704 // Generic slow implementation for non-random access iterators. This is fine
00705 // for forward and bidirectional iterators, but it will *consume* input
00706 // iterators so is useless for them.
00707 template<class Iter> static
00708 typename std::iterator_traits<Iter>::difference_type
00709 iterDistanceImpl(const Iter& first, const Iter& last1, std::input_iterator_tag) {
00710     typename std::iterator_traits<Iter>::difference_type d = 0;
00711     for (Iter src=first; src != last1; ++src, ++d)
00712         ;
00713     return d;
00714 }
00715 
00716 // Fast specialization for random access iterators (including ordinary
00717 // pointers) -- just subtract.
00718 template<class Iter> static
00719 typename std::iterator_traits<Iter>::difference_type
00720 iterDistanceImpl(const Iter& first, const Iter& last1, 
00721                  std::random_access_iterator_tag) {
00722     return last1 - first;
00723 }
00724 
00725 // This method attempts to determine whether any elements in the iterator range
00726 // [first,last1) overlap with the elements stored in this array. This is used 
00727 // for error checks for operations where source is not permitted to overlap the
00728 // destination. For random access iterators (including ordinary pointers), we 
00729 // can answer this question definitively because we expect the data to be 
00730 // consecutive in memory. For other kinds of iterators, we will just assume
00731 // there is no overlap. Note that null ranges do not overlap even if the
00732 // pair of equal iterators points within the other range -- what matters is
00733 // the number of overlapping elements.
00734 template<class Iter> bool
00735 overlapsWithData(const Iter& first, const Iter& last1) {
00736     return overlapsWithDataImpl(first,last1,
00737                 typename std::iterator_traits<Iter>::iterator_category());
00738 }
00739 
00740 // This is a partial specialization of the above where the data is given
00741 // with ordinary pointers.
00742 template <class T2> bool
00743 overlapsWithData(const T2* first, const T2* last1) {
00744     // Find the start and end+1 of the alleged overlap region. There is
00745     // overlap iff end+1 > start. Note that this works if either range 
00746     // is [0,0) or [p,p), or if last1 is illegally less than first (we just
00747     // want to report no overlap in that case -- it is someone else's business
00748     // to complain).
00749     const T* obegin = std::max(cbegin(), (const T*)first);
00750     const T* oend1  = std::min(cend(),   (const T*)last1);
00751 
00752     return obegin < oend1;
00753 }
00754 
00755 // This is the generic implementation for any type of input iterator other than
00756 // random access (i.e., bidirectional, forward, or input) -- assume no overlap.
00757 template<class Iter> bool
00758 overlapsWithDataImpl(const Iter&, const Iter&, std::input_iterator_tag) 
00759 {   return false; }
00760 
00761 // Here we can actually test for overlap since we have random access iterators.
00762 // We convert them to pointers and then look for memory overlap.
00763 template<class Iter> bool
00764 overlapsWithDataImpl(const Iter& first, const Iter& last1, 
00765                      std::random_access_iterator_tag) {
00766     // We must check that the input iterators span a non-zero range before
00767     // assuming we can dereference them.
00768     if (last1 <= first)
00769         return false; // zero or malformed source range: no overlap
00770 
00771     // We now know we can dereference first and last1-1 (can't safely 
00772     // dereference last1 but we can use pointer arithmetic to point past
00773     // the (last-1)th element in memory). We then take the dereferenced
00774     // object's address to get ordinary pointers that we can use to 
00775     // watch for illegal overlap.
00776     return overlapsWithData(&*first, &*(last1-1)); // use pointer overload
00777 }
00778 
00779 // Cast an integral type to maximal-width unsigned long long to avoid accidental
00780 // overflows that might otherwise occur due to wraparound that can happen 
00781 // with small index types.
00782 template <class S>
00783 static unsigned long long ull(S sz)
00784 {   return (unsigned long long)sz; }
00785 
00786 // Return size(), capacity(), and max_size() cast to unsigned long long.
00787 unsigned long long ullSize()     const {return ull(size());}
00788 unsigned long long ullCapacity() const {return ull(capacity());}
00789 unsigned long long ullMaxSize()  const {return ull(max_size());}
00790 
00791 // Useful in error messages for explaining why something was too big.
00792 const char* indexName() const {return NiceTypeName<X>::name();}
00793 
00796 private:
00797 //------------------------------------------------------------------------------
00798 //                               DATA MEMBERS
00799 // These are the only data members and this layout is guaranteed not to change
00800 // from release to release. If data is null, then nUsed==nAllocated==0.
00801 
00802 T*                  pData;      // ptr to data referenced here, or 0 if none
00803 packed_size_type    nUsed;      // number of elements currently present (size)
00804 packed_size_type    nAllocated; // heap allocation; 0 if pData is not owned
00805 
00806 ArrayViewConst_& operator=(const ArrayViewConst_& src); // suppressed
00807 };
00808 
00809 
00810 
00811 
00812 
00813 
00814 //==============================================================================
00815 //                            CLASS ArrayView_
00816 //==============================================================================
00828 template <class T, class X> class ArrayView_ : public ArrayViewConst_<T,X> {
00829 typedef ArrayViewConst_<T,X> CBase;
00830 public:
00831 //------------------------------------------------------------------------------
00836 /*{*/
00837 typedef T                                               value_type;
00838 typedef X                                               index_type;
00839 typedef T*                                              pointer;
00840 typedef const T*                                        const_pointer;
00841 typedef T&                                              reference;
00842 typedef const T&                                        const_reference;
00843 typedef T*                                              iterator;
00844 typedef const T*                                        const_iterator;
00845 typedef std::reverse_iterator<iterator>                 reverse_iterator;
00846 typedef std::reverse_iterator<const_iterator>           const_reverse_iterator;
00847 typedef typename ArrayIndexTraits<X>::size_type         size_type;
00848 typedef typename ArrayIndexTraits<X>::difference_type   difference_type;
00849 typedef typename ArrayIndexPackType<size_type>::packed_size_type 
00850                                                         packed_size_type;
00851 /*}*/
00852 
00853 
00854 //------------------------------------------------------------------------------
00860 
00862 ArrayView_() : CBase() {}
00863 
00865 ArrayView_(const ArrayView_& src) : CBase(src) {}
00866 
00868 ArrayView_(T* first, const T* last1) : CBase(first,last1) {} 
00869 
00871 template <class A>
00872 ArrayView_(std::vector<T,A>& v) : CBase(v) {}
00873 
00875 operator const Array_<T,X>&() const 
00876 {   return *reinterpret_cast<const Array_<T,X>*>(this); }  
00877 
00879 operator Array_<T,X>&() 
00880 {   return *reinterpret_cast<Array_<T,X>*>(this); } 
00881 
00884 void disconnect() {this->CBase::disconnect();}
00885 
00888 ~ArrayView_() {this->CBase::disconnect();}
00892 //------------------------------------------------------------------------------
00904 
00906 ArrayView_& operator=(const ArrayView_& src) {
00907     if (&src != this)
00908         avAssignIteratorDispatch(src.cbegin(), src.cend(),
00909                                  std::random_access_iterator_tag(),
00910                                  "ArrayView_<T>::operator=(ArrayView_<T>)");
00911     return *this;
00912 }
00913 
00914 
00917 template <class T2, class X2>
00918 ArrayView_& operator=(const ArrayViewConst_<T2,X2>& src) {
00919     if ((const void*)&src != (void*)this)
00920         avAssignIteratorDispatch(src.cbegin(), src.cend(),
00921                                  std::random_access_iterator_tag(),
00922                                  "ArrayView_<T>::operator=(Array_<T2>)");
00923     return *this;
00924 }
00925 
00926 // Help out dumb compilers struggling to match the template arguments and
00927 // promote the Array_ or ArrayView_ to ArrayConstView_ at the same time.
00928 
00931 template <class T2, class X2>
00932 ArrayView_& operator=(const ArrayView_<T2,X2>& src)
00933 {   return *this = static_cast<const ArrayViewConst_<T2,X2>&>(src); }
00936 template <class T2, class X2>
00937 ArrayView_& operator=(const Array_<T2,X2>& src)
00938 {   return *this = static_cast<const ArrayViewConst_<T2,X2>&>(src); }
00939 
00942 template <class T2, class A2>
00943 ArrayView_& operator=(const std::vector<T2,A2>& src) {
00944     avAssignIteratorDispatch(src.begin(), src.end(),
00945                              std::random_access_iterator_tag(),
00946                              "ArrayView_<T>::operator=(std::vector<T2>)");
00947     return *this;
00948 }
00949 
00951 ArrayView_& operator=(const T& fillValue) 
00952 {   fill(fillValue); return *this; }
00953 
00959 ArrayView_& fill(const T& fillValue) {
00960     for (T* d = begin(); d != end(); ++d)
00961         *d = fillValue; // using T::operator=(T)
00962     return *this;
00963 }
00964 
00968 void assign(size_type n, const T& fillValue) {
00969     SimTK_ERRCHK2(n == size(), "ArrayView_<T>::assign(n,value)",
00970         "Assignment to an ArrayView is permitted only if the source"
00971         " is the same size. Here n==%llu element(s) but the"
00972         " ArrayView has a fixed size of %llu.", 
00973         this->ull(n), this->ull(size()));
00974 
00975     fill(fillValue);
00976 }
00977 
00995 template <class T2>
00996 void assign(const T2* first, const T2* last1) {
00997     const char* methodName = "ArrayView_<T>::assign(T2* first, T2* last1)";
00998     SimTK_ERRCHK((first&&last1)||(first==last1), methodName, 
00999         "One of the source pointers was null (0); either both must be"
01000         " non-null or both must be null.");
01001     // Valid pointers are random access iterators.
01002     avAssignIteratorDispatch(first, last1, std::random_access_iterator_tag(),
01003                              methodName);
01004 }
01005 
01035 // Watch out for integral types matching this signature -- they must be
01036 // forwarded to the assign(n, fillValue) signature instead.
01037 template <class Iter>
01038 void assign(const Iter& first, const Iter& last1)
01039 {   avAssignDispatch(first,last1,typename IsIntegralType<Iter>::Result(),
01040                      "ArrayView_<T>::assign(Iter first, Iter last1)"); }
01044 //------------------------------------------------------------------------------
01051 
01058 const T& operator[](index_type i) const {return this->CBase::operator[](i);}
01059 
01067 T& operator[](index_type i) {return const_cast<T&>(this->CBase::operator[](i));}
01068 
01073 const T& at(index_type i) const {return this->CBase::at(i);}
01074 
01079 T& at(index_type i) {return const_cast<T&>(this->CBase::at(i));}
01080 
01083 const T& getElt(index_type i) const {return this->CBase::getElt(i);}
01086 T& updElt(index_type i) {return const_cast<T&>(this->CBase::getElt(i));}
01087 
01093 const T& front() const {return this->CBase::front();} 
01094 
01100 T& front() {return const_cast<T&>(this->CBase::front());}
01101 
01107 const T& back() const {return this->CBase::back();}
01108 
01114 T& back() {return const_cast<T&>(this->CBase::back());}
01115 
01134 ArrayView_ operator()(index_type index, size_type length) {
01135     const size_type ix(index);
01136     SimTK_ERRCHK2(isSizeInRange(ix, size()), "ArrayView_<T>(index,length)",
01137         "For this operator, we must have 0 <= index <= size(), but"
01138         " index==%llu and size==%llu.", this->ull(ix), ullSize());
01139     SimTK_ERRCHK2(isSizeInRange(length, size_type(size()-ix)), 
01140         "ArrayView_<T>(index,length)", 
01141         "This operator requires 0 <= length <= size()-index, but"
01142         " length==%llu and size()-index==%llu.",this->ull(length),this->ull(size()-ix));
01143 
01144     return ArrayView_(data()+ix, data()+ix+length);
01145 }
01148 ArrayView_ updSubArray(index_type index, size_type length)
01149 {   return (*this)(index,length); }
01153 //------------------------------------------------------------------------------
01162 
01167 const T* cbegin() const {return this->CBase::cbegin();}
01169 const T* begin() const {return this->CBase::cbegin();}
01174 T* begin() {return const_cast<T*>(this->CBase::cbegin());}
01175 
01180 const T* cend() const {return this->CBase::cend();}
01182 const T* end() const {return this->CBase::cend();}
01187 T* end() {return const_cast<T*>(this->CBase::cend());}
01188 
01191 const_reverse_iterator crbegin() const {return this->CBase::crbegin();}
01193 const_reverse_iterator rbegin() const {return this->CBase::crbegin();} 
01196 reverse_iterator rbegin() {return reverse_iterator(end());}
01197 
01201 const_reverse_iterator crend() const {return this->CBase::crend();}
01203 const_reverse_iterator rend() const {return this->CBase::crend();}
01207 reverse_iterator rend() {return reverse_iterator(begin());}
01208 
01215 const T* cdata() const {return this->CBase::cdata();}
01218 const T* data() const {return this->CBase::cdata();}
01222 T* data() {return const_cast<T*>(this->CBase::cdata());}
01226 //------------------------------------------------------------------------------
01232 
01233 // Note: these have to be explicitly forwarded to the base class methods
01234 // in order to keep gcc from complaining. Note that the "this->" is 
01235 // apparently necessary in order to permit delayed definition of templatized 
01236 // methods. Doxygen picks up the comments from the base class.
01237 
01238 size_type size()      const {return this->CBase::size();}
01239 size_type max_size()  const {return this->CBase::max_size();}
01240 bool      empty()     const {return this->CBase::empty();}
01241 size_type capacity()  const {return this->CBase::capacity();}
01242 size_type allocated() const {return this->CBase::allocated();}
01243 bool      isOwner()   const {return this->CBase::isOwner();}
01247 //------------------------------------------------------------------------------
01248                                    private:
01249 //------------------------------------------------------------------------------
01250 // no data members are allowed
01251 
01252 //------------------------------------------------------------------------------
01253 //                       ARRAY VIEW ASSIGN DISPATCH
01254 // This is the assign() implementation for ArrayView_ when the class that 
01255 // matched the alleged InputIterator template argument turned out to be one of 
01256 // the integral types in which case this should match the assign(n, fillValue) 
01257 // signature.
01258 template <class IntegralType>
01259 void avAssignDispatch(IntegralType n, IntegralType v, TrueType isIntegralType,
01260                       const char*) 
01261 {   assign(size_type(n), value_type(v)); }
01262 
01263 // This is the assign() implementation for ArrayView_ when the class that 
01264 // matched the alleged InputIterator template argument is NOT an integral type 
01265 // and may very well be an iterator. 
01266 template <class InputIterator> 
01267 void avAssignDispatch(const InputIterator& first, const InputIterator& last1, 
01268                       FalseType isIntegralType, const char* methodName) 
01269 {   avAssignIteratorDispatch(first, last1, 
01270         typename std::iterator_traits<InputIterator>::iterator_category(),
01271         methodName); }
01272 
01273 // This is the assign() implementation for a plain input_iterator
01274 // (i.e., not a forward, bidirectional, or random access iterator). These
01275 // have the unfortunate property that we can't count the elements in advance.
01276 // Here we're going to complain if there aren't enough; but will simply stop
01277 // when we get size() elements and not insist that the input stream reached
01278 // the supplied last1 iterator. Semantics is elementwise assignment.
01279 template <class InputIterator>
01280 void avAssignIteratorDispatch(const InputIterator& first, 
01281                               const InputIterator& last1, 
01282                               std::input_iterator_tag, 
01283                               const char* methodName) 
01284 {
01285     T* p = begin();
01286     InputIterator src = first;
01287     while (src != last1 && p != end())
01288         *p++ = *src++; // call T's assignment operator
01289 
01290     // p now points just after the last element that was copied.
01291     const size_type nCopied = size_type(p - begin());
01292     SimTK_ERRCHK2_ALWAYS(nCopied == size(), methodName,
01293         "The supplied input_iterator provided only %llu elements but this"
01294         " ArrayView has a fixed size of %llu elements.",
01295         this->ull(nCopied), ullSize());
01296 
01297     // We don't care if there are still more input elements available.
01298 }
01299 
01300 // This is the assign() implementation that works for forward and bidirectional
01301 // iterators, but is not used for random_access_iterators. Here we'll count
01302 // the elements as we copy them and complain at the end if there were too
01303 // few or too many.
01304 template <class ForwardIterator>
01305 void avAssignIteratorDispatch(const ForwardIterator& first, 
01306                               const ForwardIterator& last1,
01307                               std::forward_iterator_tag, 
01308                               const char* methodName) 
01309 {
01310     T* p = begin();
01311     ForwardIterator src = first;
01312     while (src != last1 && p != end())
01313         *p++ = *src++; // call T's assignment operator
01314 
01315     // p now points just after the last element that was copied.
01316     const size_type nCopied = size_type(p - begin());
01317     SimTK_ERRCHK2_ALWAYS(nCopied == size(), methodName,
01318         "The supplied forward_ or bidirectional_iterator source range provided"
01319         " only %llu elements but this ArrayView has a fixed size of"
01320         " %llu elements.", this->ull(nCopied), ullSize());
01321 
01322     // Make sure we ran out of source elements.
01323     SimTK_ERRCHK1_ALWAYS(src == last1, methodName,
01324         "The supplied forward_ or bidirectional_iterator source range"
01325         " contained too many elements; this ArrayView has a fixed size of"
01326         " %llu elements.", ullSize());
01327 }
01328 
01329 // This is the assign() implementation that works for random_access_iterators
01330 // including ordinary pointers. Here we check the number of elements in advance
01331 // and complain if the source and destination aren't the same size. The 
01332 // copying loop can be done faster in this case.
01333 template <class RandomAccessIterator>
01334 void avAssignIteratorDispatch(const RandomAccessIterator& first, 
01335                               const RandomAccessIterator& last1,
01336                               std::random_access_iterator_tag, 
01337                               const char* methodName) 
01338 {
01339     SimTK_ERRCHK2_ALWAYS(this->isSameSize(last1-first), methodName,
01340         "Assignment to an ArrayView is permitted only if the source"
01341         " is the same size. Here the source had %llu element(s) but the"
01342         " ArrayView has a fixed size of %llu.", 
01343         this->ull(last1-first), this->ull(size()));
01344 
01345     SimTK_ERRCHK_ALWAYS(!this->overlapsWithData(first,last1), methodName,
01346         "Source range can't overlap with the destination data.");
01347 
01348     T* p = begin();
01349     RandomAccessIterator src = first;
01350     while (p != end())
01351         *p++ = *src++; // call T's assignment operator
01352 }
01353 
01354 
01355 //------------------------------------------------------------------------------
01356 // The following private methods are protected methods in the ArrayViewConst_ 
01357 // base class, so they should not need repeating here. However, we explicitly 
01358 // forward to the base methods to avoid gcc errors. The gcc complaint
01359 // is due to their not depending on any template parameters; the "this->"
01360 // apparently fixes that problem.
01361 
01362 packed_size_type psize()      const {return this->CBase::psize();}
01363 packed_size_type pallocated() const {return this->CBase::pallocated();}
01364 
01365 // This just cast sizes to unsigned long long so that we can do comparisons
01366 // without getting warnings.
01367 unsigned long long ullSize()     const {return this->CBase::ullSize();}
01368 unsigned long long ullCapacity() const {return this->CBase::ullCapacity();}
01369 unsigned long long ullMaxSize()  const {return this->CBase::ullMaxSize();}
01370 // This is the index type name and is handy for error messages to explain
01371 // why some size was too big.
01372 const char* indexName() const   {return this->CBase::indexName();}
01373 };
01374 
01375 
01376 
01377 
01378 
01379 //==============================================================================
01380 //                               CLASS Array_
01381 //==============================================================================
01484 template <class T, class X> class Array_ : public ArrayView_<T,X> {
01485     typedef ArrayView_<T,X>      Base;
01486     typedef ArrayViewConst_<T,X> CBase;
01487 public:
01488 
01489 
01490 //------------------------------------------------------------------------------
01496 // Doxygen picks up individual descriptions from the base class.
01497 /*{*/
01498 typedef T                                               value_type;
01499 typedef X                                               index_type;
01500 typedef T*                                              pointer;
01501 typedef const T*                                        const_pointer;
01502 typedef T&                                              reference;
01503 typedef const T&                                        const_reference;
01504 typedef T*                                              iterator;
01505 typedef const T*                                        const_iterator;
01506 typedef std::reverse_iterator<iterator>                 reverse_iterator;
01507 typedef std::reverse_iterator<const_iterator>           const_reverse_iterator;
01508 typedef typename ArrayIndexTraits<X>::size_type         size_type;
01509 typedef typename ArrayIndexTraits<X>::difference_type   difference_type;
01510 typedef typename ArrayIndexPackType<size_type>::packed_size_type 
01511                                                         packed_size_type;
01512 /*}*/
01513 
01514 //------------------------------------------------------------------------------
01521 /*{*/
01522 
01524 Array_() : Base() {}
01525 
01530 explicit Array_(size_type n) : Base() {
01531     SimTK_SIZECHECK(n, max_size(), "Array_<T>::ctor(n)");
01532     allocateNoConstruct(n);
01533     defaultConstruct(data(), data()+n);
01534     setSize(n);
01535 }
01536 
01540 Array_(size_type n, const T& initVal) : Base() {
01541     SimTK_SIZECHECK(n, max_size(), "Array_<T>::ctor(n,T)");
01542     setSize(n);
01543     allocateNoConstruct(size());
01544     fillConstruct(begin(), cend(), initVal);
01545 }
01561 template <class InputIter>
01562 Array_(const InputIter& first, const InputIter& last1) : Base() {
01563     ctorDispatch(first,last1,typename IsIntegralType<InputIter>::Result());
01564 }
01565 
01571 template <class T2>
01572 Array_(const T2* first, const T2* last1) : Base() {
01573     SimTK_ERRCHK((first&&last1)||(first==last1), "Array_<T>(first,last1)", 
01574         "Pointers must be non-null unless they are both null.");
01575     SimTK_ERRCHK3(this->isSizeOK(last1-first), "Array_<T>(first,last1)",
01576         "Source has %llu elements but this array is limited to %llu"
01577         " elements by its index type %s.",
01578         this->ull(last1-first), ullMaxSize(), indexName());
01579 
01580     setSize(size_type(last1-first));
01581     allocateNoConstruct(size());
01582     copyConstruct(begin(), cend(), first);
01583 }
01584 
01589 template <class T2>
01590 explicit Array_(const std::vector<T2>& v) : Base() { 
01591     if (v.empty()) return;
01592 
01593     SimTK_ERRCHK3(this->isSizeOK(v.size()), "Array_<T>::ctor(std::vector<T2>)",
01594         "The source std::vector's size %llu is too big for this array which"
01595         " is limited to %llu elements by its index type %s.",
01596         this->ull(v.size()), ullMaxSize(), indexName());
01597 
01598     // Call the above constructor, making sure to use pointers into the
01599     // vector's data rather than the iterators begin() and end() in case
01600     // they are different types.
01601     new (this) Array_(&v.front(), (&v.back())+1);
01602 }
01603 
01608 Array_(const Array_& src) : Base() {
01609     setSize(src.size());
01610     allocateNoConstruct(size());
01611     copyConstruct(begin(), cend(), src.data());
01612 }
01613 
01620 template <class T2, class X2>
01621 Array_(const Array_<T2,X2>& src) : Base() {
01622     new (this) Array_(src.begin(), src.cend()); // see above
01623 }
01624 
01654 Array_(T* first, const T* last1, const DontCopy&) : Base(first,last1) {}
01655 
01683 template <class A>
01684 Array_(std::vector<T,A>& v, const DontCopy&) : Base(v) {}
01685 
01689 ~Array_() {
01690     deallocate();
01691 }
01692 
01701 Array_& deallocate() {
01702     if (allocated()) { // owner with non-zero allocation
01703         clear(); // each element is destructed; size()=0; allocated() unchanged
01704         deallocateNoDestruct(); // free data(); allocated()=0
01705     }
01706     this->Base::disconnect(); // clear the handle
01707     return *this;
01708 }
01709 
01713 //------------------------------------------------------------------------------
01748 
01766 void assign(size_type n, const T& fillValue) {
01767     SimTK_ERRCHK3(this->isSizeOK(n), "Array_<T>::assign(n,value)",
01768         "Requested size %llu is too big for this array which is limited"
01769         " to %llu elements by its index type %s.",
01770         this->ull(n), ullMaxSize(), indexName());
01771 
01772     SimTK_ERRCHK2(isOwner() || n==size(), "Array_<T>::assign(n,value)",
01773         "Requested size %llu is not allowed because this is a non-owner"
01774         " array of fixed size %llu.", this->ull(n), this->ull(size()));
01775 
01776     if (!isOwner())
01777         this->Base::fill(fillValue);
01778     else {
01779         clear(); // all elements destructed; allocation unchanged
01780         reallocateIfAdvisable(n); // change size if too small or too big
01781         fillConstruct(data(), cdata()+n, fillValue);
01782         setSize(n);
01783     }
01784 }
01785 
01800 void fill(const T& fillValue) {this->Base::fill(fillValue);}
01801 
01802 
01824 template <class T2>
01825 void assign(const T2* first, const T2* last1) {
01826     const char* methodName = "Array_<T>::assign(T2* first, T2* last1)";
01827     SimTK_ERRCHK((first&&last1)||(first==last1), methodName, 
01828         "Pointers must be non-null unless they are both null.");
01829     SimTK_ERRCHK(!this->overlapsWithData(first,last1), methodName,
01830         "Source range can't overlap the current array contents.");
01831     // Pointers are random access iterators.
01832     assignIteratorDispatch(first,last1,std::random_access_iterator_tag(),
01833                            methodName);
01834 }
01835 
01836 
01872 template <class Iter>
01873 void assign(const Iter& first, const Iter& last1) {
01874     assignDispatch(first,last1,typename IsIntegralType<Iter>::Result(),
01875                    "Array_<T>::assign(Iter first, Iter last1)");
01876 }
01877 
01883 Array_& operator=(const Array_& src) {
01884     if (this != &src)
01885         assignIteratorDispatch(src.begin(), src.end(), 
01886                                std::random_access_iterator_tag(),
01887                                "Array_<T>::operator=(Array_<T>)");
01888     return *this;
01889 }
01890 
01896 template <class T2, class X2>
01897 Array_& operator=(const Array_<T2,X2>& src) {
01898     assignIteratorDispatch(src.begin(), src.end(), 
01899                            std::random_access_iterator_tag(),
01900                            "Array_<T>::operator=(Array_<T2,X2>)");
01901     return *this;
01902 }
01903 
01904 
01909 template <class T2, class A>
01910 Array_& operator=(const std::vector<T2,A>& src) {
01911     assignIteratorDispatch(src.begin(), src.end(), 
01912                            std::random_access_iterator_tag(),
01913                            "Array_<T>::operator=(std::vector)");
01914     return *this;
01915 }
01916 
01923 void swap(Array_& other) {
01924     T* const pTmp=data(); setData(other.data()); other.setData(pTmp);
01925     size_type nTmp=size(); setSize(other.size()); other.setSize(nTmp);
01926     nTmp=allocated(); setAllocated(other.allocated()); other.setAllocated(nTmp);
01927 }
01928 
01934 Array_& adoptData(T* newData, size_type dataSize, 
01935                   size_type dataCapacity) 
01936 {
01937     SimTK_SIZECHECK(dataCapacity, max_size(), "Array_<T>::adoptData()");
01938     SimTK_ERRCHK2(dataSize <= dataCapacity, "Array_<T>::adoptData()", 
01939         "Specified data size %llu was greater than the specified data"
01940         " capacity of %llu.", this->ull(dataSize), this->ull(dataCapacity));
01941     SimTK_ERRCHK(newData || dataCapacity==0, "Array_<T>::adoptData()",
01942         "A null data pointer is allowed only if the size and capacity are"
01943         " specified as zero.");
01944     SimTK_ERRCHK(!this->overlapsWithData(newData, newData+dataSize), 
01945         "Array_<T>::adoptData()",
01946         "The new data can't overlap with the old data.");
01947 
01948     deallocate();
01949     setData(newData);
01950     setSize(dataSize);
01951     setAllocated(dataCapacity);
01952     return *this;
01953 }
01956 Array_& adoptData(T* newData, size_type dataSize) 
01957 {   return adoptData(newData, dataSize, dataSize); }
01958 
01959 
01973 Array_& shareData(T* newData, size_type dataSize) {
01974     SimTK_SIZECHECK(dataSize, max_size(), "Array_<T>::shareData()");
01975     SimTK_ERRCHK(newData || dataSize==0, "Array_<T>::shareData()",
01976         "A null data pointer is allowed only if the size is zero.");
01977     SimTK_ERRCHK(!this->overlapsWithData(newData, newData+dataSize), 
01978         "Array_<T>::shareData()",
01979         "The new data can't overlap with the old data.");
01980 
01981     deallocate();
01982     setData(newData);
01983     setSize(dataSize);
01984     setAllocated(0); // indicates shared data
01985     return *this;
01986 }
01987 
01990 Array_& shareData(T* first, const T* last1) {
01991     SimTK_ERRCHK3(this->isSizeOK(last1-first), "Array_<T>::shareData(first,last1)",
01992         "Requested size %llu is too big for this array which is limited"
01993         " to %llu elements by its index type %s.",
01994         this->ull(last1-first), ullMaxSize(), indexName());
01995     return shareData(first, size_type(last1-first));
01996 }
01997 
02001 //------------------------------------------------------------------------------
02007 
02008 // Note: these have to be explicitly forwarded to the base class methods
02009 // in order to keep gcc from complaining. Note that the "this->" is 
02010 // apparently necessary in order to permit delayed definition of templatized 
02011 // methods.
02012 
02014 size_type size() const {return this->CBase::size();}
02016 size_type max_size() const {return this->CBase::max_size();}
02019 bool empty() const {return this->CBase::empty();}
02024 size_type capacity() const {return this->CBase::capacity();}
02025 
02030 void resize(size_type n) {
02031     if (n == size()) return;
02032 
02033     SimTK_ERRCHK2(isOwner(), "Array_<T>::resize(n)",
02034         "Requested size change to %llu is not allowed because this is a"
02035         " non-owner array of fixed size %llu.", this->ull(n), this->ull(size()));
02036 
02037     if (n < size()) {
02038         erase(data()+n, cend());
02039         return;
02040     }
02041     // n > size()
02042     reserve(n);
02043     defaultConstruct(data()+size(), cdata()+n); // data() has changed
02044     setSize(n);
02045 }
02046 
02051 void resize(size_type n, const T& initVal) {
02052     if (n == size()) return;
02053 
02054     SimTK_ERRCHK2(isOwner(), "Array_<T>::resize(n,value)",
02055         "Requested size change to %llu is not allowed because this is a"
02056         " non-owner array of fixed size %llu.", this->ull(n), this->ull(size()));
02057 
02058     if (n < size()) {
02059         erase(data()+n, cend());
02060         return;
02061     }
02062     // n > size()
02063     reserve(n);
02064     fillConstruct(data()+size(), cdata()+n, initVal);
02065     setSize(n);
02066 }
02067 
02074 void reserve(size_type n) {
02075     if (capacity() >= n)
02076         return;
02077 
02078     SimTK_ERRCHK2(isOwner(), "Array_<T>::reserve()",
02079         "Requested capacity change to %llu is not allowed because this is a"
02080         " non-owner array of fixed size %llu.", this->ull(n), this->ull(size()));
02081 
02082     T* newData = allocN(n); // no construction yet
02083     copyConstructThenDestructSource(newData, newData+size(), data());
02084     freeN(data());
02085     setData(newData);
02086     setAllocated(n);
02087 }
02088 
02109 void shrink_to_fit() {
02110     // Allow 25% slop, but note that if size()==0 this will always reallocate
02111     // unless capacity is already zero.
02112     if (capacity() - size()/4 <= size()) // avoid overflow if size() near max
02113         return;
02114     T* newData = allocN(size());
02115     copyConstructThenDestructSource(newData, newData+size(), data());
02116     deallocateNoDestruct(); // data()=0, allocated()=0, size() unchanged
02117     setData(newData);
02118     setAllocated(size());
02119 }
02120 
02124 size_type allocated() const {return this->CBase::allocated();}
02130 bool isOwner() const {return this->CBase::isOwner();}
02134 //------------------------------------------------------------------------------
02143 
02148 const T* cbegin() const {return this->CBase::cbegin();}
02150 const T* begin() const {return this->CBase::cbegin();}
02155 T* begin() {return this->Base::begin();}
02156 
02161 const T* cend() const {return this->CBase::cend();}
02163 const T* end() const {return this->CBase::cend();}
02168 T* end() {return this->Base::end();}
02169 
02172 const_reverse_iterator crbegin() const {return this->CBase::crbegin();}
02174 const_reverse_iterator rbegin() const {return this->CBase::crbegin();} 
02177 reverse_iterator rbegin() {return this->Base::rbegin();}
02178 
02182 const_reverse_iterator crend() const {return this->CBase::crend();}
02184 const_reverse_iterator rend() const {return this->CBase::crend();}
02188 reverse_iterator rend() {return this->Base::rend();}
02189 
02196 const T* cdata() const {return this->CBase::cdata();}
02199 const T* data() const {return this->CBase::cdata();}
02203 T* data() {return this->Base::data();}
02211 
02218 const T& operator[](index_type i) const {return this->CBase::operator[](i);}
02219 
02227 T& operator[](index_type i) {return this->Base::operator[](i);}
02228 
02233 const T& at(index_type i) const {return this->CBase::at(i);}
02234 
02239 T& at(index_type i) {return const_cast<T&>(this->Base::at(i));}
02240 
02243 const T& getElt(index_type i) const {return this->CBase::getElt(i);}
02246 T& updElt(index_type i) {return this->Base::updElt(i);}
02247 
02253 const T& front() const {return this->CBase::front();} 
02254 
02260 T& front() {return const_cast<T&>(this->Base::front());}
02261 
02267 const T& back() const {return this->CBase::back();}
02268 
02274 T& back() {return const_cast<T&>(this->Base::back());}
02275 
02278 ArrayViewConst_<T,X> operator()(index_type index, size_type length) const
02279 {   return CBase::operator()(index,length); }
02282 ArrayViewConst_<T,X> getSubArray(index_type index, size_type length) const
02283 {   return CBase::getSubArray(index,length); }
02284 
02287 ArrayView_<T,X> operator()(index_type index, size_type length)
02288 {   return Base::operator()(index,length); }
02291 ArrayView_<T,X> updSubArray(index_type index, size_type length)
02292 {   return Base::updSubArray(index,length); }
02296 //------------------------------------------------------------------------------
02302 
02329 void push_back(const T& value) {
02330     if (pallocated() == psize())
02331         growAtEnd(1,"Array_<T>::push_back(value)");
02332     copyConstruct(end(), value);
02333     incrSize();
02334 }
02335 
02349 void push_back() {
02350     if (pallocated() == psize())
02351         growAtEnd(1,"Array_<T>::push_back()");
02352     defaultConstruct(end());
02353     incrSize();
02354 }
02355 
02371 T* raw_push_back() {
02372     if (pallocated() == psize())
02373         growAtEnd(1,"Array_<T>::raw_push_back()");
02374     T* const p = end();
02375     incrSize();
02376     return p;
02377 }
02378 
02381 void pop_back() {
02382     SimTK_ERRCHK(!empty(), "Array_<T>::pop_back()", "Array was empty.");
02383     destruct(&back());
02384     decrSize();
02385 }
02386 
02404 T* erase(T* first, const T* last1) {
02405     SimTK_ERRCHK(begin() <= first && first <= last1 && last1 <= end(),
02406     "Array<T>::erase(first,last1)", "Pointers out of range or out of order.");
02407 
02408     const size_type nErased = size_type(last1-first);
02409     SimTK_ERRCHK(isOwner() || nErased==0, "Array<T>::erase(first,last1)",
02410         "No elements can be erased from a non-owner array.");
02411 
02412     if (nErased) {
02413         destruct(first, last1); // Destruct the elements we're erasing.
02414         moveElementsDown(first+nErased, nErased); // Compress followers into the gap.
02415         setSize(size()-nErased);
02416     }
02417     return first;
02418 }
02419 
02439 T* erase(T* p) {
02440     SimTK_ERRCHK(begin() <= p && p < end(),
02441         "Array<T>::erase(p)", "Pointer must point to a valid element.");
02442     SimTK_ERRCHK(isOwner(), "Array<T>::erase(p)",
02443         "No elements can be erased from a non-owner array.");
02444 
02445     destruct(p);              // Destruct the element we're erasing.
02446     moveElementsDown(p+1, 1); // Compress followers into the gap.
02447     decrSize();
02448     return p;
02449 }
02450 
02451 
02472 T* eraseFast(T* p) {
02473     SimTK_ERRCHK(begin() <= p && p < end(),
02474         "Array<T>::eraseFast(p)", "Pointer must point to a valid element.");
02475     SimTK_ERRCHK(isOwner(), "Array<T>::eraseFast(p)",
02476         "No elements can be erased from a non-owner array.");
02477 
02478     destruct(p);
02479     if (p+1 != end()) 
02480         moveOneElement(p, &back());
02481     decrSize();
02482     return p;
02483 }
02484 
02492 void clear() {
02493     SimTK_ERRCHK(isOwner() || empty(), "Array_<T>::clear()", 
02494         "clear() is not allowed for a non-owner array.");
02495     destruct(begin(), end());
02496     setSize(0);
02497 }
02498 
02499 
02526 T* insert(T* p, size_type n, const T& value) {
02527     T* const gap = insertGapAt(p, n, "Array<T>::insert(p,n,value)");
02528     // Copy construct into the inserted elements and note the size change.
02529     fillConstruct(gap, gap+n, value);
02530     setSize(size()+n);
02531     return gap;
02532 }
02533 
02538 T* insert(T* p, const T& value)  {
02539     T* const gap = insertGapAt(p, 1, "Array<T>::insert(p,value)");
02540     // Copy construct into the inserted element and note the size change.
02541     copyConstruct(gap, value);
02542     incrSize();
02543     return gap;
02544 }
02545 
02575 template <class T2>
02576 T* insert(T* p, const T2* first, const T2* last1) {
02577     const char* methodName = "Array_<T>::insert(T* p, T2* first, T2* last1)";
02578     SimTK_ERRCHK((first&&last1) || (first==last1), methodName, 
02579         "One of first or last1 was null; either both or neither must be null.");
02580     SimTK_ERRCHK(!this->overlapsWithData(first,last1), methodName,
02581         "Source range can't overlap with the current array contents.");
02582     // Pointers are random access iterators.
02583     return insertIteratorDispatch(p, first, last1,
02584                                   std::random_access_iterator_tag(),
02585                                   methodName);
02586 }
02587 
02590 template <class Iter>
02591 T* insert(T* p, const Iter& first, const Iter& last1) {
02592     return insertDispatch(p, first, last1,
02593                           typename IsIntegralType<Iter>::Result(),
02594                           "Array_<T>::insert(T* p, Iter first, Iter last1)");
02595 }
02600 //------------------------------------------------------------------------------
02601                                   private:
02602 //------------------------------------------------------------------------------
02603 
02604 
02605 // This method is used when we have already decided we need to make room for 
02606 // some new elements by reallocation, by creating a gap somewhere within the
02607 // existing data. We'll issue an error message if this would violate the  
02608 // max_size restriction (we can afford to do that even in a Release build since
02609 // we don't expect to grow very often). Otherwise we'll allocate some more space
02610 // and copy construct the existing elements into the new space, leaving a gap 
02611 // where indicated. Note that this method does not change the current size but
02612 // does change the capacity.
02613 //
02614 // The gapPos must point within the existing data with null OK if the array
02615 // itself is null, and end() being OK any time although you should use the
02616 // more specialized growAtEnd() method if you know that's what's happening.
02617 //
02618 // Don't call this with a gapSz of zero.
02619 T* growWithGap(T* gapPos, size_type gapSz, const char* methodName) {
02620     assert(gapSz > 0); // <= 0 is a bug, not a user error
02621 
02622     // Note that gapPos may be null if begin() and end() are also.
02623     SimTK_ERRCHK(begin() <= gapPos && gapPos <= end(), methodName, 
02624         "Given insertion point is not valid for this array.");
02625 
02626     // Get some new space of a reasonable size.
02627     setAllocated(calcNewCapacityForGrowthBy(gapSz, methodName));
02628     T* newData   = allocN(allocated());
02629 
02630     // How many elements will be before the gap?
02631     const size_type nBefore = (size_type)(gapPos-begin());
02632 
02633     // Locate the gap in the new space allocation.
02634     T* newGap    = newData + nBefore;
02635     T* newGapEnd = newGap  + gapSz; // one past the last element in the gap
02636 
02637     // Copy elements before insertion point; destruct source as we go.
02638     copyConstructThenDestructSource(newData,   newGap,        data());
02639     // Copy/destruct elements at and after insertion pt; leave gapSz gap.
02640     copyConstructThenDestructSource(newGapEnd, newData+size(), gapPos);
02641 
02642     // Throw away the old data and switch to the new.
02643     freeN(data()); setData(newData);
02644     return newGap;
02645 }
02646 
02647 // Same as growWithGap(end(), n, methodName); see above.
02648 void growAtEnd(size_type n, const char* methodName) {
02649     assert(n > 0); // <= 0 is a bug, not a user error
02650     // Get some new space of a reasonable size.
02651     setAllocated(calcNewCapacityForGrowthBy(n, methodName));
02652     T* newData   = allocN(allocated());
02653     // Copy all the elements; destruct source as we go.
02654     copyConstructThenDestructSource(newData, newData+size(), data());
02655     // Throw away the old data and switch to the new.
02656     freeN(data()); setData(newData);
02657 }
02658 
02659 // This method determines how much we should increase the array's capacity
02660 // when asked to insert n elements, due to an insertion or push_back. We will
02661 // generally allocate more new space than requested, in anticipation of
02662 // further insertions. This has to be based on the current size so that only
02663 // log(n) reallocations are performed to insert n elements one at a time. Our
02664 // policy here is to at least double the capacity unless that would exceed 
02665 // max_size(). There is also a minimum amount of allocation we'll do if the 
02666 // current size is zero or very small. 
02667 size_type calcNewCapacityForGrowthBy(size_type n, const char* methodName) const {
02668     SimTK_ERRCHK3_ALWAYS(isGrowthOK(n), methodName,
02669         "Can't grow this Array by %llu element(s) because it would"
02670         " then exceed the max_size of %llu set by its index type %s.",
02671         (unsigned long long)n, ullMaxSize(), indexName());
02672 
02673     // At this point we know that capacity()+n <= max_size().
02674     const size_type mustHave = capacity() + n;
02675 
02676     // Be careful not to overflow size_type as you could if you 
02677     // double capacity() rather than halving max_size().
02678     const size_type wantToHave = capacity() <= max_size()/2 
02679                                     ? 2*capacity() 
02680                                     : max_size();
02681 
02682     const size_type newCapacity = std::max(std::max(mustHave,wantToHave),
02683                                            minAlloc());
02684     return newCapacity;
02685 }
02686 
02687 // Insert an unconstructed gap of size n beginning at position p. The return
02688 // value is a pointer to the first element in the gap. It will be p if no
02689 // reallocation occurred, otherwise it will be pointing into the new data.
02690 // On return size() will be unchanged although allocated() may be bigger.
02691 T* insertGapAt(T* p, size_type n, const char* methodName) {
02692     // Note that p may be null if begin() and end() are also.
02693     SimTK_ERRCHK(begin() <= p && p <= end(), methodName, 
02694         "Given insertion point is not valid for this Array.");
02695 
02696     if (n==0) return p; // nothing to do
02697 
02698     SimTK_ERRCHK_ALWAYS(isOwner(), methodName,
02699         "No elements can be inserted into a non-owner array.");
02700 
02701     // Determine the number of elements before the insertion point and
02702     // the number at or afterwards (those must be moved up by one slot).
02703     const size_type before = (size_type)(p-begin()), after = (size_type)(end()-p);
02704 
02705     // Grow the container if necessary. Note that if we have to grow we
02706     // can create the gap at the same time we copy the old elements over
02707     // to the new space.
02708     if (capacity() >= size()+n) {
02709         moveElementsUp(p, n); // leave a gap at p
02710     } else { // need to grow
02711         setAllocated(calcNewCapacityForGrowthBy(n, methodName));
02712         T* newdata = allocN(allocated());
02713         // Copy the elements before the insertion point, and destroy source.
02714         copyConstructThenDestructSource(newdata, newdata+before, data());
02715         // Copy the elements at and after the insertion point, leaving a gap
02716         // of n elements.
02717         copyConstructThenDestructSource(newdata+before+n,
02718                                         newdata+before+n+after,
02719                                         p); // i.e., pData+before
02720         p = newdata + before; // points into newdata now
02721         freeN(data());
02722         setData(newdata);
02723     }
02724 
02725     return p;
02726 }
02727 
02728 //------------------------------------------------------------------------------
02729 //                           CTOR DISPATCH
02730 // This is the constructor implementation for when the class that matches
02731 // the alleged InputIterator type turns out to be one of the integral types
02732 // in which case this should be the ctor(n, initValue) constructor.
02733 template <class IntegralType> void
02734 ctorDispatch(IntegralType n, IntegralType v, TrueType isIntegralType) {
02735     new(this) Array_(size_type(n), value_type(v));
02736 }
02737 
02738 // This is the constructor implementation for when the class that matches
02739 // the alleged InputIterator type is NOT an integral type and may very well
02740 // be an iterator. In that case we split into iterators for which we can
02741 // determine the number of elements in advance (forward, bidirectional,
02742 // random access) and input iterators, for which we can't. Note: iterator
02743 // types are arranged hierarchically random->bi->forward->input with each
02744 // deriving from the one on its right, so the forward iterator tag also
02745 // matches bi and random.
02746 template <class InputIterator> void
02747 ctorDispatch(const InputIterator& first, const InputIterator& last1, 
02748              FalseType isIntegralType) 
02749 {   ctorIteratorDispatch(first, last1, 
02750         typename std::iterator_traits<InputIterator>::iterator_category()); }
02751 
02752 // This is the slow generic ctor implementation for any iterator that can't
02753 // make it up to forward_iterator capability (that is, an input_iterator).
02754 // The issue here is that we can't advance the iterator to count the number
02755 // of elements before allocating because input_iterators are consumed when
02756 // reference so we can't go back to look. That means we may have to reallocate
02757 // memory log n times as we "push back" these elements onto the array.
02758 template <class InputIterator> void
02759 ctorIteratorDispatch(const InputIterator& first, const InputIterator& last1, 
02760                      std::input_iterator_tag) 
02761 {
02762     InputIterator src = first;
02763     while (src != last1) {
02764         // We can afford to check this always since we are probably doing I/O.
02765         // Throwing an exception in a constructor is tricky, though -- this
02766         // won't go through the Array_ destructor although it will call the
02767         // Base (ArrayView_) destructor. Since we have already allocated
02768         // some space, we must call deallocate() manually.
02769         if (size() == max_size()) {
02770             deallocate();
02771             SimTK_ERRCHK2_ALWAYS(!"too many elements",
02772                 "Array_::ctor(InputIterator first, InputIterator last1)",
02773                 "There were still source elements available when the array"
02774                 " reached its maximum size of %llu as determined by its index"
02775                 " type %s.", ullMaxSize(), indexName());
02776         }
02777         push_back(*src++);
02778     }
02779 }
02780 
02781 // This is the faster constructor implementation for iterator types for which
02782 // we can calculate the number of elements in advance. This will be optimal
02783 // for a random access iterator since we can count in constant time, but for
02784 // forward or bidirectional we'll have to advance n times to count and then
02785 // go back again to do the copy constructions.
02786 template <class ForwardIterator> void
02787 ctorIteratorDispatch(const ForwardIterator& first, const ForwardIterator& last1, 
02788                      std::forward_iterator_tag) 
02789 {
02790     typedef typename std::iterator_traits<ForwardIterator>::difference_type
02791         difference_type;
02792     // iterDistance() is constant time for random access iterators, but 
02793     // O(last1-first) for forward and bidirectional since it has to increment 
02794     // to count how far apart they are.
02795     const difference_type nInput = this->iterDistance(first,last1);
02796 
02797     SimTK_ERRCHK(nInput >= 0, 
02798         "Array_(ForwardIterator first, ForwardIterator last1)", 
02799         "Iterators were out of order.");
02800 
02801     SimTK_ERRCHK3(this->isSizeOK(nInput), 
02802         "Array_(ForwardIterator first, ForwardIterator last1)",
02803         "Source has %llu elements but this array is limited to %llu"
02804         " elements by its index type %s.",
02805         this->ull(nInput), ullMaxSize(), indexName());
02806 
02807     const size_type n = size_type(nInput);
02808     setSize(n);
02809     allocateNoConstruct(n);
02810     copyConstruct(data(), data()+n, first);
02811 }
02812 
02813 //------------------------------------------------------------------------------
02814 //                           INSERT DISPATCH
02815 // This is the insert() implementation for when the class that matches
02816 // the alleged InputIterator type turns out to be one of the integral types
02817 // in which case this should be the insert(p, n, initValue) constructor.
02818 template <class IntegralType> 
02819 T* insertDispatch(T* p, IntegralType n, IntegralType v, 
02820                   TrueType isIntegralType, const char*) 
02821 {   return insert(p, size_type(n), value_type(v)); }
02822 
02823 // This is the insert() implementation for when the class that matches
02824 // the alleged InputIterator type is NOT an integral type and may very well
02825 // be an iterator. See ctorDispatch() above for more information.
02826 template <class InputIterator> 
02827 T* insertDispatch(T* p, const InputIterator& first, const InputIterator& last1, 
02828                   FalseType isIntegralType, const char* methodName) 
02829 {   return insertIteratorDispatch(p, first, last1, 
02830         typename std::iterator_traits<InputIterator>::iterator_category(),
02831         methodName); }
02832 
02833 // This is the slow generic insert implementation for any iterator that can't
02834 // make it up to forward_iterator capability (that is, an input_iterator).
02835 // See ctorIteratorDispatch() above for more information.
02836 template <class InputIterator> 
02837 T* insertIteratorDispatch(T* p, InputIterator first, InputIterator last1, 
02838                           std::input_iterator_tag, const char* methodName) 
02839 {
02840     size_type nInserted = 0;
02841     while (first != last1) {
02842         // We can afford to check this always since we are probably doing I/O.
02843         SimTK_ERRCHK2_ALWAYS(size() < max_size(), methodName,
02844             "There were still source elements available when the array"
02845             " reached its maximum size of %llu as determined by its index"
02846             " type %s.", ullMaxSize(), indexName());
02847         p = insert(p, *first++);  // p may now point to reallocated memory
02848         ++p; ++nInserted;
02849     }
02850     // p now points just after the last inserted element; subtract the
02851     // number inserted to get a pointer to the first inserted element.
02852     return p-nInserted;
02853 }
02854 
02855 // This is the faster constructor implementation for iterator types for which
02856 // we can calculate the number of elements in advance. This will be optimal
02857 // for a random access iterator since we can count in constant time, but for
02858 // forward or bidirectional we'll have to advance n times to count and then
02859 // go back again to do the copy constructions.
02860 template <class ForwardIterator>
02861 T* insertIteratorDispatch(T* p, const ForwardIterator& first, 
02862                                 const ForwardIterator& last1,
02863                                 std::forward_iterator_tag,
02864                                 const char* methodName) 
02865 {
02866     typedef typename std::iterator_traits<ForwardIterator>::difference_type
02867         difference_type;
02868     // iterDistance() is constant time for random access iterators, but 
02869     // O(last1-first) for forward and bidirectional since it has to increment 
02870     // to count how far apart they are.
02871     const difference_type nInput = this->iterDistance(first,last1);
02872 
02873     SimTK_ERRCHK(nInput >= 0, methodName, "Iterators were out of order.");
02874 
02875     SimTK_ERRCHK3(isGrowthOK(nInput), methodName,
02876         "Source has %llu elements which would make this array exceed the %llu"
02877         " elements allowed by its index type %s.",
02878         this->ull(nInput), ullMaxSize(), indexName());
02879 
02880     const size_type n = size_type(nInput);
02881     p = insertGapAt(p, n, methodName);
02882     copyConstruct(p, p+n, first);
02883     setSize(size()+n);
02884     return p;
02885 }
02886 
02887 //------------------------------------------------------------------------------
02888 //                           ASSIGN DISPATCH
02889 // This is the assign() implementation for when the class that matches
02890 // the alleged InputIterator type turns out to be one of the integral types
02891 // in which case this should be the assign(n, initValue) constructor.
02892 template <class IntegralType>
02893 void assignDispatch(IntegralType n, IntegralType v, TrueType isIntegralType,
02894                     const char* methodName) 
02895 {   assign(size_type(n), value_type(v)); }
02896 
02897 // This is the assign() implementation for when the class that matches
02898 // the alleged InputIterator type is NOT an integral type and may very well
02899 // be an iterator. See ctorDispatch() above for more information.
02900 template <class InputIterator> 
02901 void assignDispatch(const InputIterator& first, const InputIterator& last1, 
02902                     FalseType isIntegralType, const char* methodName) 
02903 {   assignIteratorDispatch(first, last1, 
02904         typename std::iterator_traits<InputIterator>::iterator_category(),
02905         methodName); }
02906 
02907 // This is the slow generic implementation for a plain input_iterator
02908 // (i.e., not a forward, bidirectional, or random access iterator). These
02909 // have the unfortunate property that we can't count the elements in advance.
02910 template <class InputIterator>
02911 void assignIteratorDispatch(const InputIterator& first, 
02912                             const InputIterator& last1, 
02913                             std::input_iterator_tag, 
02914                             const char* methodName) 
02915 {
02916     // TODO: should probably allow this and just blow up when the size()+1st
02917     // element is seen.
02918     SimTK_ERRCHK_ALWAYS(isOwner(), methodName,
02919         "Assignment to a non-owner array can only be done from a source"
02920         " designated with forward iterators or pointers because we"
02921         " must be able to verify that the source and destination sizes"
02922         " are the same.");
02923 
02924     clear(); // TODO: change space allocation here?
02925     InputIterator src = first;
02926     while (src != last1) {
02927         // We can afford to check this always since we are probably doing I/O.
02928         SimTK_ERRCHK2_ALWAYS(size() < max_size(), methodName,
02929             "There were still source elements available when the array"
02930             " reached its maximum size of %llu as determined by its index"
02931             " type %s.", ullMaxSize(), indexName());
02932 
02933         push_back(*src++);
02934     }
02935 }
02936 
02937 // This is the faster implementation that works for forward, bidirectional,
02938 // and random access iterators including ordinary pointers. We can check here that the 
02939 // iterators are in the right order, and that the source is not too big to
02940 // fit in this array. Null pointer checks should be done prior to calling,
02941 // however, since iterators in general aren't pointers.
02942 template <class ForwardIterator>
02943 void assignIteratorDispatch(const ForwardIterator& first, 
02944                             const ForwardIterator& last1,
02945                             std::forward_iterator_tag, 
02946                             const char* methodName) 
02947 {
02948     typedef typename std::iterator_traits<ForwardIterator>::difference_type
02949         IterDiffType;
02950     // iterDistance() is constant time for random access iterators, but 
02951     // O(last1-first) for forward and bidirectional since it has to increment 
02952     // to count how far apart they are.
02953     const IterDiffType nInput = this->iterDistance(first,last1);
02954 
02955     SimTK_ERRCHK(nInput >= 0, methodName, "Iterators were out of order.");
02956 
02957     SimTK_ERRCHK3(this->isSizeOK(nInput), methodName,
02958         "Source has %llu elements but this Array is limited to %llu"
02959         " elements by its index type %s.",
02960         this->ull(nInput), ullMaxSize(), indexName());
02961 
02962     const size_type n = size_type(nInput);
02963     if (isOwner()) {
02964         // This is an owner Array; assignment is considered deallocation
02965         // followed by copy construction.
02966 
02967         clear(); // all elements destructed; allocation unchanged
02968         reallocateIfAdvisable(n); // change allocation if too small or too big
02969         copyConstruct(data(), cdata()+n, first);
02970         setSize(n);
02971     } else {
02972         // This is a non-owner Array. Assignment can occur only if the
02973         // source is the same size as the array, and the semantics are of
02974         // repeated assignment using T::operator=() not destruction followed
02975         // by copy construction.
02976         SimTK_ERRCHK2(n == size(), methodName,
02977             "Source has %llu elements which does not match the size %llu"
02978             " of the non-owner array it is being assigned into.",
02979             this->ull(n), ullSize());
02980 
02981         T* p = begin();
02982         ForwardIterator src = first;
02983         while (src != last1)
02984             *p++ = *src++; // call T's assignment operator
02985     }
02986 }
02987 
02988 // We are going to put a total of n elements into the Array (probably
02989 // because of an assignment or resize) and we want the space allocation
02990 // to be reasonable. That means of course that the allocation must be 
02991 // *at least* n, but we also don't want it to be too big. Our policy
02992 // here is that if it is currently less than twice what we need we
02993 // won't reallocate, otherwise we'll shrink the space. When changing
02994 // the size to zero or something very small we'll treat the Array as
02995 // though its current size is minAlloc, meaning we won't reallocate
02996 // if the existing space is less than twice minAlloc.
02997 // nAllocated will be set appropriately; size() is not touched here.
02998 // No constructors or destructors are called.
02999 void reallocateIfAdvisable(size_type n) {
03000     if (allocated() < n || allocated()/2 > std::max(minAlloc(), n)) 
03001         reallocateNoDestructOrConstruct(n);
03002 }
03003 
03004 
03005 void allocateNoConstruct(size_type n) 
03006 {   setData(allocN(n)); setAllocated(n); } // size() left unchanged
03007 void deallocateNoDestruct() 
03008 {   freeN(data()); setData(0); setAllocated(0); } // size() left unchanged
03009 void reallocateNoDestructOrConstruct(size_type n)
03010 {   deallocateNoDestruct(); allocateNoConstruct(n); }
03011 
03012 // This sets the smallest allocation we'll do when growing.
03013 size_type minAlloc() const 
03014 {   return std::min(max_size(), size_type(4)); }
03015 
03016 // Allocate without construction. Returns a null pointer if asked
03017 // to allocate 0 elements. In Debug mode we'll fill memory with 
03018 // all 1's as a bug catcher.
03019 static T* allocN(size_type n) {
03020     if (n==0) return 0;
03021     unsigned char* newdata = new unsigned char[n * sizeof(T)];
03022     #ifndef NDEBUG
03023         unsigned char* b=newdata; 
03024         const unsigned char* e=newdata+(n*sizeof(T));
03025         while (b != e) *b++ = 0xff;
03026     #endif
03027     return reinterpret_cast<T*>(newdata);
03028 }
03029 
03030 // Free memory without calling T's destructor. Nothing happens if passed
03031 // a null pointer.
03032 static void freeN(T* p) {
03033     delete[] reinterpret_cast<char*>(p);
03034 }
03035 
03036 // default construct one element
03037 static void defaultConstruct(T* p) {new(p) T();}
03038 // default construct range [b,e)
03039 static void defaultConstruct(T* b, const T* e) 
03040 {   while (b!=e) new(b++) T(); }
03041 
03042 // copy construct range [b,e) with repeats of a given value
03043 static void fillConstruct(T* b, const T* e, const T& v)
03044 {   while(b!=e) new(b++) T(v); }
03045 
03046 // copy construct one element from a given value
03047 static void copyConstruct(T* p, const T& v) {new(p) T(v);}
03048 // copy construct range [b,e) from sequence of source values
03049 static void copyConstruct(T* b, const T* e, T* src)
03050 {   while(b!=e) new(b++) T(*src++); }
03051 // Templatized copy construct will work if the source elements are
03052 // assignment compatible with the destination elements.
03053 template <class InputIterator>
03054 static void copyConstruct(T* b, const T* e, InputIterator src)
03055 {   while(b!=e) new(b++) T(*src++); }
03056 
03057 // Copy construct range [b,e] from sequence of source values and
03058 // destruct the source after it is copied. It's better to alternate
03059 // copying and destructing than to do this in two passes since we
03060 // will already have touched the memory.
03061 static void copyConstructThenDestructSource(T* b, const T* e, T* src)
03062 {   while(b!=e) {new(b++) T(*src); src++->~T();} }
03063 
03064 // We have an element at from that we would like to move into the currently-
03065 // unconstructed slot at to. Both from and to are expected to be pointing to
03066 // elements within the currently allocated space. From's slot will be left
03067 // unconstructed.
03068 void moveOneElement(T* to, T* from) {
03069     assert(data() <= to   && to   < data()+allocated());
03070     assert(data() <= from && from < data()+allocated());
03071     copyConstruct(to, *from); 
03072     destruct(from);
03073 }
03074 
03075 
03076 // Move elements from p to end() down by n>0 places to fill an unconstructed 
03077 // gap beginning at p-n. Any leftover space at the end will be unconstructed.
03078 void moveElementsDown(T* p, size_type n) {
03079     assert(n > 0);
03080     for (; p != end(); ++p)
03081         moveOneElement(p-n,p);
03082 }
03083 
03084 // Move elements from p to end() up by n>0 places to make an unconstructed gap
03085 // at [p,p+n). Note that this has to be done backwards so that we don't
03086 // write on any elements until after they've been copied.
03087 void moveElementsUp(T* p, size_type n) {
03088     assert(n > 0);
03089     T* src = end(); // points one past source element (begin()-1 not allowed)
03090     while (src != p) {
03091         --src; // now points to source
03092         moveOneElement(src+n, src);;
03093     }
03094 }
03095 
03096 // destruct one element
03097 static void destruct(T* p) {p->~T();}
03098 // destruct range [b,e)
03099 static void destruct(T* b, const T* e)
03100 {   while(b!=e) b++->~T(); }
03101 
03102 // Check that growing this array by n elements wouldn't cause it to exceed
03103 // its allowable maximum size.
03104 template <class S>
03105 bool isGrowthOK(S n) const
03106 {   return this->isSizeOK(ullCapacity() + this->ull(n)); }
03107 
03108 // The following private methods are protected methods in the ArrayView base 
03109 // class, so they should not need repeating here. Howevr, we explicitly 
03110 // forward to the Base methods to avoid gcc errors. The gcc complaint
03111 // is due to their not depending on any template parameters; the "this->"
03112 // apparently fixes that problem.
03113 
03114 // These provide direct access to the data members.
03115 packed_size_type psize()      const {return this->CBase::psize();}
03116 packed_size_type pallocated() const {return this->CBase::pallocated();}
03117 
03118 void setData(const T* p)        {this->CBase::setData(p);}
03119 void setSize(size_type n)       {this->CBase::setSize(n);}
03120 void incrSize()                 {this->CBase::incrSize();}
03121 void decrSize()                 {this->CBase::decrSize();}
03122 void setAllocated(size_type n)  {this->CBase::setAllocated(n);}
03123 // This just cast sizes to unsigned long long so that we can do comparisons
03124 // without getting warnings.
03125 unsigned long long ullSize()     const {return this->CBase::ullSize();}
03126 unsigned long long ullCapacity() const {return this->CBase::ullCapacity();}
03127 unsigned long long ullMaxSize()  const {return this->CBase::ullMaxSize();}
03128 // This is the index type name and is handy for error messages to explain
03129 // why some size was too big.
03130 const char* indexName() const   {return this->CBase::indexName();}
03131 };
03132 
03133 
03134 // This "private" static method is used to implement ArrayView's 
03135 // fillArrayViewFromStream() and Array's readArrayFromStream() namespace-scope
03136 // static methods, which are in turn used to implement ArrayView's and 
03137 // Array's stream extraction operators ">>". This method has to be in the 
03138 // header file so that we don't need to pass streams through the API, but it 
03139 // is not intended for use by users and has no Doxygen presence, unlike 
03140 // fillArrayFromStream() and readArrayFromStream() and (more commonly)
03141 // the extraction operators.
03142 template <class T, class X> static inline 
03143 std::istream& readArrayFromStreamHelper
03144    (std::istream& in, bool isFixedSize, Array_<T,X>& out)
03145 {
03146     // If already failed, bad, or eof, set failed bit and return without 
03147     // touching the Array.
03148     if (!in.good()) {in.setstate(std::ios::failbit); return in;}
03149 
03150     // If the passed-in Array isn't an owner, then we have to treat it as
03151     // a fixed size ArrayView regardless of the setting of the isFixedSize
03152     // argument.
03153     if (!out.isOwner())
03154         isFixedSize = true; // might be overriding the argument here
03155 
03156     // numRequired will be ignored unless isFixedSize==true.
03157     const typename Array_<T,X>::size_type 
03158         numRequired = isFixedSize ? out.size() : 0;
03159 
03160     if (!isFixedSize)
03161         out.clear(); // We're going to replace the entire contents of the Array.
03162 
03163     // Skip initial whitespace. If that results in eof this may be a successful
03164     // read of a 0-length, unbracketed Array. That is OK for either a
03165     // variable-length Array or a fixed-length ArrayView of length zero.
03166     std::ws(in); if (in.fail()) return in;
03167     if (in.eof()) {
03168         if (isFixedSize && numRequired != 0)
03169             in.setstate(std::ios_base::failbit); // zero elements not OK
03170         return in;
03171     }
03172     
03173     // Here the stream is good and the next character is non-white.
03174     assert(in.good());
03175 
03176     // Use this for raw i/o (peeks and gets).
03177     typename       std::iostream::int_type ch;
03178     const typename std::iostream::int_type EOFch = 
03179         std::iostream::traits_type::eof();
03180 
03181     // Now see if the sequence is bare or surrounded by (), [], or {}.
03182     bool lookForCloser = true;
03183     char openBracket, closeBracket;
03184     ch = in.peek(); if (in.fail()) return in;
03185     assert(ch != EOFch); // we already checked above
03186 
03187     openBracket = (char)ch;
03188     if      (openBracket=='(') {in.get(); closeBracket = ')';}
03189     else if (openBracket=='[') {in.get(); closeBracket = ']';}
03190     else if (openBracket=='{') {in.get(); closeBracket = '}';}
03191     else lookForCloser = false;
03192 
03193     // If lookForCloser is true, then closeBracket contains the terminating
03194     // delimiter, otherwise we're not going to quit until eof.
03195 
03196     // Eat whitespace after the opening bracket to see what's next.
03197     if (in.good()) std::ws(in);
03198 
03199     // If we're at eof now it must be because the open bracket was the
03200     // last non-white character in the stream, which is an error.
03201     if (!in.good()) {
03202         if (in.eof()) {
03203             assert(lookForCloser); // or we haven't read anything that could eof
03204             in.setstate(std::ios::failbit);
03205         }
03206         return in;
03207     }
03208 
03209     // istream is good and next character is non-white; ready to read first
03210     // value or terminator.
03211 
03212     // We need to figure out whether the elements are space- or comma-
03213     // separated and then insist on consistency.
03214     bool commaOK = true, commaRequired = false;
03215     bool terminatorSeen = false;
03216     X nextIndex(0);
03217     while (true) {
03218         char c;
03219 
03220         // Here at the top of this loop, we have already successfully read 
03221         // n=nextIndex values of type T. For fixed-size reads, it might be
03222         // the case that n==numRequired already, but we still may need to
03223         // look for a closing bracket before we can declare victory.
03224         // The stream is good() (not at eof) but it might be the case that 
03225         // there is nothing but white space left; we don't know yet because
03226         // if we have satisfied the fixed-size count and are not expecting
03227         // a terminator then we should quit without absorbing the trailing
03228         // white space.
03229         assert(in.good());
03230 
03231         // Look for closing bracket before trying to read value.
03232         if (lookForCloser) {
03233             // Eat white space to find the closing bracket.
03234             std::ws(in); if (!in.good()) break; // eof?
03235             ch = in.peek(); assert(ch != EOFch);
03236             if (!in.good()) break;
03237             c = (char)ch;
03238             if (c == closeBracket) {   
03239                 in.get(); // absorb the closing bracket
03240                 terminatorSeen = true; 
03241                 break; 
03242             }
03243             // next char not a closing bracket; fall through
03244         }
03245 
03246         // We didn't look or didn't find a closing bracket. The istream is good 
03247         // but we might be looking at white space.
03248 
03249         // If we already got all the elements we want, break for final checks.
03250         if (isFixedSize && (nextIndex == numRequired))
03251             break; // that's a full count.
03252 
03253         // Look for comma before value, except the first time.
03254         if (commaOK && nextIndex != 0) {
03255             // Eat white space to find the comma.
03256             std::ws(in); if (!in.good()) break; // eof?
03257             ch = in.peek(); assert(ch != EOFch);
03258             if (!in.good()) break;
03259             c = (char)ch;
03260             if (c == ',') {
03261                 in.get(); // absorb comma
03262                 commaRequired = true; // all commas from now on
03263             } else { // next char not a comma
03264                 if (commaRequired) // bad, e.g.: v1, v2, v3 v4 
03265                 {   in.setstate(std::ios::failbit); break; }
03266                 else commaOK = false; // saw: v1 v2 (no commas now)
03267             }
03268             if (!in.good()) break; // might be eof
03269         }
03270 
03271         // No closing bracket yet; don't have enough elements; skipped comma 
03272         // if any; istream is good; might be looking at white space.
03273         assert(in.good());
03274 
03275         // Now read in an element of type T.
03276         // The extractor T::operator>>() will ignore leading white space.
03277         if (!isFixedSize)
03278             out.push_back(); // grow by one (default consructed)
03279         in >> out[nextIndex]; if (in.fail()) break;
03280         ++nextIndex;
03281 
03282         if (!in.good()) break; // might be eof
03283     }
03284 
03285     // We will get here under a number of circumstances:
03286     //  - the fail bit is set in the istream, or
03287     //  - we reached eof
03288     //  - we saw a closing brace
03289     //  - we got all the elements we wanted (for a fixed-size read)
03290     // Note that it is possible that we consumed everything except some
03291     // trailing white space (meaning we're not technically at eof), but
03292     // for consistency with built-in operator>>()'s we won't try to absorb
03293     // that trailing white space.
03294 
03295     if (!in.fail()) {
03296         if (lookForCloser && !terminatorSeen)
03297             in.setstate(std::ios::failbit); // missing terminator
03298 
03299         if (isFixedSize && nextIndex != numRequired)
03300             in.setstate(std::ios::failbit); // wrong number of values
03301     }
03302 
03303     return in;
03304 }
03305 
03306 
03307 
03308 //------------------------------------------------------------------------------
03309 //                          RELATED GLOBAL OPERATORS
03310 //------------------------------------------------------------------------------
03311 // These are logically part of the Array_<T,X> class but are not actually 
03312 // class members; that is, they are in the SimTK namespace.
03313 
03314 // Some of the serialization methods could have been member functions but 
03315 // then an attempt to explicitly instantiate the whole Array_<T> class for
03316 // some type T would fail if T did not support the requisite I/O operations
03317 // even if those operations were never used. This came up when Chris Bruns was
03318 // trying to wrap Array objects for Python, which requires explicit 
03319 // instantiation.
03320 
03328 
03332 template <class T, class X> inline void
03333 writeUnformatted(std::ostream& o, const Array_<T,X>& v) {
03334     for (X i(0); i < v.size(); ++i) {
03335         if (i != 0) o << " ";
03336         writeUnformatted(o, v[i]);
03337     }
03338 }
03339 
03340 
03344 template <class T, class X> inline void
03345 writeFormatted(std::ostream& o, const Array_<T,X>& v) {
03346     o << '(';
03347     for (X i(0); i < v.size(); ++i) {
03348         if (i != 0) o << ',';
03349         writeFormatted(o, v[i]);
03350     }
03351     o << ')';
03352 }
03353 
03360 template <class T, class X> inline 
03361 std::ostream&
03362 operator<<(std::ostream& o, 
03363            const ArrayViewConst_<T,X>& a) 
03364 {
03365     o << '(';
03366     if (!a.empty()) {
03367         o << a.front();
03368         for (const T* p = a.begin()+1; p != a.end(); ++p)
03369             o << ',' << *p;
03370     }
03371     return o << ')';
03372 } 
03373 
03374 
03378 template <class T, class X> inline bool 
03379 readUnformatted(std::istream& in, Array_<T,X>& v) {
03380     v.clear();
03381     T element;
03382     std::ws(in); // Make sure we're at eof if stream is all whitespace.
03383     while (!in.eof() && readUnformatted(in, element))
03384         v.push_back(element);
03385     return !in.fail(); // eof is expected and ok
03386 }
03387 
03392 template <class T, class X> inline bool 
03393 readUnformatted(std::istream& in, ArrayView_<T,X>& v) {
03394     for (X i(0); i < v.size(); ++i)
03395         if (!readUnformatted(in, v[i])) return false;
03396     return true;
03397 }
03398 
03399 
03405 template <class T, class X> inline bool 
03406 readFormatted(std::istream& in, Array_<T,X>& v) {
03407     return !readArrayFromStream(in,v).fail();
03408 }
03409 
03415 template <class T, class X> inline bool 
03416 readFormatted(std::istream& in, ArrayView_<T,X>& v) {
03417     return !fillArrayViewFromStream(in,v).fail();
03418 }
03419 
03449 template <class T, class X> static inline 
03450 std::istream& readArrayFromStream(std::istream& in, Array_<T,X>& out)
03451 {   return readArrayFromStreamHelper<T,X>(in, false /*variable sizez*/, out); }
03452 
03453 
03454 
03479 template <class T, class X> static inline 
03480 std::istream& fillArrayFromStream(std::istream& in, Array_<T,X>& out)
03481 {   return readArrayFromStreamHelper<T,X>(in, true /*fixed size*/, out); }
03482 
03487 template <class T, class X> static inline 
03488 std::istream& fillArrayViewFromStream(std::istream& in, ArrayView_<T,X>& out)
03489 {   return readArrayFromStreamHelper<T,X>(in, true /*fixed size*/, out); }
03490 
03491 
03492 
03493 
03503 template <class T, class X> inline
03504 std::istream& operator>>(std::istream& in, Array_<T,X>& out) 
03505 {   return readArrayFromStream<T,X>(in, out); }
03506 
03514 template <class T, class X> inline
03515 std::istream& operator>>(std::istream& in, ArrayView_<T,X>& out) 
03516 {   return fillArrayViewFromStream<T,X>(in, out); }
03517 
03527 
03530 template <class T1, class X1, class T2, class X2> inline bool 
03531 operator==(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2) {
03532     // Avoid warnings in size comparison by using common type.
03533     const ptrdiff_t sz1 = a1.end()-a1.begin();
03534     const ptrdiff_t sz2 = a2.end()-a2.begin();
03535     if (sz1 != sz2) return false;
03536     const T1* p1 = a1.begin();
03537     const T2* p2 = a2.begin();
03538     while (p1 != a1.end())
03539         if (!(*p1++ == *p2++)) return false;
03540     return true;
03541 }
03544 template <class T1, class X1, class T2, class X2> inline bool 
03545 operator!=(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2)
03546 {   return !(a1 == a2); }
03547 
03552 template <class T1, class X1, class T2, class X2> inline bool 
03553 operator<(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2) {
03554     const T1* p1 = a1.begin();
03555     const T2* p2 = a2.begin();
03556     while (p1 != a1.end() && p2 != a2.end()) {
03557         if (!(*p1 == *p2))
03558             return *p1 < *p2; // otherwise p1 > p2
03559         ++p1; ++p2;
03560     }
03561     // All elements were equal until one or both arrays ran out of elements.
03562     // a1 is less than a2 only if a1 ran out and a2 didn't.
03563     return p1 == a1.end() && p2 != a2.end();
03564 }
03567 template <class T1, class X1, class T2, class X2> inline bool 
03568 operator>=(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2)
03569 {   return !(a1 < a2); }
03573 template <class T1, class X1, class T2, class X2> inline bool 
03574 operator>(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2)
03575 {   return a2 < a1; }
03578 template <class T1, class X1, class T2, class X2> inline bool 
03579 operator<=(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2)
03580 {   return !(a1 > a2); }
03581 
03585 template <class T1, class X1, class T2, class A2> inline bool 
03586 operator==(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
03587 {   return a1 == ArrayViewConst_<T2,size_t>(v2); }
03588 
03592 template <class T1, class A1, class T2, class X2> inline bool 
03593 operator==(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
03594 {   return a2 == v1; }
03595 
03598 template <class T1, class X1, class T2, class A2> inline bool 
03599 operator!=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
03600 {   return !(a1 == v2); }
03603 template <class T1, class A1, class T2, class X2> inline bool 
03604 operator!=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
03605 {   return !(a2 == v1); }
03606 
03612 template <class T1, class X1, class T2, class A2> inline bool 
03613 operator<(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
03614 {   return a1 < ArrayViewConst_<T2,size_t>(v2); }
03615 
03621 template <class T1, class A1, class T2, class X2> inline bool 
03622 operator<(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
03623 {   return ArrayViewConst_<T1,size_t>(v1) < a2; }
03624 
03627 template <class T1, class X1, class T2, class A2> inline bool 
03628 operator>=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
03629 {   return !(a1 < v2); }
03632 template <class T1, class A1, class T2, class X2> inline bool 
03633 operator>=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
03634 {   return !(v1 < a2); }
03635 
03639 template <class T1, class X1, class T2, class A2> inline bool 
03640 operator>(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
03641 {   return v2 < a1; }
03645 template <class T1, class A1, class T2, class X2> inline bool 
03646 operator>(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
03647 {   return a2 < v1; }
03648 
03651 template <class T1, class X1, class T2, class A2> inline bool 
03652 operator<=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
03653 {   return !(a1 > v2); }
03656 template <class T1, class A1, class T2, class X2> inline bool 
03657 operator<=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
03658 {   return !(v1 > a2); }
03659 
03662 } // namespace SimTK
03663 
03664 namespace std {
03668 template <class T, class X> inline void
03669 swap(SimTK::Array_<T,X>& a1, SimTK::Array_<T,X>& a2) {
03670     a1.swap(a2);
03671 }
03672 
03673 } // namespace std
03674   
03675 #endif // SimTK_SimTKCOMMON_ARRAY_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines