Object-oriented Scientific Computing Library: Version 0.910
uvector_tlate.h
Go to the documentation of this file.
00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006-2012, Andrew W. Steiner
00005   
00006   This file is part of O2scl.
00007   
00008   O2scl is free software; you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation; either version 3 of the License, or
00011   (at your option) any later version.
00012   
00013   O2scl is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017   
00018   You should have received a copy of the GNU General Public License
00019   along with O2scl. If not, see <http://www.gnu.org/licenses/>.
00020 
00021   -------------------------------------------------------------------
00022 */
00023 #ifndef O2SCL_UVECTOR_TLATE_H
00024 #define O2SCL_UVECTOR_TLATE_H
00025 
00026 /** \file uvector_tlate.h
00027     \brief File for definitions of unit-stride vectors
00028 */
00029 
00030 #include <iostream>
00031 #include <cstdlib>
00032 #include <string>
00033 #include <fstream>
00034 #include <sstream>
00035 #include <vector>
00036 
00037 #include <gsl/gsl_vector.h>
00038 
00039 #include <o2scl/err_hnd.h>
00040 #include <o2scl/string_conv.h>
00041 #include <o2scl/array.h>
00042 #include <o2scl/vector.h>
00043 
00044 #ifndef DOXYGENP
00045 namespace o2scl {
00046 #endif
00047 
00048   // Forward declaration
00049   template<class data_t> class uvector_base_tlate;
00050   // Forward declaration
00051   template<class data_t> class uvector_view_tlate;
00052   // Forward declaration
00053   template<class data_t> class uvector_tlate;
00054   // Forward declarations so that we can friend these classes in
00055   // uvector_const_view_tlate below
00056   template<class data_t> class uvector_subvector_tlate;
00057   template<class data_t> class uvector_const_subvector_tlate;
00058 
00059   /** \brief A const vector view with unit stride
00060 
00061       \future Could allow user-defined specification of 
00062       restrict keyword
00063   */
00064   template<class data_t> class uvector_const_view_tlate {
00065     
00066 #ifndef DOXYGEN_INTERNAL
00067 
00068   protected:
00069 
00070     // Make sure everyone can access the base data
00071     friend class uvector_base_tlate<data_t>;
00072     friend class uvector_view_tlate<data_t>;
00073     friend class uvector_tlate<data_t>;
00074     friend class uvector_subvector_tlate<data_t>;
00075     friend class uvector_const_subvector_tlate<data_t>;
00076 
00077     /// The data
00078     data_t *data;
00079     /// The vector sz
00080     size_t sz;
00081     /// Zero if memory is owned elsewhere, 1 otherwise
00082     int owner;
00083     
00084 #endif
00085 
00086   public:
00087 
00088     /// \name Copy constructors
00089     //@{
00090     /// Copy constructor - create a new view of the same vector
00091     uvector_const_view_tlate(const uvector_const_view_tlate &v) {
00092       data=v.data;
00093       sz=v.sz;
00094       owner=0;      
00095     }
00096     
00097     /// Copy constructor - create a new view of the same vector
00098     uvector_const_view_tlate& operator=(const uvector_const_view_tlate &v) {
00099       data=v.data;
00100       sz=v.sz;
00101       owner=0;      
00102 
00103       return *this;
00104     }
00105     //@}
00106 
00107     ~uvector_const_view_tlate() {};
00108     
00109     /// \name Get and set methods
00110     //@{
00111     /** \brief Array-like indexing 
00112      */
00113     const data_t &operator[](size_t i) const {
00114 #if O2SCL_NO_RANGE_CHECK
00115 #else
00116       if (i>=sz) {
00117         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00118                    +" in uvector_const_view_tlate::operator[] const. Size: "+
00119                    itos(sz)+
00120                    " (index should be less than size).").c_str(),gsl_eindex);
00121         return data[0];
00122       }
00123 #endif
00124       return data[i];
00125     }
00126     
00127     /** \brief Array-like indexing 
00128      */
00129     const data_t &operator()(size_t i) const {
00130 #if O2SCL_NO_RANGE_CHECK
00131 #else
00132       if (i>=sz) {
00133         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00134                    +" in uvector_const_view_tlate::operator() const. Size: "+
00135                    itos(sz)+
00136                    " (index should be less than size).").c_str(),gsl_eindex);
00137         return data[0];
00138       }
00139 #endif
00140       return data[i];
00141     }
00142     
00143     /** \brief Get (with optional range-checking) */
00144     data_t get(size_t i) const {
00145 #if O2SCL_NO_RANGE_CHECK
00146 #else
00147       if (i>=sz) {
00148         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00149                    +" in uvector_const_view_tlate::get(). Size: "+
00150                    itos(sz)+
00151                    " (index should be less than size).").c_str(),gsl_eindex);
00152         return data[0];
00153       }
00154 #endif
00155       return data[i];
00156     }
00157     
00158     /** \brief Get pointer (with optional range-checking) */
00159     const data_t *get_const_ptr(size_t i) const {
00160 #if O2SCL_NO_RANGE_CHECK
00161 #else
00162       if (i>=sz) {
00163         O2SCL_ERR2("Index out of range in ",
00164                    "uvector_const_view::get_const_ptr().",1);
00165         return 0;
00166       }
00167 #endif
00168       return (const data_t *)(data+i);
00169     }
00170     
00171     /** \brief Method to return vector size 
00172         
00173         If no memory has been allocated, this will quietly 
00174         return zero.
00175     */
00176     size_t size() const {
00177       return sz;
00178     }
00179     //@}
00180 
00181     /// \name Other methods
00182     //@{
00183 
00184     /// Return true if this object owns the data it refers to
00185     bool is_owner() const {
00186       if (owner==1) return true;
00187       return false;
00188     }
00189 
00190     /** \brief Exhaustively look through the array for a
00191         particular value 
00192 
00193         This can only fail if \em all of the entries in the array are
00194         not finite, in which case it calls O2SCL_ERR() and returns
00195         0. 
00196 
00197         If more than one entry is the same distance from <tt>x0</tt>,
00198         this function returns the entry with smallest index.
00199     */
00200     size_t lookup(const data_t x0) const {
00201 
00202       const uvector_const_view_tlate<data_t> *a=this;
00203       size_t row=0, i=0, nvar=size();
00204       while(!gsl_finite((*a)[i]) && i<nvar-1) i++;
00205       if (i==nvar-1) {
00206         O2SCL_ERR("Array not finite in intp_base::lookup()",1);
00207         return 0;
00208       }
00209       data_t best=(*a)[i], bdiff=fabs((*a)[i]-x0);
00210       for(;i<nvar;i++) {
00211         if (gsl_finite((*a)[i]) && fabs((*a)[i]-x0)<bdiff) {
00212           row=i;
00213           best=(*a)[i];
00214           bdiff=fabs((*a)[i]-x0);
00215         }
00216       }
00217       return row;
00218     }
00219 
00220     /** \brief Find the maximum element */
00221     data_t max() const {
00222       data_t maxval;
00223       if (sz>0) {
00224         maxval=data[0];
00225         for(size_t i=1;i<sz;i++) {
00226           if (data[i]>maxval) {
00227             maxval=data[i];
00228           }
00229         }
00230       } else {
00231         return 0.0;
00232       }
00233       return maxval;
00234     }
00235 
00236     /** \brief Find the minimum element */
00237     data_t min() const {
00238       data_t minval;
00239       if (sz>0) {
00240         minval=data[0];
00241         for(size_t i=1;i<sz;i++) {
00242           if (data[i]<minval) {
00243             minval=data[i];
00244           }
00245         }
00246       } else {
00247         return 0.0;
00248       }
00249       return minval;
00250     }
00251     //@}
00252 
00253     /** \brief Norm 
00254 
00255         \todo Fix this so that norm() is computed as 
00256         in ovector and so that integer norms are performed
00257         separately.
00258     */
00259     data_t norm() const {
00260       data_t result=0;
00261       for(size_t i=0;i<sz;i++) {
00262         result+=(*this)[i]*(*this)[i];
00263       }
00264       return std::sqrt(result);
00265     }
00266         
00267 #ifndef DOXYGEN_INTERNAL
00268 
00269   protected:
00270 
00271     /** \brief Empty constructor provided for use by 
00272         uvector_tlate(const uvector_tlate &v)
00273     */
00274     uvector_const_view_tlate() {};
00275 
00276 #endif
00277     
00278   };
00279   
00280   /** \brief A base class for uvector and uvector_view
00281       
00282       This class pruvides a base class for uvector and uvector_view,
00283       mostly useful for creating function arguments which accept
00284       either uvector or uvector_view. 
00285   */
00286   template<class data_t> class uvector_base_tlate : 
00287   public uvector_const_view_tlate<data_t> {
00288     
00289   public:
00290     
00291     /// \name Copy constructors
00292     //@{
00293     /// Copy constructor - create a new view of the same vector
00294   uvector_base_tlate(uvector_base_tlate &v) : 
00295     uvector_const_view_tlate<data_t>() {
00296       this->data=v.data;
00297       this->sz=v.sz;
00298       this->owner=0;      
00299     }
00300     
00301     /// Copy constructor - create a new view of the same vector
00302     uvector_base_tlate& operator=(uvector_base_tlate &v) {
00303       this->data=v.data;
00304       this->sz=v.sz;
00305       this->owner=0;      
00306 
00307       return *this;
00308     }
00309     //@}
00310 
00311     /// \name Get and set methods
00312     //@{
00313     /** \brief Array-like indexing 
00314      */
00315     data_t &operator[](size_t i) {
00316 #if O2SCL_NO_RANGE_CHECK
00317 #else
00318       if (i>=this->sz) {
00319         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00320                    +" in uvector_const_view_tlate::operator[]. Size: "+
00321                    itos(this->sz)+
00322                    " (index should be less than size).").c_str(),gsl_eindex);
00323         return this->data[0];
00324       }
00325 #endif
00326       return this->data[i];
00327     }
00328     
00329     /** \brief Array-like indexing 
00330      */
00331     const data_t &operator[](size_t i) const {
00332 #if O2SCL_NO_RANGE_CHECK
00333 #else
00334       if (i>=this->sz) {
00335         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00336                    +" in uvector_const_view_tlate::operator[] const. Size: "+
00337                    itos(this->sz)+
00338                    " (index should be less than size).").c_str(),gsl_eindex);
00339         return this->data[0];
00340       }
00341 #endif
00342       return this->data[i];
00343     }
00344     
00345     /** \brief Array-like indexing 
00346      */
00347     data_t &operator()(size_t i) {
00348 #if O2SCL_NO_RANGE_CHECK
00349 #else
00350       if (i>=this->sz) {
00351         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00352                    +" in uvector_const_view_tlate::operator(). Size: "+
00353                    itos(this->sz)+
00354                    " (index should be less than size).").c_str(),gsl_eindex);
00355         return this->data[0];
00356       }
00357 #endif
00358       return this->data[i];
00359     }
00360     
00361     /** \brief Array-like indexing 
00362      */
00363     const data_t &operator()(size_t i) const {
00364 #if O2SCL_NO_RANGE_CHECK
00365 #else
00366       if (i>=this->sz) {
00367         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00368                    +" in uvector_const_view_tlate::operator() const. Size: "+
00369                    itos(this->sz)+
00370                    " (index should be less than size).").c_str(),gsl_eindex);
00371         return this->data[0];
00372       }
00373 #endif
00374       return this->data[i];
00375     }
00376     
00377     /** \brief Get pointer (with optional range-checking) */
00378     data_t *get_ptr(size_t i) {
00379 #if O2SCL_NO_RANGE_CHECK
00380 #else
00381       if (i>=this->sz) {
00382         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00383                    +" in uvector_const_view_tlate::get_ptr(). Size: "+
00384                    itos(this->sz)+
00385                    " (index should be less than size).").c_str(),gsl_eindex);
00386         return this->data;
00387       }
00388 #endif
00389       return this->data+i;
00390     }
00391     
00392     /** \brief Set (with optional range-checking) */
00393     int set(size_t i, data_t val) {
00394 #if O2SCL_NO_RANGE_CHECK
00395 #else
00396       if (i>=this->sz) {
00397         O2SCL_ERR_RET((((std::string)"Array index ")+itos(i)+" out of bounds"
00398                        +" in uvector_const_view_tlate::set(). Size: "+
00399                        itos(this->sz)+
00400                        " (index should be less than size).").c_str(),gsl_eindex);
00401       }
00402 #endif
00403       this->data[i]=val;
00404       return 0;
00405     }
00406 
00407     /** \brief Set all of the value to be the value \c val */
00408     int set_all(data_t val) {
00409       for(size_t i=0;i<this->sz;i++) {
00410         this->data[i]=val;
00411       }
00412       return 0;
00413     }
00414 
00415     //@}
00416 
00417     /// \name Arithmetic
00418     //@{
00419     /** \brief operator+= */
00420     uvector_base_tlate<data_t> &operator+=
00421       (const uvector_base_tlate<data_t> &x) {
00422       size_t lsz=x.size();
00423       if (lsz>this->sz) lsz=this->sz;
00424       for(size_t i=0;i<lsz;i++) (*this)[i]+=x[i];
00425       
00426       return *this;
00427     }
00428     
00429     /** \brief operator-= */
00430     uvector_base_tlate<data_t> &operator-=
00431       (const uvector_base_tlate<data_t> &x) {
00432       size_t lsz=x.size();
00433       if (lsz>this->sz) lsz=this->sz;
00434       for(size_t i=0;i<lsz;i++) (*this)[i]-=x[i];
00435       
00436       return *this;
00437     }
00438     
00439     /** \brief operator+= */
00440     uvector_base_tlate<data_t> &operator+=(const data_t &y) {
00441       for(size_t i=0;i<this->sz;i++) (*this)[i]+=y;
00442 
00443       return *this;
00444     }
00445 
00446     /** \brief operator-= */
00447     uvector_base_tlate<data_t> &operator-=(const data_t &y) {
00448       for(size_t i=0;i<this->sz;i++) (*this)[i]-=y;
00449 
00450       return *this;
00451     }
00452 
00453     /** \brief operator*= */
00454     uvector_base_tlate<data_t> &operator*=(const data_t &y) {
00455       for(size_t i=0;i<this->sz;i++) (*this)[i]*=y;
00456 
00457       return *this;
00458     }
00459     //@}
00460 
00461 #ifndef DOXYGEN_INTERNAL
00462 
00463   protected:
00464 
00465     /** \brief Empty constructor for use by children
00466 
00467         \comment
00468         This is private because I want to prevent the casual end-user
00469         from creating uvector_base objects. End-users should really be
00470         focused on making normal vectors and views.
00471         \endcomment
00472     */
00473     uvector_base_tlate() {}
00474 
00475 #endif
00476 
00477   };
00478     
00479 #ifdef O2SCL_NEVER_DEFINED
00480 }{
00481 #endif
00482 
00483   /** \brief A base class for uvectors
00484    */
00485   template<class data_t> class uvector_view_tlate : 
00486   public uvector_base_tlate<data_t> {
00487 
00488   public:
00489 
00490     /// \name Copy constructors
00491     //@{
00492     /// Copy constructor - create a new view of the same vector
00493   uvector_view_tlate(const uvector_view_tlate &v) : 
00494     uvector_base_tlate<data_t>() {
00495       this->data=v.data;
00496       this->sz=v.sz;
00497       this->owner=0;      
00498     }
00499     
00500     /// Copy constructor - create a new view of the same vector
00501     uvector_view_tlate& operator=(const uvector_view_tlate &v) {
00502       this->data=v.data;
00503       this->sz=v.sz;
00504       this->owner=0;      
00505 
00506       return *this;
00507     }
00508 
00509     /// Copy constructor - create a new view of the same vector
00510   uvector_view_tlate(uvector_base_tlate<data_t> &v) :
00511     uvector_base_tlate<data_t>() {
00512       this->data=v.data;
00513       this->sz=v.sz;
00514       this->owner=0;      
00515     }
00516     
00517     /// Copy constructor - create a new view of the same vector
00518     uvector_view_tlate& operator=(uvector_base_tlate<data_t> &v) {
00519       this->data=v.data;
00520       this->sz=v.sz;
00521       this->owner=0;      
00522 
00523       return *this;
00524     }
00525     //@}
00526 
00527     /// \name Get and set methods
00528     //@{
00529     /** \brief Array-like indexing 
00530      */
00531     data_t &operator[](size_t i) const {
00532 #if O2SCL_NO_RANGE_CHECK
00533 #else
00534       if (i>=this->sz) {
00535         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00536                    +" in uvector_view_tlate::operator[]. Size: "+
00537                    itos(this->sz)+
00538                    " (index should be less than size).").c_str(),gsl_eindex);
00539         return this->data[0];
00540       }
00541 #endif
00542       return this->data[i];
00543     }
00544     
00545     /** \brief Array-like indexing 
00546      */
00547     data_t &operator()(size_t i) const {
00548 #if O2SCL_NO_RANGE_CHECK
00549 #else
00550       if (i>=this->sz) {
00551         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00552                    +" in uvector_view_tlate::operator(). Size: "+
00553                    itos(this->sz)+
00554                    " (index should be less than size).").c_str(),gsl_eindex);
00555         return this->data[0];
00556       }
00557 #endif
00558       return this->data[i];
00559     }
00560     
00561     /** \brief Get pointer (with optional range-checking) */
00562     data_t *get_ptr(size_t i) const {
00563 #if O2SCL_NO_RANGE_CHECK
00564 #else
00565       if (i>=this->sz) {
00566         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00567                    +" in uvector_view_tlate::get_ptr(). Size: "+
00568                    itos(this->sz)+
00569                    " (index should be less than size).").c_str(),gsl_eindex);
00570         return this->data;
00571       }
00572 #endif
00573       return this->data+i;
00574     }
00575     
00576     /** \brief Set (with optional range-checking) */
00577     int set(size_t i, data_t val) const {
00578 #if O2SCL_NO_RANGE_CHECK
00579 #else
00580       if (i>=this->sz) {
00581         O2SCL_ERR_RET((((std::string)"Array index ")+itos(i)+" out of bounds"
00582                        +" in uvector_view_tlate::set(). Size: "+
00583                        itos(this->sz)+
00584                        " (index should be less than size).").c_str(),gsl_eindex);
00585       }
00586 #endif
00587       this->data[i]=val;
00588       return 0;
00589     }
00590 
00591     /** \brief Set all of the value to be the value \c val */
00592     int set_all(data_t val) const {
00593       for(size_t i=0;i<this->sz;i++) {
00594         this->data[i]=val;
00595       }
00596       return 0;
00597     }
00598 
00599     //@}
00600 
00601 #ifndef DOXYGEN_INTERNAL
00602 
00603   protected:
00604 
00605     /** \brief Empty constructor provided for use by 
00606         uvector_view_tlate(const uvector_view_tlate &v)
00607     */
00608     uvector_view_tlate() {}
00609 
00610 #endif
00611 
00612   };
00613   
00614   /** \brief A vector with unit stride
00615       
00616       There are several useful methods which are defined in the parent
00617       class, \ref uvector_view_tlate .  There is also an << operator
00618       for this class documented "Functions" section of \ref
00619       uvector_tlate.h.
00620   */
00621   template<class data_t> class uvector_tlate : 
00622   public uvector_base_tlate<data_t> {
00623 
00624   public:
00625 
00626     // This is required so that the uvector_view_tlate constructor
00627     // can access uvector_tlate data.
00628     friend class uvector_view_tlate<data_t>;
00629 
00630     /// \name Standard constructor
00631     //@{
00632     /** \brief Create an uvector of size \c n with owner as 'true' */
00633     uvector_tlate(size_t n=0) {
00634       
00635       this->sz=0;
00636       this->data=0;
00637 
00638       // This must be set to 1 even if n=0 so that future
00639       // calls to operator= work properly
00640       this->owner=1;
00641 
00642       if (n>0) {
00643         this->data=(data_t *)malloc(n*sizeof(data_t));
00644         if (this->data) {
00645           this->sz=n;
00646         } else {
00647           O2SCL_ERR("No memory for data in uvector_tlate constructor",
00648                     gsl_enomem);
00649         }
00650       }
00651     }
00652     //@}
00653     
00654     /// \name Copy constructors
00655     //@{
00656     /// Deep copy constructor - allocate new space and make a copy
00657   uvector_tlate(const uvector_tlate &v) : 
00658     uvector_base_tlate<data_t>() {
00659 
00660       this->sz=0;
00661       this->data=0;
00662       this->owner=1;
00663 
00664       size_t n=v.sz;
00665       if (n>0) {
00666         this->data=(data_t *)malloc(n*sizeof(data_t));
00667         if (this->data) {
00668           this->sz=n;
00669           this->owner=1;
00670           for(size_t i=0;i<n;i++) {
00671             this->data[i]=v[i];
00672           }
00673         } else {
00674           O2SCL_ERR("No memory for data in uvector_tlate constructor",
00675                     gsl_enomem);
00676         }
00677       } else {
00678         this->sz=0;
00679       }
00680     }
00681     
00682     /// Deep copy constructor - allocate new space and make a copy
00683   uvector_tlate(const uvector_const_view_tlate<data_t> &v) : 
00684     uvector_base_tlate<data_t>() {
00685 
00686       this->sz=0;
00687       this->data=0;
00688       this->owner=1;
00689 
00690       size_t n=v.size();
00691       if (n>0) {
00692         this->data=(data_t *)malloc(n*sizeof(data_t));
00693         if (this->data) {
00694           this->sz=n;
00695           this->owner=1;
00696           for(size_t i=0;i<n;i++) {
00697             this->data[i]=v[i];
00698           }
00699         } else {
00700           O2SCL_ERR("No memory for data in uvector_tlate constructor",
00701                     gsl_enomem);
00702         }
00703       } else {
00704         this->sz=0;
00705       }
00706     }
00707 
00708     /** \brief Deep copy constructor - if owner is true, allocate space and
00709         make a new copy, otherwise, just copy into the view
00710     */
00711     uvector_tlate& operator=(const uvector_tlate &v) {
00712 
00713       // Check for self-assignment
00714       if (this==&v) return *this;
00715 
00716       size_t sz2=v.sz;
00717       this->sz=0;
00718       this->data=0;
00719       if (this->owner) {
00720         allocate(sz2);
00721       } else {
00722         if (this->sz!=sz2) {
00723           O2SCL_ERR("Sizes don't match in uvector_tlate::operator=()",
00724                     gsl_ebadlen);
00725           return *this;
00726         }
00727       }
00728       for(size_t i=0;i<sz2;i++) {
00729         this->data[i]=v[i];
00730       }
00731       return *this;
00732     }
00733 
00734     /** \brief Deep copy constructor - if owner is true, allocate space and
00735         make a new copy, otherwise, just copy into the view
00736     */
00737     uvector_tlate& operator=(const uvector_const_view_tlate<data_t> &v) {
00738 
00739       // Check for self-assignment
00740       if (this==&v) return *this;
00741 
00742       size_t sz2=v.size();
00743       this->sz=0;
00744       this->data=0;
00745       if (this->owner) {
00746         allocate(sz2);
00747       } else {
00748         if (this->sz!=sz2) {
00749           O2SCL_ERR("Sizes don't match in uvector_tlate::operator=()",
00750                     gsl_ebadlen);
00751           return *this;
00752         }
00753       }
00754       for(size_t i=0;i<sz2;i++) {
00755         this->data[i]=v[i];
00756       }
00757       return *this;
00758     }
00759     //@}
00760 
00761     ~uvector_tlate() {
00762       if (this->sz>0) {
00763         if (this->owner==1) {
00764           std::free(this->data);
00765         }
00766         this->sz=0;
00767       }
00768     }
00769 
00770     /// \name Memory allocation
00771     //@{
00772     /** \brief Allocate memory for size \c n after freeing any memory 
00773         presently in use
00774 
00775         If \c nsize is zero, this only frees the memory and allocates
00776         no additional memory. 
00777         \comment
00778         9/16/09 - I used to set an error here, but that was causing
00779         problems with std::vector<uvector> type objects, and also
00780         we don't want the user to have to make an extra nsize>0 check
00781         every time they call allocate(), so we don't set an error here.
00782         \endcomment
00783     */
00784     int allocate(size_t nsize) {
00785       if (this->sz>0) free();
00786 
00787       if (nsize>0) {
00788         this->data=(data_t *)malloc(nsize*sizeof(data_t));
00789         if (this->data) {
00790           this->sz=nsize;
00791           this->owner=1;
00792         } else {
00793           O2SCL_ERR_RET("No memory for data in uvector_tlate::allocate()",
00794                         gsl_enomem);
00795         }
00796       }
00797       return 0;
00798     }
00799 
00800     /** \brief Free the memory 
00801     
00802         This function will safely do nothing if used without first
00803         allocating memory or if called multiple times in succession.
00804     */
00805     int free() {
00806       if (this->sz>0) {
00807         if (this->owner==1) {
00808           std::free(this->data);
00809         }
00810         this->sz=0;
00811       }
00812       return 0;
00813     }
00814     //@}
00815 
00816     /// \name Other methods
00817     //@{
00818     /// Erase an element from the array. 
00819     int erase(size_t ix) {
00820 
00821       // Only proceed if the user gave an element inside the array
00822       if (this->sz>ix) {
00823 
00824         // Decrement the size 
00825         this->sz--;
00826 
00827         // Allocate new space
00828         data_t *newdat=(data_t *)(malloc(this->sz*sizeof(data_t)));
00829 
00830         // Copy into the new space
00831         for(size_t i=0;i<this->sz;i++) {
00832           if (i<ix) newdat[i]=this->data[i];
00833           else newdat[i]=this->data[i+1];
00834         }
00835 
00836         // Free the old space and reset the pointer
00837         std::free(this->data);
00838         this->data=newdat;
00839 
00840       } else {
00841         O2SCL_ERR_RET("Cannot erase() beyond end of uvector_tlate.",
00842                       gsl_einval);
00843       }
00844 
00845       return 0;
00846     }
00847     //@}
00848 
00849     /** \brief Sort the vector and ensure all elements are unique by 
00850         removing duplicates
00851     */
00852     int sort_unique() {
00853       o2scl::vector_sort<uvector_tlate<data_t>,data_t >(this->sz,*this);
00854       for(size_t i=1;i<this->sz;i++) {
00855         if ((*this)[i]==(*this)[i-1]) {
00856           int ret=erase(i-1);
00857           if (ret!=0) {
00858             O2SCL_ERR_RET("Erase failed in uvector_tlate::sort_unique().",
00859                           gsl_esanity);
00860           }
00861           i--;
00862         }
00863       }
00864       return 0;
00865     }
00866     //@}
00867 
00868   };
00869 
00870   /** \brief Create a vector from an array 
00871    */
00872   template<class data_t> class uvector_array_tlate : 
00873   public uvector_view_tlate<data_t> {
00874   public:
00875     /** \brief Create a vector from \c dat with size \c n */
00876     uvector_array_tlate(size_t n, data_t *dat) {
00877       if (n>0) {
00878         this->data=dat;
00879         this->sz=n;
00880         this->owner=0;
00881       }
00882     }
00883   };
00884     
00885   /** \brief Create a vector from a subvector of another
00886    */
00887   template<class data_t> class uvector_subvector_tlate : 
00888   public uvector_view_tlate<data_t> {
00889   public:
00890     /** \brief Create a vector from \c orig */
00891     uvector_subvector_tlate(uvector_base_tlate<data_t> &orig, 
00892                             size_t offset, size_t n) {
00893       if (offset+n-1<orig.size()) {
00894         this->data=orig.data+offset;
00895         this->sz=n;
00896         this->owner=0;
00897       } else {
00898         this->sz=0;
00899         O2SCL_ERR("Subvector failed in uvector_sub_view().",1);
00900       }
00901     }
00902   };
00903 
00904   /** \brief Create a vector from an const array 
00905    */
00906   template<class data_t> class uvector_const_array_tlate :
00907   public uvector_const_view_tlate<data_t> {
00908   public:
00909     /** \brief Create a vector from \c dat with size \c n */
00910     uvector_const_array_tlate(size_t n, const data_t *dat) {
00911       if (n>0) {
00912         // We have to do an explicit cast here, but we prevent the
00913         // user from changing the data.
00914         this->data=(data_t *)dat;
00915         this->sz=n;
00916         this->owner=0;
00917       }
00918     }
00919     
00920     ~uvector_const_array_tlate() {};
00921     
00922   };
00923 
00924   /** \brief Create a const vector from a subvector of another vector
00925    */
00926   template<class data_t> class uvector_const_subvector_tlate :
00927   public uvector_const_view_tlate<data_t> {
00928   public:
00929     /** \brief Create a vector from \c orig 
00930      */
00931     uvector_const_subvector_tlate
00932       (const uvector_base_tlate<data_t> &orig, size_t offset, size_t n) {
00933       if (offset+n-1<orig.sz) {
00934         this->data=orig.data+offset;
00935         this->sz=n;
00936         this->owner=0;
00937       } else {
00938         this->sz=0;
00939         O2SCL_ERR("Subvector failed in uvector_subvector().",1);
00940       }
00941     }
00942 
00943   };
00944 
00945   /// uvector typedef
00946   typedef uvector_tlate<double> uvector;
00947   /// uvector_view typedef
00948   typedef uvector_view_tlate<double> uvector_view;
00949   /// uvector_base typedef
00950   typedef uvector_base_tlate<double> uvector_base;
00951   /// uvector_const_view typedef
00952   typedef uvector_const_view_tlate<double> uvector_const_view;
00953   /// uvector_array typedef
00954   typedef uvector_array_tlate<double> uvector_array;
00955   /// uvector_subvector typedef
00956   typedef uvector_subvector_tlate<double> uvector_subvector;
00957   /// uvector_const_array typedef
00958   typedef uvector_const_array_tlate<double> uvector_const_array;
00959   /// uvector_const_subvector typedef
00960   typedef uvector_const_subvector_tlate<double> uvector_const_subvector;
00961   
00962   /// uvector_int typedef
00963   typedef uvector_tlate<int> uvector_int;
00964   /// uvector_int_view typedef
00965   typedef uvector_view_tlate<int> uvector_int_view;
00966   /// uvector_int_base typedef
00967   typedef uvector_base_tlate<int> uvector_int_base;
00968   /// uvector_int_const_view typedef
00969   typedef uvector_const_view_tlate<int> uvector_int_const_view;
00970   /// uvector_int_array typedef
00971   typedef uvector_array_tlate<int> uvector_int_array;
00972   /// uvector_int_subvector typedef
00973   typedef uvector_subvector_tlate<int> uvector_int_subvector;
00974   /// uvector_int_const_array typedef
00975   typedef uvector_const_array_tlate<int> uvector_int_const_array;
00976   /// uvector_int_const_subvector typedef
00977   typedef uvector_const_subvector_tlate<int> uvector_int_const_subvector;
00978 
00979   /// uvector_size_t typedef
00980   typedef uvector_tlate<size_t> uvector_size_t;
00981   /// uvector_size_t_view typedef
00982   typedef uvector_view_tlate<size_t> uvector_size_t_view;
00983   /// uvector_size_t_base typedef
00984   typedef uvector_base_tlate<size_t> uvector_size_t_base;
00985   /// uvector_size_t_const_view typedef
00986   typedef uvector_const_view_tlate<size_t> uvector_size_t_const_view;
00987   /// uvector_size_t_array typedef
00988   typedef uvector_array_tlate<size_t> uvector_size_t_array;
00989   /// uvector_size_t_subvector typedef
00990   typedef uvector_subvector_tlate<size_t> uvector_size_t_subvector;
00991   /// uvector_size_t_const_array typedef
00992   typedef uvector_const_array_tlate<size_t> uvector_size_t_const_array;
00993   /// uvector_size_t_const_subvector typedef
00994   typedef uvector_const_subvector_tlate<size_t> 
00995     uvector_size_t_const_subvector;
00996 
00997   /** \brief A operator for simple vector output
00998 
00999       This outputs all of the vector elements. All of these are
01000       separated by one space character, though no trailing space or \c
01001       endl is sent to the output. If the vector is empty, nothing
01002       is done.
01003   */
01004   template<class data_t>
01005     std::ostream &operator<<
01006     (std::ostream &os, 
01007      const uvector_const_view_tlate<data_t> &v) {
01008     if (v.size()>0) {
01009       for(size_t i=0;i<v.size()-1;i++) {
01010         os << v[i] << ' ';
01011       }
01012       os << v[v.size()-1];
01013     }
01014     return os;
01015   }
01016   
01017   /** \brief A simple class to provide an \c allocate() function
01018       for \ref uvector
01019   */
01020   class uvector_alloc {
01021   public:
01022     /// Allocate \c v for \c i elements
01023     void allocate(uvector &o, size_t i) { o.allocate(i); }
01024     /// Free memory
01025     void free(uvector &o) { o.free(); }
01026   };
01027 
01028   /** \brief A simple class to provide an \c allocate() function
01029       for \ref uvector_int
01030   */
01031   class uvector_int_alloc {
01032   public:
01033     /// Allocate \c v for \c i elements
01034     void allocate(uvector_int &o, size_t i) { o.allocate(i); }
01035     /// Free memory
01036     void free(uvector_int &o) { o.free(); }
01037   };
01038 
01039   /** \brief A simple class to provide an \c allocate() function
01040       for \ref uvector_size_t
01041   */
01042   class uvector_size_t_alloc {
01043   public:
01044     /// Allocate \c v for \c i elements
01045     void allocate(uvector_size_t &o, size_t i) { o.allocate(i); }
01046     /// Free memory
01047     void free(uvector_size_t &o) { o.free(); }
01048   };
01049 
01050   /** \brief A vector with unit-stride where the memory allocation is 
01051       performed in the constructor
01052   */
01053 #ifdef DOXYGENP
01054   template<size_t N=0> class ufvector : 
01055   public uvector_tlate<data_t>
01056 #else
01057     template<size_t N=0> class ufvector : 
01058   public uvector_tlate<double>
01059 #endif
01060   {
01061   public:
01062   ufvector() : uvector_tlate<double>(N) {
01063     }
01064   };
01065   
01066 #ifndef DOXYGENP
01067 }
01068 #endif
01069 
01070 #endif
01071 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.