Object-oriented Scientific Computing Library: Version 0.910
ovector_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_OVECTOR_TLATE_H
00024 #define O2SCL_OVECTOR_TLATE_H
00025 
00026 /** \file ovector_tlate.h
00027     \brief File for definitions of vectors
00028 
00029     \future Clean up maybe by moving, for example, ovector reverse
00030     classes to a different header file
00031     \future Define ovector_uint classes?
00032 */
00033 
00034 #include <iostream>
00035 #include <cstdlib>
00036 #include <cmath>
00037 #include <string>
00038 #include <fstream>
00039 #include <sstream>
00040 #include <vector>
00041 
00042 #include <gsl/gsl_vector.h>
00043 #include <gsl/gsl_sys.h>
00044 
00045 #include <o2scl/err_hnd.h>
00046 #include <o2scl/string_conv.h>
00047 #include <o2scl/uvector_tlate.h>
00048 #include <o2scl/array.h>
00049 #include <o2scl/vector.h>
00050 
00051 #ifndef DOXYGENP
00052 namespace o2scl {
00053 #endif
00054 
00055   /** \brief Norm object for gsl vectors
00056       
00057       This object is principally for use inside the ovector templates
00058       e.g.. \ref ovector_tlate . For most applications, this object
00059       need not be instantiated directly by the end-user. 
00060 
00061       For an empty vector, this function returns zero and does not
00062       call the error handler.
00063   */
00064   class gsl_vector_norm : public gsl_vector {
00065     
00066   public:
00067     
00068     /// Compute the norm of a gsl_vector
00069     double norm() const {
00070       
00071       double scale = 0.0;                                
00072       double ssq = 1.0;                          
00073       
00074       if (this->size <= 0) {                             
00075         return 0.0;                              
00076       } else if (this->size == 1) {                      
00077         return fabs((this->data)[0]);
00078       }                                          
00079       
00080       for (size_t i = 0; i < this->size; i++) {          
00081         const double x = (this->data)[i*this->stride];
00082         
00083         if (x != 0.0) {                          
00084           const double ax = fabs(x);             
00085           
00086           if (scale < ax) {                                 
00087             ssq = 1.0 + ssq * (scale / ax) * (scale / ax);    
00088             scale = ax;                                     
00089           } else {                                          
00090             ssq += (ax / scale) * (ax / scale);             
00091           }                                                 
00092         }                                                           
00093         
00094       }                                                     
00095       
00096       return scale * std::sqrt(ssq);                                
00097     }
00098   };
00099 
00100   /* Forward declaration of ovector_base_tlate (This is used to allow
00101      the iterator to friend ovector_base; undocumented)
00102    */
00103   template<class data_t, class vparent_t, class block_t> 
00104     class ovector_base_tlate;
00105   
00106   /** \brief A const vector view with finite stride
00107   */
00108   template<class data_t, class vparent_t, class block_t> 
00109     class ovector_const_view_tlate : 
00110   public vparent_t {
00111     
00112   public:
00113 
00114     // Forward declaration of iterator class (undocumented)
00115     class iterator;
00116 
00117     /** \brief A const iterator for ovectors
00118         
00119         \note Experimental.
00120         
00121         \todo Default constructor and iterator typedefs
00122     */
00123     class const_iterator {
00124 
00125     protected:
00126 
00127       /// Pointer to current
00128       data_t *dp;
00129 
00130       /// Stride
00131       size_t stride;
00132 
00133       /// Internally create an iterator directly from a pointer
00134       const_iterator(data_t *p, size_t s) {
00135         dp=p;
00136         stride=s;
00137       }
00138 
00139       /// Grant access to ovector classes for begin() and end() functions
00140       friend class ovector_const_view_tlate<data_t,vparent_t,block_t>;
00141 
00142       /// Grant access to ovector classes for begin() and end() functions
00143       friend class ovector_base_tlate<data_t,vparent_t,block_t>;
00144 
00145     public:
00146       /// Copy-constructor for a const iterator
00147       const_iterator(const iterator &it) {
00148         dp=it.dp;
00149         stride=it.stride;
00150       }
00151 
00152       /// Equality
00153       bool operator==(const const_iterator &it) const {
00154         return (dp==it.dp);
00155       }
00156 
00157       /// Inequality
00158       bool operator!=(const const_iterator &it) const {
00159         return (dp!=it.dp);
00160       }
00161 
00162       /// Inequality
00163       bool operator!=(const iterator &it) const {
00164         return (dp!=it.dp);
00165       }
00166 
00167       /// Less than
00168       bool operator<(const const_iterator &it) const {
00169         return (dp<it.dp);
00170       }
00171 
00172       /// Greater than
00173       bool operator>(const const_iterator &it) const {
00174         return (dp>it.dp);
00175       }
00176 
00177       /// Prefix increment
00178       const_iterator operator++() {
00179         dp+=stride;
00180         return *this;
00181       }
00182 
00183       /// Prefix decrement
00184       const_iterator operator--() {
00185         dp-=stride;
00186         return *this;
00187       }
00188 
00189       /// Postfix increment
00190       const_iterator operator++(int) {
00191         dp+=stride;
00192         return *this;
00193       }
00194 
00195       /// Postfix decrement
00196       const_iterator operator--(int) {
00197         dp-=stride;
00198         return *this;
00199       }
00200 
00201       /// Dereference - return the corresponding vector element
00202       const data_t operator*() const {
00203         return *dp;
00204       }
00205 
00206       /// Move forward
00207       const_iterator operator+=(size_t n) {
00208         dp+=n*stride;
00209         return *this;
00210       }
00211 
00212       /// Move backwards
00213       const_iterator operator-=(size_t n) {
00214         dp-=n*stride;
00215         return *this;
00216       }
00217     };
00218 
00219     /** \brief An iterator for ovectors
00220         
00221         \note Experimental.
00222      */
00223     class iterator : public const_iterator {
00224 
00225      protected:
00226 
00227       /// Internally create an iterator directly from a pointer
00228     iterator(data_t *p, size_t s) : const_iterator(p,s) {
00229       }
00230 
00231       /// Grant access to ovector classes for begin() and end() functions
00232       friend class ovector_const_view_tlate<data_t,vparent_t,block_t>;
00233 
00234       /// Grant access to ovector classes for begin() and end() functions
00235       friend class ovector_base_tlate<data_t,vparent_t,block_t>;
00236 
00237     public:
00238 
00239       /// Copy constructor
00240       iterator(const const_iterator &cit) {
00241         this->dp=cit.dp;
00242         this->stride=cit.stride;
00243       }
00244 
00245       /// Dereference - return the corresponding vector element
00246       const data_t operator*() const {
00247         return *(this->dp);
00248       }
00249 
00250       /// Dereference - return the corresponding vector element
00251       data_t operator*() {
00252         return *(this->dp);
00253       }
00254     };
00255 
00256     /// An iterator for the beginning of the vector
00257     const_iterator begin() const {
00258       return const_iterator(vparent_t::data,vparent_t::stride);
00259     }
00260 
00261     /// An iterator for the end of the vector
00262     const_iterator end() const {
00263       return const_iterator(vparent_t::data+vparent_t::size*vparent_t::stride,
00264                             vparent_t::stride);
00265     }
00266 
00267     /// \name Copy constructors
00268     //@{
00269     /// Shallow copy constructor - create a new view of the same vector
00270     ovector_const_view_tlate(const ovector_const_view_tlate &v) {
00271       vparent_t::block=0;
00272       vparent_t::data=v.data;
00273       vparent_t::size=v.size();
00274       vparent_t::stride=v.stride();
00275       vparent_t::owner=0;      
00276     }
00277 
00278     /// Shallow copy constructor - create a new view of the same vector
00279     ovector_const_view_tlate& operator=(const ovector_const_view_tlate &v) {
00280       vparent_t::block=0;
00281       vparent_t::data=v.data;
00282       vparent_t::size=v.size();
00283       vparent_t::stride=v.stride();
00284       vparent_t::owner=0;      
00285 
00286       return *this;
00287     }
00288 
00289     /** \brief Shallow copy constructor - view a unit-stride vector
00290      */
00291     ovector_const_view_tlate(const uvector_const_view_tlate<data_t> &v) {
00292       vparent_t::block=0;
00293       vparent_t::data=v.data;
00294       vparent_t::size=v.size();
00295       vparent_t::stride=1;
00296       vparent_t::owner=0;      
00297     }
00298     
00299     /// Shallow copy constructor - view a unit-stride vector
00300     ovector_const_view_tlate& operator=
00301       (const uvector_const_view_tlate<data_t> &v) {
00302       vparent_t::block=0;
00303       vparent_t::data=v.data;
00304       vparent_t::size=v.size();
00305       vparent_t::stride=1;
00306       vparent_t::owner=0;      
00307 
00308       return *this;
00309     }
00310     //@}
00311 
00312     ~ovector_const_view_tlate() {};
00313 
00314     /// \name Get methods
00315     //@{
00316     /** \brief Array-like indexing (with optional range-checking)
00317      */
00318     const data_t &operator[](size_t i) const {
00319 #if O2SCL_NO_RANGE_CHECK
00320 #else
00321       if (i>=vparent_t::size) {
00322         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00323                    +" in ovector_const_view_tlate::operator[]. Size: "+
00324                    itos(vparent_t::size)+
00325                    " (index should be less than size).").c_str(),gsl_eindex);
00326         return vparent_t::data[0];
00327       }
00328 #endif
00329       return vparent_t::data[i*vparent_t::stride];
00330     }
00331     
00332     /** \brief Array-like indexing (with optional range-checking)
00333      */
00334     const data_t &operator()(size_t i) const {
00335 #if O2SCL_NO_RANGE_CHECK
00336 #else
00337       if (i>=vparent_t::size) {
00338         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00339                    +" in ovector_const_view_tlate::operator(). Size: "+
00340                    itos(vparent_t::size)+
00341                    " (index should be less than size).").c_str(),gsl_eindex);
00342         return vparent_t::data[0];
00343       }
00344 #endif
00345       return vparent_t::data[i*vparent_t::stride];
00346     }
00347 
00348     /** \brief Get (with optional range-checking) */
00349     data_t get(size_t i) const {
00350 #if O2SCL_NO_RANGE_CHECK
00351 #else
00352       if (i>=vparent_t::size) {
00353         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00354                    +" in ovector_const_view_tlate::get(). Size: "+
00355                    itos(vparent_t::size)+
00356                    " (index should be less than size).").c_str(),gsl_eindex);
00357         return vparent_t::data[0];
00358       }
00359 #endif
00360       return vparent_t::data[i*vparent_t::stride];
00361     }
00362     
00363     /** \brief Get pointer (with optional range-checking) */
00364     const data_t *get_const_ptr(size_t i) const {
00365 #if O2SCL_NO_RANGE_CHECK
00366 #else
00367       if (i>=vparent_t::size) {
00368         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00369                    +" in ovector_const_view_tlate::get_const_ptr(). Size: "+
00370                    itos(vparent_t::size)+
00371                    " (index should be less than size).").c_str(),gsl_eindex);
00372         return vparent_t::data;
00373       }
00374 #endif
00375       return (const data_t *)(vparent_t::data+i*vparent_t::stride);
00376     }
00377     
00378     /** \brief Method to return vector size 
00379 
00380         If no memory has been allocated, this will quietly 
00381         return zero.
00382     */
00383     size_t size() const {
00384       return vparent_t::size;
00385     }
00386 
00387     /** \brief Method to return capacity
00388 
00389         Analogous to <tt>std::vector<>.capacity()</tt>.
00390     */
00391     size_t capacity() const {
00392       if (vparent_t::block) return vparent_t::block->size;
00393       return 0;
00394     }
00395 
00396     /** \brief Method to return vector stride
00397 
00398         If no memory has been allocated, this will quietly return
00399         zero.
00400     */
00401     size_t stride() const {
00402       return vparent_t::stride;
00403     }
00404     //@}
00405 
00406     /// \name Other methods
00407     //@{
00408     /** \brief Return true if this object owns the data it refers to
00409 
00410         This can be used to determine if an object is a "vector_view",
00411         or a "vector". If is_owner() is true, then it is an \ref
00412         ovector_tlate object.
00413 
00414         If any \o2 class creates a \ref ovector_tlate object in which
00415         \ref is_owner() returns false, then it is a bug and should be
00416         reported.
00417     */
00418     bool is_owner() const {
00419       if (vparent_t::owner==1) return true;
00420       return false;
00421     }
00422 
00423     /** \brief Exhaustively look through the vector for a
00424         particular value and return the closest match
00425 
00426         This can only fail if the vector is empty or if \em all of the
00427         entries in the vector are not finite. In these cases the
00428         function calls the error handler and returns 0.
00429 
00430         If more than one entry is the same distance from <tt>x0</tt>,
00431         this function returns the entry with smallest index.
00432     */
00433     size_t lookup(const data_t x0) const {
00434       if (vparent_t::size==0) {
00435         O2SCL_ERR("Empty vector ovector_const_view_tlate::lookup().",
00436                   gsl_einval);
00437         return 0;
00438       }
00439       const ovector_const_view_tlate<data_t,vparent_t,block_t> *a=this;
00440       size_t row=0, i=0, nvar=size();
00441       while(!gsl_finite((*a)[i]) && i<nvar-1) i++;
00442       if (i==nvar-1) {
00443         O2SCL_ERR2("Entire array not finite in ",
00444                    "ovector_const_view_tlate::lookup()",gsl_einval);
00445         return 0;
00446       }
00447       data_t best=(*a)[i], bdiff=fabs((*a)[i]-x0);
00448       for(;i<nvar;i++) {
00449         if (gsl_finite((*a)[i]) && fabs((*a)[i]-x0)<bdiff) {
00450           row=i;
00451           best=(*a)[i];
00452           bdiff=fabs((*a)[i]-x0);
00453         }
00454       }
00455       return row;
00456     }
00457 
00458     /** \brief Find the maximum element 
00459 
00460         This can only fail if \em all of the entries in the array are
00461         not finite or if the vector is empty, in which case it calls
00462         the error handler and returns 0.
00463     */
00464     data_t max() const {
00465       data_t maxval=0;
00466       if (vparent_t::size>0) {
00467         bool setb=false;
00468         for(size_t i=0;i<vparent_t::size;i++) {
00469           double v=vparent_t::data[i];
00470           if (gsl_finite(v)) {
00471             if (setb==false) {
00472               maxval=v;
00473               setb=true;
00474             } else if (v>maxval) {
00475               maxval=v;
00476             }
00477           }
00478         }
00479         if (setb==false) {
00480           O2SCL_ERR("No finite values in ovector_const_view_tlate::max().",
00481                     gsl_einval);
00482           return 0.0;
00483         }
00484       } else {
00485         O2SCL_ERR("Empty vector in ovector_const_view_tlate::max().",
00486                   gsl_einval);
00487         return 0.0;
00488       }
00489       return maxval;
00490     }
00491 
00492     /** \brief Find the location of the maximum element 
00493 
00494         This can only fail if \em all of the entries in the array are
00495         not finite or if the vector is empty, in which case it calls
00496         the error handler and returns 0.
00497     */
00498     size_t max_index() const {
00499 
00500       if (vparent_t::size>0) {
00501 
00502         // These next two variables don't need initialization, but
00503         // we do so here to avoid warnings. These initial values
00504         // are essentially ignored by the code below.
00505         data_t maxval=vparent_t::data[0];
00506         size_t loc=0;
00507         
00508         bool setb=false;
00509         for(size_t i=0;i<vparent_t::size;i++) {
00510           double v=vparent_t::data[i];
00511           if (gsl_finite(v)) {
00512             if (setb==false) {
00513               maxval=v;
00514               loc=i;
00515               setb=true;
00516             } else if (v>maxval) {
00517               maxval=v;
00518               loc=i;
00519             }
00520           }
00521         }
00522 
00523         if (setb==false) {
00524           O2SCL_ERR2("No finite values in ",
00525                      "ovector_const_view_tlate::max_index().",gsl_einval);
00526           return 0;
00527         }
00528 
00529         return loc;
00530 
00531       }
00532        
00533       O2SCL_ERR("Empty vector ovector_const_view_tlate::max_index().",
00534                 gsl_einval);
00535       return 0;
00536     }
00537 
00538     /** \brief Find the minimum element 
00539 
00540         This can only fail if \em all of the entries in the array are
00541         not finite or if the vector is empty, in which case it calls
00542         the error handler and returns 0.
00543     */
00544     data_t min() const {
00545       data_t minval=0;
00546       if (vparent_t::size>0) {
00547         bool setb=false;
00548         for(size_t i=0;i<vparent_t::size;i++) {
00549           double v=vparent_t::data[i];
00550           if (gsl_finite(v)) {
00551             if (setb==false) {
00552               minval=v;
00553               setb=true;
00554             } else if (v<minval) {
00555               minval=v;
00556             }
00557           }
00558         }
00559         if (setb==false) {
00560           O2SCL_ERR("No finite values in ovector_const_view_tlate::min().",
00561                     gsl_einval);
00562           return 0.0;
00563         }
00564       } else {
00565         O2SCL_ERR("Empty vector ovector_const_view_tlate::min().",
00566                   gsl_einval);
00567         return 0.0;
00568       }
00569       return minval;
00570     }
00571 
00572     /** \brief Find the location of the minimum element 
00573 
00574         This can only fail if \em all of the entries in the array are
00575         not finite or if the vector is empty, in which case it calls
00576         the error handler and returns 0.
00577     */
00578     size_t min_index() const {
00579       
00580       if (vparent_t::size>0) {
00581 
00582         // These next two variables don't need initialization, but
00583         // we do so here to avoid warnings. These initial values
00584         // are essentially ignored by the code below.
00585         data_t maxval=vparent_t::data[0];
00586         size_t loc=0;
00587         
00588         bool setb=false;
00589         for(size_t i=0;i<vparent_t::size;i++) {
00590           double v=vparent_t::data[i];
00591           if (gsl_finite(v)) {
00592             if (setb==false) {
00593               maxval=v;
00594               loc=i;
00595               setb=true;
00596             } else if (v<maxval) {
00597               maxval=v;
00598               loc=i;
00599             }
00600           }
00601         }
00602 
00603         if (setb==false) {
00604           O2SCL_ERR2("No finite values in ",
00605                      "ovector_const_view_tlate::min_index().",gsl_einval);
00606           return 0;
00607         }
00608         
00609         return loc;
00610       } 
00611       
00612       O2SCL_ERR("Empty vector ovector_const_view_tlate::min_index().",
00613                 gsl_einval);
00614       return 0;
00615     }
00616     //@}
00617 
00618 
00619 
00620 #ifndef DOXYGEN_INTERNAL
00621 
00622   protected:
00623 
00624     /** \brief Empty constructor provided for use by 
00625         ovector_view_tlate(const ovector_view_tlate &v)
00626     */
00627     ovector_const_view_tlate() {};
00628 
00629 #endif
00630     
00631   };
00632 
00633   /** \brief A base class for ovector and ovector_view
00634 
00635       This class provides a base class for ovector and ovector_view,
00636       mostly useful for creating function arguments which accept
00637       either ovector or ovector_view. 
00638   */
00639   template<class data_t, class vparent_t, class block_t> 
00640     class ovector_base_tlate : 
00641   public ovector_const_view_tlate<data_t,vparent_t,block_t> {
00642     
00643   public:
00644 
00645     /// Desc
00646     typedef typename ovector_const_view_tlate<data_t,
00647       vparent_t,block_t>::const_iterator const_iterator;
00648     /// Desc
00649     typedef typename ovector_const_view_tlate<data_t,
00650       vparent_t,block_t>::iterator iterator;
00651     
00652     /// Desc
00653     const_iterator begin() const {
00654       return const_iterator(vparent_t::data,vparent_t::stride);
00655     }
00656     /// Desc
00657     const_iterator end() const {
00658       return const_iterator(vparent_t::data+vparent_t::size*vparent_t::stride,
00659                             vparent_t::stride);
00660     }
00661     /// Desc
00662     iterator begin() {
00663       return iterator(vparent_t::data,vparent_t::stride);
00664     }
00665     /// Desc
00666     iterator end() {
00667       return iterator(vparent_t::data+vparent_t::size*vparent_t::stride,
00668                       vparent_t::stride);
00669     }
00670 
00671     /// \name Copy constructors
00672     //@{
00673 
00674     /// Shallow copy constructor - create a new view of the same vector
00675   ovector_base_tlate(ovector_base_tlate &v)
00676     : ovector_const_view_tlate<data_t,vparent_t,block_t>() {
00677       vparent_t::block=0;
00678       vparent_t::data=v.data;
00679       vparent_t::size=v.size();
00680       vparent_t::stride=v.stride();
00681       vparent_t::owner=0;      
00682     }
00683     
00684     /// Shallow copy constructor - create a new view of the same vector
00685     ovector_base_tlate& operator=(ovector_base_tlate &v) {
00686       vparent_t::block=0;
00687       vparent_t::data=v.data;
00688       vparent_t::size=v.size();
00689       vparent_t::stride=v.stride();
00690       vparent_t::owner=0;      
00691 
00692       return *this;
00693     }
00694 
00695     //@}
00696 
00697     ~ovector_base_tlate() {};
00698 
00699     /// \name Get and set methods
00700     //@{
00701     /** \brief Array-like indexing 
00702     */
00703     const data_t &operator[](size_t i) const {
00704 #if O2SCL_NO_RANGE_CHECK
00705 #else
00706       if (i>=vparent_t::size) {
00707         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00708                    +" in ovector_base_tlate::operator[]. Size: "+
00709                    itos(vparent_t::size)+
00710                    " (index should be less than size).").c_str(),gsl_eindex);
00711         return vparent_t::data[0];
00712       }
00713 #endif
00714       return vparent_t::data[i*vparent_t::stride];
00715     }
00716     
00717     /** \brief Array-like indexing with operator()
00718     */
00719     const data_t &operator()(size_t i) const {
00720 #if O2SCL_NO_RANGE_CHECK
00721 #else
00722       if (i>=vparent_t::size) {
00723         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00724                    +" in ovector_base_tlate::operator(). Size: "+
00725                    itos(vparent_t::size)+
00726                    " (index should be less than size).").c_str(),gsl_eindex);
00727         return vparent_t::data[0];
00728       }
00729 #endif
00730       return vparent_t::data[i*vparent_t::stride];
00731     }
00732 
00733     /** \brief Array-like indexing 
00734     */
00735     data_t &operator[](size_t i) {
00736 #if O2SCL_NO_RANGE_CHECK
00737 #else
00738       if (i>=vparent_t::size) {
00739         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00740                    +" in ovector_base_tlate::operator[]. Size: "+
00741                    itos(vparent_t::size)+
00742                    " (index should be less than size).").c_str(),gsl_eindex);
00743         return vparent_t::data[0];
00744       }
00745 #endif
00746       return vparent_t::data[i*vparent_t::stride];
00747     }
00748     
00749     /** \brief Array-like indexing with operator()
00750     */
00751     data_t &operator()(size_t i) {
00752 #if O2SCL_NO_RANGE_CHECK
00753 #else
00754       if (i>=vparent_t::size) {
00755         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00756                    +" in ovector_base_tlate::operator(). Size: "+
00757                    itos(vparent_t::size)+
00758                    " (index should be less than size).").c_str(),gsl_eindex);
00759         return vparent_t::data[0];
00760       }
00761 #endif
00762       return vparent_t::data[i*vparent_t::stride];
00763     }
00764     
00765     /** \brief Get pointer (with optional range-checking) */
00766     data_t *get_ptr(size_t i) {
00767 #if O2SCL_NO_RANGE_CHECK
00768 #else
00769       if (i>=vparent_t::size) {
00770         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00771                    +" in ovector_base_tlate::get_ptr(). Size: "+
00772                    itos(vparent_t::size)+
00773                    " (index should be less than size).").c_str(),gsl_eindex);
00774         return vparent_t::data;
00775       }
00776 #endif
00777       return vparent_t::data+i*vparent_t::stride;
00778     }
00779     
00780     /** \brief Set (with optional range-checking) */
00781     int set(size_t i, data_t val) {
00782 #if O2SCL_NO_RANGE_CHECK
00783 #else
00784       if (i>=vparent_t::size) {
00785         O2SCL_ERR_RET((((std::string)"Array index ")+itos(i)+" out of bounds"
00786                        +" in ovector_base_tlate::set(). Size: "+
00787                        itos(vparent_t::size)+
00788                        " (index should be less than size).").c_str(),
00789                       gsl_eindex);
00790       }
00791 #endif
00792       vparent_t::data[i*vparent_t::stride]=val;
00793       return 0;
00794     }
00795 
00796     /** \brief Set all of the value to be the value \c val 
00797 
00798         If the vector is empty, this function does not perform
00799         any assignment and does not call the error handler.
00800     */
00801     int set_all(data_t val) {
00802       for(size_t i=0;i<vparent_t::size;i++) {
00803         vparent_t::data[i*vparent_t::stride]=val;
00804       }
00805       return 0;
00806     }
00807     //@}
00808 
00809     /** \name Arithmetic */
00810     //@{
00811     /** \brief operator+= 
00812           
00813         This operator only operates on elements which are present
00814         in both vectors, i.e. elements which are present in one vector
00815         but missing in the other will be ignored. If one of the
00816         two vectors is empty, this function does nothing and
00817         does not call the error handler.
00818     */
00819     ovector_base_tlate<data_t,vparent_t,block_t> &operator+=
00820       (const ovector_base_tlate<data_t,vparent_t,block_t> &x) {
00821       size_t lsize=x.size();
00822       if (lsize>this->size()) lsize=this->size();
00823       for(size_t i=0;i<lsize;i++) (*this)[i]+=x[i];
00824       
00825       return *this;
00826     }
00827     
00828     /** \brief operator-= 
00829         
00830         This operator only operates on elements which are present
00831         in both vectors, i.e. elements which are present in one vector
00832         but missing in the other will be ignored. If one of the
00833         two vectors is empty, this function does nothing and
00834         does not call the error handler.
00835     */
00836     ovector_base_tlate<data_t,vparent_t,block_t> &operator-=
00837       (const ovector_base_tlate<data_t,vparent_t,block_t> &x) {
00838       size_t lsize=x.size();
00839       if (lsize>this->size()) lsize=this->size();
00840       for(size_t i=0;i<lsize;i++) (*this)[i]-=x[i];
00841       
00842       return *this;
00843     }
00844 
00845     /** \brief operator+= 
00846 
00847         If the vector is empty, this function does not perform
00848         any modifications and does not call the error handler.
00849     */
00850     ovector_base_tlate<data_t,vparent_t,block_t> &operator+=(const data_t &x) {
00851       for(size_t i=0;i<this->size();i++) (*this)[i]+=x;
00852       return *this;
00853     }
00854     
00855     /** \brief operator-= 
00856 
00857         If the vector is empty, this function does not perform
00858         any modifications and does not call the error handler.
00859     */
00860     ovector_base_tlate<data_t,vparent_t,block_t> &operator-=(const data_t &x) {
00861       for(size_t i=0;i<this->size();i++) (*this)[i]-=x;
00862       return *this;
00863     }
00864     
00865     /** \brief operator*= 
00866 
00867         If the vector is empty, this function does not perform
00868         any modifications and does not call the error handler.
00869     */
00870     ovector_base_tlate<data_t,vparent_t,block_t> &operator*=
00871       (const data_t &y) {
00872       for(size_t i=0;i<this->size();i++) (*this)[i]*=y;
00873         
00874       return *this;
00875     }
00876     //@}
00877     
00878     /// \name Other methods
00879     //@{
00880     /** \brief Return a gsl vector */
00881     vparent_t *get_gsl_vector() { return this; };
00882 
00883     /** \brief Return a \c const gsl vector 
00884      */
00885     const vparent_t *get_gsl_vector_const() const { return this; };
00886     //@}
00887 
00888   protected:
00889 
00890     /** \brief Empty constructor for use by children
00891 
00892         \comment
00893         This is private because I want to prevent the casual end-user
00894         from creating ovector_base objects. End-users should really be
00895         focused on making normal vectors and views.
00896         \endcomment
00897     */
00898     ovector_base_tlate() {};
00899 
00900   };
00901   
00902   /** \brief A vector view with finite stride
00903   */
00904   template<class data_t, class vparent_t, class block_t> 
00905     class ovector_view_tlate : 
00906   public ovector_base_tlate<data_t,vparent_t,block_t> {
00907     
00908   public:
00909 
00910     /// \name Copy constructors
00911     //@{
00912     /// Shallow copy constructor - create a new view of the same vector
00913   ovector_view_tlate(const ovector_view_tlate &v) :
00914     ovector_base_tlate<data_t,vparent_t,block_t>() {
00915       vparent_t::block=0;
00916       vparent_t::data=v.data;
00917       vparent_t::size=v.size();
00918       vparent_t::stride=v.stride();
00919       vparent_t::owner=0;      
00920     }
00921       
00922     /// Shallow copy constructor - create a new view of the same vector
00923     ovector_view_tlate& operator=
00924       (const ovector_view_tlate &v) {
00925       vparent_t::block=0;
00926       vparent_t::data=v.data;
00927       vparent_t::size=v.size();
00928       vparent_t::stride=v.stride();
00929       vparent_t::owner=0;      
00930       
00931       return *this;
00932     }
00933     
00934     /// Shallow copy constructor for non-views
00935   ovector_view_tlate(ovector_base_tlate<data_t,vparent_t,block_t> &v) :
00936     ovector_base_tlate<data_t,vparent_t,block_t>() {
00937       vparent_t::block=0;
00938       vparent_t::data=v.data;
00939       vparent_t::size=v.size();
00940       vparent_t::stride=v.stride();
00941       vparent_t::owner=0;      
00942     }
00943     
00944     /// Shallow copy constructor for non-views
00945     ovector_view_tlate& operator=
00946       (ovector_base_tlate<data_t,vparent_t,block_t> &v) {
00947       vparent_t::block=0;
00948       vparent_t::data=v.data;
00949       vparent_t::size=v.size();
00950       vparent_t::stride=v.stride();
00951       vparent_t::owner=0;      
00952       
00953       return *this;
00954     }
00955     
00956     /// Shallow copy constructor for unit-stride vectors
00957     ovector_view_tlate
00958       (uvector_base_tlate<data_t> &v) {
00959       vparent_t::block=0;
00960       vparent_t::data=v.data;
00961       vparent_t::size=v.size();
00962       vparent_t::stride=1;
00963       vparent_t::owner=0;      
00964     }
00965     
00966     /// Shallow copy constructor for unit-stride vectors
00967     ovector_view_tlate& operator=
00968       (uvector_base_tlate<data_t> &v) {
00969       vparent_t::block=0;
00970       vparent_t::data=v.data;
00971       vparent_t::size=v.size();
00972       vparent_t::stride=1;
00973       vparent_t::owner=0;      
00974       
00975       return *this;
00976     }
00977     //@}
00978 
00979     /** \name Get and set methods
00980 
00981         \comment
00982         We have to redefine these here because they are different than
00983         the forms given in ovector_base. 
00984         \endcomment
00985     */
00986     //@{
00987     /** \brief Array-like indexing 
00988     */
00989     data_t &operator[](size_t i) const {
00990 #if O2SCL_NO_RANGE_CHECK
00991 #else
00992       if (i>=vparent_t::size) {
00993         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
00994                    +" in ovector_view_tlate::operator[]. Size: "+
00995                    itos(vparent_t::size)+
00996                    " (index should be less than size).").c_str(),gsl_eindex);
00997         return vparent_t::data[0];
00998       }
00999 #endif
01000       return vparent_t::data[i*vparent_t::stride];
01001     }
01002     
01003     /** \brief Array-like indexing with operator()
01004     */
01005     data_t &operator()(size_t i) const {
01006 #if O2SCL_NO_RANGE_CHECK
01007 #else
01008       if (i>=vparent_t::size) {
01009         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
01010                    +" in ovector_view_tlate::operator(). Size: "+
01011                    itos(vparent_t::size)+
01012                    " (index should be less than size).").c_str(),gsl_eindex);
01013         return vparent_t::data[0];
01014       }
01015 #endif
01016       return vparent_t::data[i*vparent_t::stride];
01017     }
01018 
01019     
01020     /** \brief Get pointer (with optional range-checking) */
01021     data_t *get_ptr(size_t i) const {
01022 #if O2SCL_NO_RANGE_CHECK
01023 #else
01024       if (i>=vparent_t::size) {
01025         O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds"
01026                    +" in ovector_view_tlate::get_ptr(). Size: "+
01027                    itos(vparent_t::size)+
01028                    " (index should be less than size).").c_str(),gsl_eindex);
01029         return vparent_t::data;
01030       }
01031 #endif
01032       return vparent_t::data+i*vparent_t::stride;
01033     }
01034     
01035     /** \brief Set (with optional range-checking) */
01036     int set(size_t i, data_t val) const {
01037 #if O2SCL_NO_RANGE_CHECK
01038 #else
01039       if (i>=vparent_t::size) {
01040         O2SCL_ERR_RET((((std::string)"Array index ")+itos(i)+" out of bounds"
01041                        +" in ovector_view_tlate::set(). Size: "+
01042                        itos(vparent_t::size)+
01043                        " (index should be less than size).").c_str(),
01044                       gsl_eindex);
01045       }
01046 #endif
01047       vparent_t::data[i*vparent_t::stride]=val;
01048       return 0;
01049     }
01050 
01051     /** \brief Set all of the value to be the value \c val 
01052 
01053         If the vector is empty, this function does not perform
01054         any assignment and does not call the error handler.
01055     */
01056     int set_all(double val) const {
01057       for(size_t i=0;i<vparent_t::size;i++) {
01058         vparent_t::data[i*vparent_t::stride]=val;
01059       }
01060       return 0;
01061     }
01062     //@}
01063     
01064 #ifndef DOXYGEN_INTERNAL
01065 
01066   protected:
01067 
01068     /** \brief Empty constructor provided for use by 
01069         ovector_view_tlate(const ovector_view_tlate &v)
01070     */
01071     ovector_view_tlate() {};
01072 
01073 #endif
01074 
01075   };
01076 
01077   /** \brief A vector with finite stride
01078 
01079       There are several global binary operators associated with
01080       objects of type \ref uvector_tlate. The are documented in the
01081       "Functions" section of \ref ovector_tlate.h.
01082       
01083       <b>Design notes</b>
01084 
01085       At present, the owner variable can be used to distinguish
01086       between ovectors and ovector_views: for views, owner is always
01087       zero, but for normal ovectors, owner is 1 (even for empty
01088       vectors).
01089 
01090       The reserve(), pop_back(), and push_back() methods require the
01091       ability to have empty vectors which still have memory allocated
01092       for them, so the proper test for whether or not memory is
01093       allocated is to test whether or not 'block' is zero. This means
01094       we should never have a case where the block is non-zero (i.e.
01095       there is memory allocated there) but the size of the block is
01096       zero. This is the test used in the destructor and the free()
01097       method. The free method also sets block to zero accordingly.
01098 
01099   */
01100   template<class data_t, class vparent_t, class block_t> 
01101     class ovector_tlate : 
01102   public ovector_base_tlate<data_t,vparent_t,block_t> {
01103 
01104 #ifndef DOXYGEN_INTERNAL
01105 
01106   protected:
01107     
01108     /// An internal sanity check to ensure correctness
01109     void intl_sanity_check(size_t ix) {
01110       if (vparent_t::owner==0 || (vparent_t::block==0 && vparent_t::size>0) ||
01111           (vparent_t::block!=0 && (vparent_t::block->size==0 || 
01112                                    vparent_t::size>vparent_t::block->size))) {
01113         std::cout << "owner: " << vparent_t::owner 
01114                   << " block: " << vparent_t::block 
01115                   << " size: " << vparent_t::size 
01116                   << " bsize: " << vparent_t::block->size << " "
01117                   << ix << std::endl;
01118         O2SCL_ERR("Internal error in ovector_tlate.",gsl_esanity);
01119       }
01120       return;
01121     }
01122 
01123     /** \brief An internal allocate function
01124 
01125         \note This function does nothing if \c nsize is zero. Also,
01126         this does not free any already allocated memory first (unlike
01127         the user-interface version allocate()).
01128     */
01129     int intl_allocate(size_t nsize) {
01130       
01131 #if O2SCL_NO_RANGE_CHECK
01132 #else
01133       intl_sanity_check(0);
01134 #endif
01135       
01136       if (nsize>0) {
01137         vparent_t::block=(block_t *)malloc(sizeof(block_t));
01138         if (vparent_t::block) {
01139           vparent_t::block->data=(data_t *)malloc(nsize*sizeof(data_t));
01140           if (vparent_t::block->data) {
01141             vparent_t::block->size=nsize;
01142             vparent_t::data=vparent_t::block->data;
01143             vparent_t::size=nsize;
01144             vparent_t::stride=1;
01145             vparent_t::owner=1;
01146           } else {
01147             std::free(vparent_t::block);
01148             // If the block allocation failed, make sure to 
01149             // return block to zero so that destructors know
01150             // that memory has not been allocated
01151             vparent_t::block=0;
01152             O2SCL_ERR_RET("No memory for data in ovector::allocate()",
01153                           gsl_enomem);
01154           }
01155         } else {
01156           O2SCL_ERR_RET("No memory for block in ovector::allocate()",
01157                         gsl_enomem);
01158         }
01159       }
01160 
01161 #if O2SCL_NO_RANGE_CHECK
01162 #else
01163       intl_sanity_check(1);
01164 #endif
01165 
01166       return 0;
01167     }
01168 
01169     /// The internal free function
01170     int intl_free() {
01171 
01172 #if O2SCL_NO_RANGE_CHECK
01173 #else
01174       intl_sanity_check(2);
01175 #endif
01176 
01177       if (vparent_t::block!=0 && vparent_t::block->size>0) {
01178         std::free(vparent_t::block->data);
01179         vparent_t::block->data=0;
01180         std::free(vparent_t::block);
01181         vparent_t::block=0;
01182       }
01183       vparent_t::size=0;
01184       vparent_t::stride=0;
01185       return 0;
01186     }
01187 
01188 
01189     /** \brief An internal init() function
01190         
01191         This function calls intl_allocate() first, and then copies the
01192         data from the vector \c v.
01193     */
01194     template<class alt_vec_t> int intl_init(size_t n, alt_vec_t &v) {
01195       
01196       int ret=intl_allocate(n);
01197       if (ret==0) {
01198         for(size_t i=0;i<n;i++) {
01199           vparent_t::data[i*vparent_t::stride]=v[i];
01200         }
01201       }
01202       
01203       return ret;
01204     }
01205 
01206     /// An internal assignment function for <tt>operator=()</tt>
01207     template<class alt_vec_t> ovector_tlate &intl_assign
01208       (size_t n, alt_vec_t &v) {
01209 
01210 #if O2SCL_NO_RANGE_CHECK
01211 #else
01212       intl_sanity_check(3);
01213 #endif
01214       
01215       // Check for self-assignment
01216       if (this==&v) return *this;
01217       
01218       allocate(n);
01219       for(size_t i=0;i<n;i++) {
01220         vparent_t::data[i*vparent_t::stride]=v[i];
01221       }
01222       
01223       return *this;
01224     }
01225 
01226 #endif    
01227 
01228   public:
01229     
01230     /// \name Standard constructor
01231     //@{
01232     /** \brief Create an ovector of size \c n with owner as 'true' */
01233     ovector_tlate(size_t n=0) {
01234       
01235       // Start with an empty vector (Avoid uninitialized variable errors.)
01236       vparent_t::data=0;
01237       vparent_t::size=0;
01238       vparent_t::stride=0;
01239       vparent_t::block=0;
01240       vparent_t::owner=1;
01241 
01242       if (n>0) intl_allocate(n);
01243 
01244     }
01245     //@}
01246     
01247     /// \name Copy constructors
01248     //@{
01249     /** \brief Deep copy constructor
01250 
01251         \comment
01252         Note I think this has to be separate from the constructor
01253         for ovector_base_tlate objects otherwise the compiler will
01254         synthesize its own.
01255         \endcomment
01256     */
01257   ovector_tlate(const ovector_tlate &v) :
01258     ovector_base_tlate<data_t,vparent_t,block_t>() {
01259       
01260       // Start with an empty vector (Avoid uninitialized variable errors.)
01261       vparent_t::data=0;
01262       vparent_t::size=0;
01263       vparent_t::stride=0;
01264       vparent_t::block=0;
01265       vparent_t::owner=1;
01266 
01267       intl_init(v.size(),v);
01268 
01269     }
01270 
01271     /// Deep copy constructor for generic vectors
01272     template<class alt_vec_t>
01273       ovector_tlate(size_t nv, alt_vec_t &v) : 
01274     ovector_base_tlate<data_t,vparent_t,block_t>() {
01275       
01276       // Start with an empty vector (Avoid uninitialized variable errors.)
01277       vparent_t::data=0;
01278       vparent_t::size=0;
01279       vparent_t::stride=0;
01280       vparent_t::block=0;
01281       vparent_t::owner=1;
01282 
01283       intl_init(nv,v);
01284 
01285     }
01286 
01287     /// Deep copy constructor for other related vectors
01288   ovector_tlate(const ovector_const_view_tlate<data_t,vparent_t,block_t> &v) : 
01289     ovector_base_tlate<data_t,vparent_t,block_t>() {
01290       
01291       // Start with an empty vector (Avoid uninitialized variable errors.)
01292       vparent_t::data=0;
01293       vparent_t::size=0;
01294       vparent_t::stride=0;
01295       vparent_t::block=0;
01296       vparent_t::owner=1;
01297 
01298       intl_init(v.size(),v);
01299 
01300     }
01301 
01302     /** \brief Deep copy constructor, if owner is true, allocate
01303         space and make a new copy, otherwise, just copy into the
01304         view
01305     */
01306     ovector_tlate& operator=(const ovector_tlate &v) {
01307       
01308       return intl_assign(v.size(),v);
01309     }
01310 
01311     /** \brief Deep copy constructor, if owner is true, allocate
01312         space and make a new copy, otherwise, just copy into the
01313         view
01314     */
01315     ovector_tlate& operator=
01316       (const ovector_const_view_tlate<data_t,vparent_t,block_t> &v) {
01317       
01318       return intl_assign(v.size(),v);
01319     }
01320 
01321     /** \brief Deep copy constructor, if owner is true, allocate
01322         space and make a new copy, otherwise, just copy into the
01323         view
01324     */
01325     ovector_tlate& operator=
01326       (const uvector_const_view_tlate<data_t> &v) {
01327 
01328       return intl_assign(v.size(),v);
01329     }
01330     //@}
01331 
01332     ~ovector_tlate() {
01333 
01334 #if O2SCL_NO_RANGE_CHECK
01335 #else
01336       intl_sanity_check(4);
01337 #endif
01338 
01339       if (vparent_t::owner==1) {
01340         if (vparent_t::block!=0 && vparent_t::block->size>0) {
01341           std::free(vparent_t::block->data);
01342         }
01343         if (vparent_t::block!=0) {
01344           std::free(vparent_t::block);
01345         }
01346       }
01347       
01348     }
01349     
01350     /// \name Memory allocation
01351     //@{
01352     /** \brief Allocate memory for size \c n after freeing any memory
01353         currently in use
01354 
01355         Note that this automatically deallocates any previously
01356         allocated memory before attempting to allocate more. If this
01357         allocation fails (i.e. because we ran out of memory) then the
01358         original vector will still have been deallocated.
01359     */
01360     int allocate(size_t nsize) {
01361 
01362       intl_free();
01363       intl_allocate(nsize);
01364 
01365       return 0;
01366     }
01367 
01368     /** \brief Free the memory 
01369         
01370         This function will safely do nothing if used without first
01371         allocating memory or if called multiple times in succession.
01372     */
01373     int free() {
01374       return intl_free();
01375     }
01376     //@}
01377 
01378     /// \name Stack-like operations
01379     //@{
01380 
01381     /// Add a value to the end of the vector
01382     int push_back(data_t val) {
01383 
01384 #if O2SCL_NO_RANGE_CHECK
01385 #else
01386       intl_sanity_check(6);
01387 #endif
01388 
01389       if (vparent_t::block==0) {
01390         
01391         // Empty, so make a 1-element vector
01392         allocate(1);
01393         vparent_t::data[0]=val;
01394           
01395       } else if (vparent_t::block->size==vparent_t::size) {
01396           
01397         // Allocate new memory in vparent_t::block
01398         vparent_t::block->data=(data_t *)malloc
01399           (2*vparent_t::block->size*sizeof(data_t));
01400         vparent_t::block->size*=2;
01401                 
01402         // Copy the data to the new memory
01403         for(size_t i=0;i<vparent_t::size;i++) {
01404           vparent_t::block->data[i]=vparent_t::data[i];
01405         }
01406           
01407         // Delete the old memory
01408         std::free(vparent_t::data);
01409           
01410         // Reset data to the new memory
01411         vparent_t::data=vparent_t::block->data;
01412 
01413         // Add the new value to the end of the array and 
01414         // increment size
01415         vparent_t::block->data[vparent_t::size]=val;
01416         vparent_t::size++;
01417 
01418       } else {
01419 
01420         // Add the new value to the end of the array and 
01421         // increment size
01422         vparent_t::block->data[vparent_t::size]=val;
01423         vparent_t::size++;
01424 
01425       }
01426 
01427 #if O2SCL_NO_RANGE_CHECK
01428 #else
01429       intl_sanity_check(7);
01430 #endif
01431 
01432       return 0;
01433     }
01434 
01435     /** \brief Reserve memory by increasing capacity
01436     
01437         Increase the maximum capacity of the vector so that calls
01438         to push_back() do not need to automatically increase the
01439         capacity.
01440 
01441         If the argument \c cap is smaller than the present vector size
01442         given by \ref size(), then this function does nothing and the
01443         error handler is not called.
01444     */
01445     int reserve(size_t cap) {
01446             
01447 #if O2SCL_NO_RANGE_CHECK
01448 #else
01449       intl_sanity_check(8);
01450 #endif
01451 
01452       // Do nothing if we are reserving memory for less than the
01453       // current size
01454               
01455       if (cap>vparent_t::size) {
01456 
01457         bool initially_empty=false;
01458 
01459         // If it's initially_empty, we need to allocate a block
01460         if (!vparent_t::block) {
01461           initially_empty=true;
01462           vparent_t::block=(block_t *)malloc(sizeof(block_t));
01463         }
01464 
01465         // If it's empty, or if the block size is too small,
01466         // reserve space. On the other hand, if the block size
01467         // is already large enough, do nothing.
01468         if (initially_empty || vparent_t::block->size<cap) {
01469 
01470           // Allocate new memory in vparent_t::block
01471           vparent_t::block->data=(data_t *)malloc(cap*sizeof(data_t));
01472           vparent_t::block->size=cap;
01473           
01474           // Copy the data to the new memory
01475           for(size_t i=0;i<vparent_t::size;i++) {
01476             vparent_t::block->data[i]=vparent_t::data[i];
01477           }
01478           
01479           // Delete the old memory
01480           if (!initially_empty) {
01481             std::free(vparent_t::data);
01482           }
01483           
01484           // Reset data to the new memory
01485           vparent_t::data=vparent_t::block->data;
01486         }
01487       }
01488 
01489 #if O2SCL_NO_RANGE_CHECK
01490 #else
01491       intl_sanity_check(9);
01492 #endif
01493 
01494       return 0;
01495     }
01496 
01497     /** \brief Return the last value and shrink the vector size by one
01498     */
01499     data_t pop_back() {
01500 
01501 #if O2SCL_NO_RANGE_CHECK
01502 #else
01503       intl_sanity_check(10);
01504 #endif
01505 
01506       if (vparent_t::size==0) {
01507         O2SCL_ERR("Attempted to pop an empty vector in ovector::pop_back().",
01508                   gsl_einval);
01509         return 0.0;
01510       }
01511 
01512       // Otherwise, just decrease the size by one and return the last
01513       // element
01514       vparent_t::size--;
01515 
01516 #if O2SCL_NO_RANGE_CHECK
01517 #else
01518       intl_sanity_check(11);
01519 #endif
01520 
01521       return vparent_t::data[vparent_t::size];
01522     }
01523     //@}
01524 
01525     /// \name Other methods
01526     //@{
01527     /// Remove element with index \c ix and decrease the vector size by one
01528     int erase(size_t ix) {
01529 
01530 #if O2SCL_NO_RANGE_CHECK
01531 #else
01532       intl_sanity_check(12);
01533 #endif
01534 
01535       if (ix<vparent_t::size) {
01536         for(size_t i=ix+1;i<vparent_t::size;i++) {
01537           vparent_t::data[i-1]=vparent_t::data[i];
01538         }
01539         vparent_t::size--;
01540       } else {
01541         O2SCL_ERR_RET("Tried to erase() past end in ovector_tlate::erase().",
01542                       gsl_einval);
01543       }
01544 
01545 #if O2SCL_NO_RANGE_CHECK
01546 #else
01547       intl_sanity_check(13);
01548 #endif
01549 
01550       return 0;
01551     }
01552     
01553     /** \brief Sort the vector and ensure all elements are unique by 
01554         removing duplicates
01555     */
01556     int sort_unique() {
01557 
01558 #if O2SCL_NO_RANGE_CHECK
01559 #else
01560       intl_sanity_check(14);
01561 #endif
01562       
01563       o2scl::vector_sort<ovector_tlate<data_t,vparent_t,block_t>,data_t >
01564         (vparent_t::size,*this);
01565       for(size_t i=1;i<vparent_t::size;i++) {
01566         if ((*this)[i]==(*this)[i-1]) {
01567           int ret=erase(i-1);
01568           if (ret!=0) {
01569             O2SCL_ERR2_RET("Erase failed in ",
01570                            "ovector_tlate::sort_unique().",gsl_esanity);
01571           }
01572           i--;
01573         }
01574       }
01575 
01576 #if O2SCL_NO_RANGE_CHECK
01577 #else
01578       intl_sanity_check(15);
01579 #endif
01580 
01581       return 0;
01582     }
01583     //@}
01584     
01585   };
01586 
01587   /** \brief Create a vector from an array 
01588   */
01589   template<class data_t, class vparent_t, class block_t> 
01590     class ovector_array_tlate : 
01591   public ovector_view_tlate<data_t,vparent_t,block_t> {
01592 
01593   public:
01594 
01595     /** \brief Create a vector from \c dat with size \c n */
01596     ovector_array_tlate(size_t n, data_t *dat) {
01597       vparent_t::block=0;
01598       vparent_t::owner=0;
01599       if (n>0) {
01600         vparent_t::data=dat;
01601         vparent_t::size=n;
01602         vparent_t::stride=1;
01603       } else {
01604         vparent_t::data=0;
01605         vparent_t::size=0;
01606         vparent_t::stride=0;
01607       }
01608     }
01609 
01610   };
01611 
01612   /** \brief Create a vector from an array with a stride
01613   */
01614   template<class data_t, class vparent_t, class block_t> 
01615     class ovector_array_stride_tlate : 
01616   public ovector_view_tlate<data_t,vparent_t,block_t> {
01617 
01618   public:
01619 
01620     /** \brief Create a vector from \c dat with size \c n and stride \c s 
01621      */
01622     ovector_array_stride_tlate(size_t n, data_t *dat, size_t s) {
01623       vparent_t::block=0;
01624       vparent_t::owner=0;
01625       if (n>0) {
01626         vparent_t::data=dat;
01627         vparent_t::size=n;
01628         vparent_t::stride=s;
01629       } else {
01630         vparent_t::data=0;
01631         vparent_t::size=0;
01632         vparent_t::stride=0;
01633       }
01634     }
01635 
01636   };
01637 
01638   /** \brief Create a vector from a subvector of another
01639 
01640       The constructor will fail if the original vector is empty, or if
01641       the user requests a subvector which includes elements beyond the
01642       end of the original vector.
01643   */
01644   template<class data_t, class vparent_t, class block_t> 
01645     class ovector_subvector_tlate : 
01646   public ovector_view_tlate<data_t,vparent_t,block_t> {
01647   public:
01648     /** \brief Create a vector from \c orig 
01649      */
01650     ovector_subvector_tlate
01651       (ovector_base_tlate<data_t,vparent_t,block_t> &orig, 
01652        size_t offset, size_t n) {
01653       if (orig.size()>0 && offset+n<orig.size()+1) {
01654         vparent_t::block=0;
01655         vparent_t::data=orig.data+offset*orig.stride();
01656         vparent_t::size=n;
01657         vparent_t::stride=orig.stride();
01658         vparent_t::owner=0;
01659       } else {
01660         std::string err="Failed because vector is of size "+
01661           itos(orig.size())+" but requested size "+itos(n)+
01662           " with offset "+itos(offset)+" in ovector_subvector "+
01663           "constructor.";
01664         O2SCL_ERR(err.c_str(),gsl_efailed);
01665         vparent_t::block=0;
01666         vparent_t::data=0;
01667         vparent_t::size=0;
01668         vparent_t::stride=0;
01669         vparent_t::owner=0;
01670       }
01671     }
01672   };
01673 
01674   /** \brief Create a const vector from an array 
01675 
01676       The constructor will fail if the size argument 
01677       \c n is zero or if the pointer \c dat is 0.
01678   */
01679   template<class data_t, class vparent_t, class block_t> 
01680     class ovector_const_array_tlate :
01681   public ovector_const_view_tlate<data_t,vparent_t,block_t> {
01682 
01683   public:
01684 
01685     /** \brief Create a vector from \c dat with size \c n */
01686     ovector_const_array_tlate(size_t n, const data_t *dat) {
01687       if (n>0 && dat!=0) {
01688         vparent_t::block=0;
01689         // We have to do an explicit cast here, but we prevent the
01690         // user from changing the data.
01691         vparent_t::data=(data_t *)dat;
01692         vparent_t::size=n;
01693         vparent_t::stride=1;
01694         vparent_t::owner=0;
01695       } else {
01696         O2SCL_ERR2("Empty array in ovector_const_array_tlate() ",
01697                    "constructor.",gsl_efailed);
01698         vparent_t::block=0;
01699         vparent_t::data=0;
01700         vparent_t::size=0;
01701         vparent_t::stride=0;
01702         vparent_t::owner=0;
01703       }
01704     }
01705     
01706     ~ovector_const_array_tlate() {};
01707     
01708   };
01709 
01710   /** \brief Create a const vector from an array with a stride 
01711 
01712       The constructor will fail if the size argument \c n is zero, the
01713       stride \c s is zero, or if the pointer \c dat is 0.
01714   */
01715   template<class data_t, class vparent_t, class block_t> 
01716     class ovector_const_array_stride_tlate : 
01717   public ovector_const_view_tlate<data_t,vparent_t,block_t> {
01718 
01719   public:
01720 
01721     /** \brief Create a vector from \c dat with size \c n */
01722     ovector_const_array_stride_tlate(size_t n, const data_t *dat, size_t s) {
01723       if (n>0 && s>0 && dat!=0) {
01724         vparent_t::block=0;
01725         // We have to do an explicit cast here, but we prevent the
01726         // user from changing the data.
01727         vparent_t::data=(data_t *)dat;
01728         vparent_t::size=n;
01729         vparent_t::stride=s;
01730         vparent_t::owner=0;
01731       } else {
01732         O2SCL_ERR2("Empty array in ovector_const_array_stride_tlate() ",
01733                    "constructor.",gsl_efailed);
01734         vparent_t::block=0;
01735         vparent_t::data=0;
01736         vparent_t::size=0;
01737         vparent_t::stride=0;
01738         vparent_t::owner=0;
01739       }
01740     }
01741 
01742   };
01743 
01744   /** \brief Create a const vector from a subvector of another vector
01745   */
01746   template<class data_t, class vparent_t, class block_t> 
01747     class ovector_const_subvector_tlate :
01748   public ovector_const_view_tlate<data_t,vparent_t,block_t> {
01749   public:
01750     /** \brief Create a vector from \c orig 
01751      */
01752     ovector_const_subvector_tlate
01753       (const ovector_const_view_tlate<data_t,vparent_t,block_t> &orig, 
01754        size_t offset, size_t n) {
01755       if (offset+n-1<orig.size()) {
01756         vparent_t::block=0;
01757         vparent_t::data=orig.data+offset*orig.stride();
01758         vparent_t::size=n;
01759         vparent_t::stride=orig.stride();
01760         vparent_t::owner=0;
01761       } else {
01762         std::string err="Failed because vector is of size "+
01763           itos(orig.size())+" but requested size "+itos(n)+
01764           " with offset "+itos(offset)+" in ovector_const_subvector "+
01765           "constructor.";
01766         O2SCL_ERR(err.c_str(),gsl_efailed);
01767         vparent_t::block=0;
01768         vparent_t::data=0;
01769         vparent_t::size=0;
01770         vparent_t::stride=0;
01771         vparent_t::owner=0;
01772       }
01773     }
01774 
01775   };
01776 
01777   /// ovector typedef
01778   typedef ovector_tlate<double,gsl_vector_norm,gsl_block> ovector;
01779   /// ovector_base typedef
01780   typedef ovector_base_tlate<double,gsl_vector_norm,gsl_block> 
01781     ovector_base;
01782   /// ovector_view typedef
01783   typedef ovector_view_tlate<double,gsl_vector_norm,gsl_block> 
01784     ovector_view;
01785   /// ovector_const_view typedef
01786   typedef ovector_const_view_tlate<double,gsl_vector_norm,gsl_block> 
01787     ovector_const_view;
01788   /// ovector_array typedef
01789   typedef ovector_array_tlate<double,gsl_vector_norm,gsl_block> ovector_array;
01790   /// ovector_array_stride typedef
01791   typedef ovector_array_stride_tlate<double,gsl_vector_norm,gsl_block> 
01792     ovector_array_stride;
01793   /// ovector_subvector typedef
01794   typedef ovector_subvector_tlate<double,gsl_vector_norm,gsl_block> 
01795     ovector_subvector;
01796   /// ovector_const_array typedef
01797   typedef ovector_const_array_tlate<double,gsl_vector_norm,gsl_block> 
01798     ovector_const_array;
01799   /// ovector_const_array_stride typedef
01800   typedef ovector_const_array_stride_tlate<double,gsl_vector_norm,gsl_block> 
01801     ovector_const_array_stride;
01802   /// ovector_const_subvector typedef
01803   typedef ovector_const_subvector_tlate<double,gsl_vector_norm,gsl_block> 
01804     ovector_const_subvector;
01805 
01806   /// ovector_int typedef
01807   typedef ovector_tlate<int,gsl_vector_int,gsl_block_int> ovector_int;
01808   /// ovector_int_base typedef
01809   typedef ovector_base_tlate<int,gsl_vector_int,gsl_block_int> 
01810     ovector_int_base;
01811   /// ovector_int_view typedef
01812   typedef ovector_view_tlate<int,gsl_vector_int,gsl_block_int> 
01813     ovector_int_view;
01814   /// ovector_int_const_base typedef
01815   typedef ovector_const_view_tlate<int,gsl_vector_int,gsl_block_int> 
01816     ovector_int_const_view;
01817   /// ovector_int_array typedef
01818   typedef ovector_array_tlate<int,gsl_vector_int,gsl_block_int> 
01819     ovector_int_array;
01820   /// ovector_int_array_stride typedef
01821   typedef ovector_array_stride_tlate<int,gsl_vector_int,gsl_block_int> 
01822     ovector_int_array_stride;
01823   /// ovector_int_subvector typedef
01824   typedef ovector_subvector_tlate<int,gsl_vector_int,gsl_block_int> 
01825     ovector_int_subvector;
01826   /// ovector_int_const_array typedef
01827   typedef ovector_const_array_tlate<int,gsl_vector_int,gsl_block_int> 
01828     ovector_int_const_array;
01829   /// ovector_int_const_array_stride typedef
01830   typedef ovector_const_array_stride_tlate<int,gsl_vector_int,gsl_block_int> 
01831     ovector_int_const_array_stride;
01832   /// ovector_int_const_subvector typedef
01833   typedef ovector_const_subvector_tlate<int,gsl_vector_int,gsl_block_int> 
01834     ovector_int_const_subvector;
01835 
01836   /** \brief A operator for naive vector output
01837 
01838       This outputs all of the vector elements. All of these are
01839       separated by one space character, though no trailing space or \c
01840       endl is sent to the output. If the vector is empty, nothing
01841       is done.
01842   */
01843   template<class data_t, class vparent_t, class block_t> 
01844     std::ostream &operator<<
01845     (std::ostream &os, 
01846      const ovector_const_view_tlate<data_t,vparent_t,block_t> &v) {
01847     if (v.size()>0) {
01848       for(size_t i=0;i<v.size()-1;i++) {
01849         os << v[i] << ' ';
01850       }
01851       os << v[v.size()-1];
01852     }
01853     return os;
01854   }
01855   
01856   /** \brief A simple class to provide an \c allocate() function
01857       for \ref ovector
01858 
01859       \future Could (or should?) the allocate() functions be adapted to
01860       return an integer error value?
01861   */
01862   class ovector_alloc {
01863   public:
01864     /// Allocate \c v for \c i elements
01865     void allocate(ovector &o, size_t i) { o.allocate(i); }
01866     /// Free memory
01867     void free(ovector &o) { o.free(); }
01868   };
01869 
01870   /** \brief A simple class to provide an \c allocate() function
01871       for \ref ovector_int
01872   */
01873   class ovector_int_alloc {
01874   public:
01875     /// Allocate \c v for \c i elements
01876     void allocate(ovector_int &o, size_t i) { o.allocate(i); }
01877     /// Free memory
01878     void free(ovector_int &o) { o.free(); }
01879   };
01880 
01881   /** \brief A vector where the memory allocation is performed in 
01882       the constructor
01883 
01884       This can be useful, for example to easily make C-style arrays of
01885       \ref ovector objects with a fixed size. For example,
01886       \code
01887       ofvector<8> x[10];
01888       \endcode
01889       would mean <tt>x</tt> is a 10-dimensional array of 
01890       \ref ovector object with initial length 8.
01891 
01892       \future Consider making allocate() and free() functions
01893       private for this class?
01894   */
01895 #ifdef DOXYGENP
01896   template<size_t N=0> class ofvector : 
01897   public ovector_tlate
01898 #else
01899     template<size_t N=0> class ofvector : 
01900   public ovector_tlate<double,gsl_vector,gsl_block>
01901 #endif
01902     {
01903     public:
01904     ofvector() : ovector_tlate<double,gsl_vector,gsl_block>(N) {
01905       }
01906     };
01907   
01908 #ifndef DOXYGENP
01909 }
01910 #endif
01911 
01912 #endif
01913 
 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.