Object-oriented Scientific Computing Library: Version 0.910
vector.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_VECTOR_H
00024 #define O2SCL_VECTOR_H
00025 
00026 /** \file vector.h
00027     \brief File for generic vector functions
00028 
00029     This file contains a set of template functions which can be
00030     applied to almost any vector or matrix type which allow element
00031     access through <tt>operator[]</tt>. Detailed requirements
00032     on the template parameters are given in the functions below. 
00033 
00034     For a general discussion of vectors and matrices in \o2, see the
00035     \ref vecmat_section of the User's Guide.
00036 
00037     For overloaded arithmetic operators involving vectors and
00038     matrices, see \ref vec_arith.h . For statistics operations not
00039     included here, see \ref vec_stats.h in the directory \c src/other
00040     . For assorted functions and classes which are specific to C-style
00041     arrays, see \ref array.h . Also related are the matrix output
00042     functions, \ref matrix_out(), \ref matrix_cx_out_paren(), and \ref
00043     matrix_out_paren() which are defined in \ref columnify.h because
00044     they utilize the class \ref columnify to format the output.
00045 
00046     For functions which search for a value in an ordered (either
00047     increasing or decreasing) vector, see the class \ref search_vec .
00048 
00049     \future Create a matrix transpose copy function?
00050     \future Create matrix swap row and column functions
00051 */
00052 #include <iostream>
00053 #include <cmath>
00054 #include <string>
00055 #include <fstream>
00056 #include <sstream>
00057 #include <o2scl/err_hnd.h>
00058 #include <o2scl/uniform_grid.h>
00059 #include <gsl/gsl_ieee_utils.h>
00060 #include <gsl/gsl_sort.h>
00061 
00062 #ifndef DOXYGENP
00063 namespace o2scl {
00064 #endif
00065 
00066   /// \name Copying functions
00067   //@{
00068   /** \brief Simple vector copy
00069 
00070       \note This ordering is reversed from the GSL function
00071       <tt>gsl_vector_memcpy()</tt>. This is to be used with
00072       \code
00073       vector_copy(N,source,destination);
00074       \endcode
00075       instead of
00076       \code
00077       gsl_vector_memcpy(destination,source);
00078       \endcode
00079 
00080       It is assumed that the memory allocation for \c dest
00081       has already been performed.
00082 
00083       This function will work for any class <tt>vec2_t</tt> which has
00084       an operator[] which returns a reference to the corresponding
00085       element and class <tt>vec_t</tt> with an operator[] which
00086       returns either a reference or the value of the corresponding
00087       element.
00088   */
00089   template<class vec_t, class vec2_t> 
00090     void vector_copy(size_t N, vec_t &src, vec2_t &dest) {
00091     size_t i, m=N%4;
00092     for(i=0;i<m;i++) {
00093       dest[i]=src[i];
00094     }
00095     for(i=m;i+3<N;i+=4) {
00096       dest[i]=src[i];
00097       dest[i+1]=src[i+1];
00098       dest[i+2]=src[i+2];
00099       dest[i+3]=src[i+3];
00100     }
00101     return;
00102   }
00103 
00104   /** \brief Generic vector swap
00105 
00106       This function swaps the elements of \c v1 and \c v2, one element
00107       at a time.
00108    */
00109   template<class vec_t, class vec2_t, class base_t> 
00110     void vector_swap(size_t N, vec_t &v1, vec2_t &v2) {
00111     base_t temp;
00112     size_t i, m=N%4;
00113     for(i=0;i<m;i++) {
00114       temp=v1[i];
00115       v1[i]=v2[i];
00116       v2[i]=temp;
00117     }
00118     for(i=m;i+3<N;i+=4) {
00119       temp=v1[i];
00120       v1[i]=v2[i];
00121       v2[i]=temp;
00122       temp=v1[i+1];
00123       v1[i+1]=v2[i+1];
00124       v2[i+1]=temp;
00125       temp=v1[i+2];
00126       v1[i+2]=v2[i+2];
00127       v2[i+2]=temp;
00128       temp=v1[i+3];
00129       v1[i+3]=v2[i+3];
00130       v2[i+3]=temp;
00131     }
00132     return;
00133   }
00134   
00135   /** \brief Simple matrix copy
00136 
00137       \note This ordering is reversed from the GSL function
00138       <tt>gsl_matrix_memcpy()</tt>. This is to be used with
00139       \code
00140       matrix_copy(N,source,destination);
00141       \endcode
00142       instead of
00143       \code
00144       gsl_matrix_memcpy(destination,source);
00145       \endcode
00146 
00147       It is assumed that the memory allocation for \c dest
00148       has already been performed.
00149 
00150       This function will work for any class <tt>vec2_t</tt> which has
00151       an operator[][] which returns a reference to the corresponding
00152       element and class <tt>vec_t</tt> with an operator[][] which
00153       returns either a reference or the value of the corresponding
00154       element.
00155   */
00156   template<class mat_t, class mat2_t> 
00157     void matrix_copy(size_t M, size_t N, mat_t &src, mat2_t &dest) {
00158     for(size_t i=0;i<M;i++) {
00159       for(size_t j=0;j<N;j++) {
00160         dest[i][j]=src[i][j];
00161       }
00162     }
00163   }
00164 
00165   /** \brief GSL complex vector copy
00166 
00167       \future At present this works only with complex types based 
00168       directly on the GSL complex format. This could be improved.
00169   */
00170   template<class vec_t, class vec2_t> 
00171     void vector_cx_copy_gsl(size_t N, vec_t &src, vec2_t &dest) {
00172     for(size_t i=0;i<N;i++) {
00173       dest[i].dat[0]=src[i].dat[0];
00174       dest[i].dat[1]=src[i].dat[1];
00175     }
00176   }
00177   
00178   /** \brief GSL complex matrix copy
00179 
00180       \future At present this works only with complex types based 
00181       directly on the GSL complex format. This could be improved.
00182   */
00183   template<class mat_t, class mat2_t> 
00184     void matrix_cx_copy_gsl(size_t M, size_t N, mat_t &src, mat2_t &dest) {
00185     for(size_t i=0;i<M;i++) {
00186       for(size_t j=0;j<N;j++) {
00187         dest[i][j].dat[0]=src[i][j].dat[0];
00188         dest[i][j].dat[1]=src[i][j].dat[1];
00189       }
00190     }
00191   }
00192   //@}
00193 
00194   /// \name Sorting functions
00195   //@{
00196   /** \brief Provide a downheap() function for vector_sort()
00197   */
00198   template<class vec_t, class data_t>
00199     void sort_downheap(vec_t &data, size_t n, size_t k) {
00200     
00201     data_t v=data[k];
00202     
00203     while (k<=n/2) {
00204       size_t j=2*k;
00205       
00206       if (j<n && data[j] < data[j+1]) j++;
00207       if (!(v < data[j])) break;
00208       data[k]=data[j];
00209       k=j;
00210     }
00211     
00212     data[k]=v;
00213   }
00214 
00215   /** \brief Sort a vector (in increasing order)
00216 
00217       This is a generic sorting template function using a heapsort
00218       algorithm. It will work for any types \c data_t and \c vec_t for
00219       which
00220       - \c data_t has a non-const version of <tt>operator=</tt>
00221       - \c data_t has a less than operator to compare elements
00222       - <tt>vec_t::operator[]</tt> returns a non-const reference
00223       to an object of type \c data_t 
00224       
00225       In particular, it will work with \ref ovector, \ref uvector, 
00226       \ref ovector_int, \ref uvector_int (and other related \o2
00227       vector classes), the STL template class <tt>std::vector</tt>,
00228       and arrays and pointers of numeric, character, and string
00229       objects.
00230 
00231       For example,
00232       \code
00233       std::string list[3]={"dog","cat","fox"};
00234       vector_sort<std::string[3],std::string>(3,list);
00235       \endcode
00236 
00237       \note With this function template alone, the user cannot avoid
00238       explicitly specifying the template types for this function
00239       because there is no parameter of type \c data_t, and function
00240       templates cannot handle default template types. For this
00241       reason, the function template \ref vector_sort_double() was
00242       also created which provides the convenience of not requiring
00243       the user to specify the vector template type.
00244 
00245       \note This sorting routine is not stable, i.e. equal elements
00246       have arbtrary final ordering
00247 
00248       This works similarly to the GSL function <tt>gsl_sort_vector()</tt>.
00249   */
00250   template<class vec_t, class data_t>
00251     int vector_sort(size_t n, vec_t &data) {
00252     
00253     size_t N;
00254     size_t k;
00255     
00256     if (n==0) return 0;
00257     
00258     N=n-1;
00259     k=N/2;
00260     k++;
00261     do {
00262       k--;
00263       sort_downheap<vec_t,data_t>(data,N,k);
00264     } while (k > 0);
00265     
00266     while (N > 0) {
00267       data_t tmp=data[0];
00268       data[0]=data[N];
00269       data[N]=tmp;
00270       N--;
00271       sort_downheap<vec_t,data_t>(data,N,0);
00272     }
00273     
00274     return 0;
00275   }
00276 
00277   /** \brief Provide a downheap() function for vector_sort_index()
00278    */
00279   template<class vec_t, class vec_size_t> 
00280     int sort_index_downheap(size_t N, const vec_t &data, vec_size_t &order,
00281                             size_t k) {
00282 
00283     const size_t pki = order[k];
00284     
00285     while (k <= N / 2) {
00286       size_t j = 2 * k;
00287       
00288       if (j < N && data[order[j]] < data[order[j + 1]]) {
00289         j++;
00290       }
00291       
00292       // avoid infinite loop if nan
00293       if (!(data[pki] < data[order[j]])) {
00294         break;
00295       }
00296       
00297       order[k] = order[j];
00298       
00299       k = j;
00300     }
00301     
00302     order[k] = pki;
00303     
00304     return 0;
00305   }
00306 
00307   /** \brief Create a permutation which sorts a vector (in increasing order)
00308 
00309       This function takes a vector \c data and arranges a list of
00310       indices in \c order, which give a sorted version of the vector.
00311       The value <tt>order[i]</tt> gives the index of entry in in \c
00312       data which corresponds to the <tt>i</tt>th value in the sorted
00313       vector. The vector \c data is unchanged by this function, and
00314       the initial values in \c order are ignored. Before calling this
00315       function, \c order must already be allocated as a vector of size
00316       \c n.
00317 
00318       For example, after calling this function, a sorted version the
00319       vector can be output with
00320       \code
00321       size_t n=5;
00322       double data[5]={3.1,4.1,5.9,2.6,3.5};
00323       permutation order(n);
00324       vector_sort_index(n,data,order);
00325       for(size_t i=0;i<n;i++) {
00326         cout << data[order[i]] << endl;
00327       }
00328       \endcode
00329 
00330       To create a permutation which stores as its <tt>i</tt>th element,
00331       the index of <tt>data[i]</tt> in the sorted vector, you can
00332       invert the permutation created by this function.
00333 
00334       This is a generic sorting template function. It will work for
00335       any types \c vec_t and \c vec_size_t for which
00336       - \c vec_t has an <tt>operator[]</tt>, and
00337       - \c vec_size_t has an <tt>operator[]</tt> which returns 
00338       a \c size_t .
00339       One possible type for \c vec_size_t is \ref permutation.
00340 
00341       This works similarly to the GSL function <tt>gsl_sort_index()</tt>.
00342   */
00343   template<class vec_t, class vec_size_t> 
00344     int vector_sort_index(size_t n, const vec_t &data, vec_size_t &order) {
00345     size_t N;
00346     size_t i, k;
00347     
00348     if (n == 0) return 0;
00349 
00350     // set permutation to identity
00351 
00352     for (i = 0 ; i < n ; i++) {
00353       order[i] = i ;
00354     }
00355     
00356     /* We have n_data elements, last element is at 'n_data-1', first
00357        at '0' Set N to the last element number.
00358     */
00359     N = n - 1;
00360     
00361     k = N / 2;
00362     // Compensate the first use of 'k--'
00363     k++;                          
00364     do {
00365       k--;
00366       sort_index_downheap<vec_t,vec_size_t>(N,data,order,k);
00367     } while (k > 0);
00368     
00369     
00370     while (N > 0) {
00371       
00372       // first swap the elements 
00373       size_t tmp = order[0];
00374       order[0] = order[N];
00375       order[N] = tmp;
00376       
00377       // then process the heap
00378       N--;
00379       
00380       sort_index_downheap<vec_t,vec_size_t>(N,data,order,0);
00381     }
00382 
00383     return 0;
00384   }
00385 
00386   /** \brief Sort a vector of doubles (in increasing order)
00387 
00388       This function is just a wrapper for
00389       \code
00390       vector_sort<vec_t,double>(n,data);
00391       \endcode
00392       See the documentation of \ref vector_sort() for more 
00393       details.
00394   */
00395   template<class vec_t>
00396     int vector_sort_double(size_t n, vec_t &data) {
00397     return vector_sort<vec_t,double>(n,data);
00398   }
00399   //@}
00400   
00401   /// \name Smallest and largest functions
00402   //@{
00403   /** \brief Find the k smallest entries of a vector
00404 
00405       Given a vector \c data of size \c n this sets the first \c k
00406       entries of the vector \c smallest to the k smallest entries from
00407       vector \c data in ascending order. The vector \c smallest must
00408       be allocated beforehand to hold at least \c k elements.
00409 
00410       This works similarly to the GSL function <tt>gsl_sort_smallest()</tt>.
00411 
00412       \note This \f$ {\cal O}(k N) \f$ algorithm is useful only when 
00413       \f$ k << N \f$.
00414 
00415       If \c k is zero, then this function does nothing and
00416       returns \ref gsl_success .
00417    */
00418   template<class vec_t, class data_t>
00419     int vector_smallest(size_t n, vec_t &data, size_t k, vec_t &smallest) {
00420     if (k>n) {
00421       O2SCL_ERR2_RET("Subset length greater than size in ",
00422                      "function vector_smallest().",gsl_einval);
00423     }
00424     if (k==0 || n==0) return gsl_success;
00425 
00426     // Take the first element
00427     size_t j=1;
00428     data_t xbound=data[0];
00429     smallest[0]=xbound;
00430 
00431     // Examine the remaining elements
00432     for(size_t i=1;i<n;i++) {
00433       data_t xi=data[i];
00434       if (j<k) {
00435         j++;
00436       } else if (xi>=xbound) {
00437         continue;
00438       }
00439       size_t i1;
00440       for(i1=j-1;i1>0;i1--) {
00441         if (xi>smallest[i1-1]) break;
00442         smallest[i1]=smallest[i1-1];
00443       }
00444       smallest[i1]=xi;
00445       xbound=smallest[j-1];
00446     }
00447     return 0;
00448   }
00449 
00450   /** \brief Find the k largest entries of a vector
00451 
00452       Given a vector \c data of size \c n this sets the first \c k
00453       entries of the vector \c largest to the k largest entries from
00454       vector \c data in descending order. The vector \c largest must
00455       be allocated beforehand to hold at least \c k elements.
00456 
00457       This works similarly to the GSL function <tt>gsl_sort_largest()</tt>.
00458 
00459       \note This \f$ {\cal O}(k N) \f$ algorithm is useful only when 
00460       \f$ k << N \f$.
00461 
00462       If \c k is zero, then this function does nothing and
00463       returns \ref gsl_success .
00464    */
00465   template<class vec_t, class data_t>
00466     int vector_largest(size_t n, vec_t &data, size_t k, vec_t &largest) {
00467     if (k>n) {
00468       O2SCL_ERR2_RET("Subset length greater than size in ",
00469                      "function vector_largest().",gsl_einval);
00470     }
00471     if (k==0 || n==0) return gsl_success;
00472 
00473     // Take the first element
00474     size_t j=1;
00475     data_t xbound=data[0];
00476     largest[0]=xbound;
00477 
00478     // Examine the remaining elements
00479     for(size_t i=1;i<n;i++) {
00480       data_t xi=data[i];
00481       if (j<k) {
00482         j++;
00483       } else if (xi<=xbound) {
00484         continue;
00485       }
00486       size_t i1;
00487       for(i1=j-1;i1>0;i1--) {
00488         if (xi<largest[i1-1]) break;
00489         largest[i1]=largest[i1-1];
00490       }
00491       largest[i1]=xi;
00492       xbound=largest[j-1];
00493     }
00494     return 0;
00495   }
00496   //@}
00497 
00498   /// \name Vector minimum and maximum functions
00499   //@{
00500   /** \brief Compute the maximum of the first \c n elements of a vector
00501    */
00502   template<class vec_t, class data_t>
00503     data_t vector_max_value(size_t n, const vec_t &data) {
00504     
00505     if (n==0) {
00506       O2SCL_ERR_RET("Sent size=0 to vector_max_value().",gsl_efailed);
00507     }
00508     data_t max=data[0];
00509     for(size_t i=1;i<n;i++) {
00510       if (data[i]>max) {
00511         max=data[i];
00512       }
00513     }
00514     return max;
00515   }
00516 
00517   /** \brief Compute the index which holds the 
00518       maximum of the first \c n elements of a vector
00519    */
00520   template<class vec_t, class data_t>
00521     size_t vector_max_index(size_t n, const vec_t &data) {
00522     
00523     if (n==0) {
00524       O2SCL_ERR_RET("Sent size=0 to vector_max_index().",gsl_efailed);
00525     }
00526     data_t max=data[0];
00527     size_t ix=0;
00528     for(size_t i=1;i<n;i++) {
00529       if (data[i]>max) {
00530         max=data[i];
00531         ix=i;
00532       }
00533     }
00534     return ix;
00535   }
00536 
00537   /** \brief Compute the maximum of the first \c n elements of a vector
00538    */
00539   template<class vec_t, class data_t>
00540     void vector_max(size_t n, const vec_t &data, size_t &index, 
00541                     data_t &val) {
00542     
00543     if (n==0) {
00544       O2SCL_ERR_RET("Sent size=0 to vector_max().",gsl_efailed);
00545     }
00546     val=data[0];
00547     index=0;
00548     for(size_t i=1;i<n;i++) {
00549       if (data[i]>val) {
00550         val=data[i];
00551         index=i;
00552       }
00553     }
00554     return index;
00555   }
00556 
00557   /** \brief Compute the minimum of the first \c n elements of a vector
00558    */
00559   template<class vec_t, class data_t>
00560     data_t vector_min_value(size_t n, const vec_t &data) {
00561     
00562     if (n==0) {
00563       O2SCL_ERR_RET("Sent size=0 to vector_min_value().",gsl_efailed);
00564     }
00565     data_t min=data[0];
00566     for(size_t i=1;i<n;i++) {
00567       if (data[i]<min) {
00568         min=data[i];
00569       }
00570     }
00571     return min;
00572   }
00573 
00574   /** \brief Compute the index which holds the 
00575       minimum of the first \c n elements of a vector
00576    */
00577   template<class vec_t, class data_t>
00578     size_t vector_min_index(size_t n, const vec_t &data) {
00579     
00580     if (n==0) {
00581       O2SCL_ERR_RET("Sent size=0 to vector_min_index().",gsl_efailed);
00582     }
00583     data_t min=data[0];
00584     size_t ix=0;
00585     for(size_t i=1;i<n;i++) {
00586       if (data[i]<min) {
00587         min=data[i];
00588         ix=i;
00589       }
00590     }
00591     return ix;
00592   }
00593 
00594   /** \brief Compute the minimum of the first \c n elements of a vector
00595    */
00596   template<class vec_t, class data_t>
00597     void vector_min(size_t n, const vec_t &data, size_t &index, 
00598                     data_t &val) {
00599     
00600     if (n==0) {
00601       O2SCL_ERR("Sent size=0 to vector_min().",gsl_efailed);
00602     }
00603     val=data[0];
00604     index=0;
00605     for(size_t i=1;i<n;i++) {
00606       if (data[i]<val) {
00607         val=data[i];
00608         index=i;
00609       }
00610     }
00611     return;
00612   }
00613 
00614   /** \brief Compute the minimum and maximum of the first 
00615       \c n elements of a vector
00616   */
00617   template<class vec_t, class data_t>
00618     void vector_minmax_value(size_t n, vec_t &data, 
00619                             data_t &min, data_t &max) {
00620     
00621     if (n==0) {
00622       O2SCL_ERR("Sent size=0 to vector_min().",gsl_efailed);
00623     }
00624     min=data[0];
00625     max=min;
00626     for(size_t i=1;i<n;i++) {
00627       if (data[i]<min) {
00628         min=data[i];
00629       }
00630       if (data[i]>max) {
00631         max=data[i];
00632       }
00633     }
00634     return;
00635   }
00636 
00637   /** \brief Compute the minimum and maximum of the first 
00638       \c n elements of a vector
00639   */
00640   template<class vec_t, class data_t>
00641     void vector_minmax_index(size_t n, vec_t &data, 
00642                              size_t &ix_min, size_t &ix_max) {
00643     
00644     if (n==0) {
00645       O2SCL_ERR("Sent size=0 to vector_min().",gsl_efailed);
00646     }
00647     data_t min=data[0];
00648     data_t max=min;
00649     ix_min=0;
00650     ix_max=0;
00651     for(size_t i=1;i<n;i++) {
00652       if (data[i]<min) {
00653         min=data[i];
00654         ix_min=i;
00655       }
00656       if (data[i]>max) {
00657         max=data[i];
00658         ix_max=i;
00659       }
00660     }
00661     return;
00662   }
00663 
00664   /** \brief Compute the minimum and maximum of the first 
00665       \c n elements of a vector
00666   */
00667   template<class vec_t, class data_t>
00668     void vector_minmax(size_t n, vec_t &data, 
00669                       size_t &ix_min, data_t &min, 
00670                       size_t &ix_max, data_t &max) {
00671     
00672     if (n==0) {
00673       O2SCL_ERR("Sent size=0 to vector_min().",gsl_efailed);
00674     }
00675     min=data[0];
00676     max=min;
00677     ix_min=0;
00678     ix_max=0;
00679     for(size_t i=1;i<n;i++) {
00680       if (data[i]<min) {
00681         min=data[i];
00682         ix_min=i;
00683       }
00684       if (data[i]>max) {
00685         max=data[i];
00686         ix_max=i;
00687       }
00688     }
00689     return;
00690   }
00691   //@}
00692 
00693   /// \name Matrix minimum and maximum functions
00694   //@{
00695   /** \brief Compute the maximum of a matrix
00696 
00697       \future Write matrix_max_index() and related functions similar
00698       to the way vector_max_index() works.
00699    */
00700   template<class mat_t, class data_t>
00701     data_t matrix_max(size_t n, const size_t m, const mat_t &data) {
00702     
00703     if (n==0 || m==0) {
00704       O2SCL_ERR_RET("Sent size=0 to matrix_max().",gsl_efailed);
00705     }
00706     data_t max=data[0][0];
00707     for(size_t i=0;i<n;i++) {
00708       for(size_t j=0;j<m;j++) {
00709         if (data[i][j]>max) {
00710           max=data[i][j];
00711         }
00712       }
00713     }
00714     return max;
00715   }
00716 
00717   /** \brief Compute the minimum of a matrix
00718    */
00719   template<class mat_t, class data_t>
00720     data_t matrix_min(size_t n, const size_t m, const mat_t &data) {
00721     
00722     if (n==0 || m==0) {
00723       O2SCL_ERR_RET("Sent size=0 to matrix_min().",gsl_efailed);
00724     }
00725     data_t min=data[0][0];
00726     for(size_t i=0;i<n;i++) {
00727       for(size_t j=0;j<m;j++) {
00728         if (data[i][j]<min) {
00729           min=data[i][j];
00730         }
00731       }
00732     }
00733     return min;
00734   }
00735 
00736   /** \brief Compute the minimum and maximum of a matrix
00737    */
00738   template<class mat_t, class data_t>
00739     int matrix_minmax(size_t n, const size_t m, const mat_t &data,
00740                       data_t &min, data_t &max) {
00741     
00742     if (n==0 || m==0) {
00743       O2SCL_ERR_RET("Sent size=0 to matrix_min().",gsl_efailed);
00744     }
00745     min=data[0][0];
00746     max=data[0][0];
00747     for(size_t i=0;i<n;i++) {
00748       for(size_t j=0;j<m;j++) {
00749         if (data[i][j]<min) {
00750           min=data[i][j];
00751         } else if (data[i][j]>max) {
00752           max=data[i][j];
00753         }
00754       }
00755     }
00756     return 0;
00757   }
00758   //@}
00759 
00760   /** \brief Create a vector-like class from a row of a matrix
00761     
00762       \comment
00763       This class isn't used in o2scl at present, but we
00764       keep it here for posterity for now.
00765       \endcomment
00766   
00767       \future Generalize to operator(,)
00768   */
00769   template <class mat_t> class matrix_row {
00770 
00771 #ifndef DOXYGEN_INTERNAL
00772 
00773   protected:
00774 
00775     /// The row index
00776     size_t r2;
00777 
00778     /// The pointer to the matrix
00779     mat_t *m2;
00780 
00781 #endif
00782 
00783   public:
00784 
00785     /// Create an object which represents row \c r of matrix \c m
00786     matrix_row(mat_t &m, size_t r) {
00787       r2=r;
00788       m2=&m;
00789     }
00790 
00791     /// Access element of column \c c from the specified row
00792     double &operator[](size_t c) {
00793       return (*m2)[r2][c];
00794     }
00795 
00796     /// Access element of column \c c from the specified row
00797     const double &operator[](size_t c) const {
00798       return (*m2)[r2][c];
00799     }
00800 
00801   };
00802 
00803   /// \name Searching functions
00804   //@{
00805   /** \brief Lookup element \c x0 in vector \c x of length \c n
00806 
00807       This function finds the element in vector \c x which is closest
00808       to \c x0. It ignores all elements in \c x which are not finite.
00809       If the vector is empty (i.e. \c n is zero), or if all of the
00810       elements in \c x are not finite, then the error handler will be
00811       called.
00812 
00813       This function works for all classes \c vec_t where an operator[]
00814       is defined which returns a double (either as a value or a
00815       reference).
00816 
00817       \future Write matrix_lookup().
00818    */
00819   template<class vec_t>
00820     size_t vector_lookup(size_t n, const vec_t &x, double x0) {
00821     if (n==0) {
00822       O2SCL_ERR("Empty vector in vector_lookup().",
00823                 gsl_einval);
00824       return 0;
00825     }
00826     size_t row=0, i=0;
00827     while(!finite(x[i]) && i<n-1) i++;
00828     if (i==n-1) {
00829       O2SCL_ERR2("Entire vector not finite in ",
00830                  "vector_lookup()",gsl_einval);
00831       return 0;
00832     }
00833     double best=x[i], bdiff=fabs(x[i]-x0);
00834     for(;i<n;i++) {
00835       if (finite(x[i]) && fabs(x[i]-x0)<bdiff) {
00836         row=i;
00837         best=x[i];
00838         bdiff=fabs(x[i]-x0);
00839       }
00840     }
00841     return row;
00842   }
00843 
00844   /** \brief Binary search a part of an increasing vector for
00845       <tt>x0</tt>.
00846       
00847       This function performs a binary search of between
00848       <tt>x[lo]</tt> and <tt>x[hi]</tt>. It returns 
00849       - \c lo if \c x0 < <tt>x[lo]</tt>
00850       - \c i if <tt>x[i]</tt> <= \c x0 < <tt>x[i+2]</tt> 
00851       for \c lo <= \c i < \c hi
00852       - \c hi-1 if \c x0 >= \c <tt>x[hi-1]</tt>
00853 
00854       The element at <tt>x[hi]</tt> is never referenced by this
00855       function. The parameter \c hi can be either the index of the
00856       last element (e.g. <tt>n-1</tt> for a vector of size <tt>n</tt>
00857       with starting index <tt>0</tt>), or the index of one element
00858       (e.g. <tt>n</tt> for a vector of size <tt>n</tt> and a starting
00859       index <tt>0</tt>) for a depending on whether or not the user
00860       wants to allow the function to return the index of the last
00861       element.
00862 
00863       This function operates in the same way as
00864       <tt>gsl_interp_bsearch()</tt>.
00865 
00866       The operation of this function is undefined if the data is
00867       not strictly monotonic, i.e. if some of the data elements are 
00868       equal.
00869 
00870       This function will call the error handler if \c lo is
00871       greater than \c hi.
00872   */
00873   template<class vec_t, class data_t> 
00874     size_t vector_bsearch_inc(const data_t x0, const vec_t &x,
00875                               size_t lo, size_t hi) {
00876     if (lo>hi) {
00877       O2SCL_ERR2("Low and high indexes backwards in ",
00878                  "vector_bsearch_inc().",gsl_einval);
00879     }
00880     while (hi>lo+1) {
00881       size_t i=(hi+lo)/2;
00882       if (x[i]>x0) {
00883         hi=i;
00884       } else {
00885         lo=i;
00886       }
00887     }
00888     
00889     return lo;
00890   }
00891 
00892   /** \brief Binary search a part of an decreasing vector for
00893       <tt>x0</tt>.
00894       
00895       This function performs a binary search of between
00896       <tt>x[lo]</tt> and <tt>x[hi]</tt> (inclusive). It returns 
00897       - \c lo if \c x0 > <tt>x[lo]</tt>
00898       - \c i if <tt>x[i]</tt> >= \c x0 > <tt>x[i+1]</tt> 
00899       for \c lo <= \c i < \c hi
00900       - \c hi-1 if \c x0 <= \c <tt>x[hi-1]</tt>
00901     
00902       The element at <tt>x[hi]</tt> is never referenced by this
00903       function. The parameter \c hi can be either the index of the
00904       last element (e.g. <tt>n-1</tt> for a vector of size <tt>n</tt>
00905       with starting index <tt>0</tt>), or the index of one element
00906       (e.g. <tt>n</tt> for a vector of size <tt>n</tt> and a starting
00907       index <tt>0</tt>) for a depending on whether or not the user
00908       wants to allow the function to return the index of the last
00909       element.
00910 
00911       The operation of this function is undefined if the data is
00912       not strictly monotonic, i.e. if some of the data elements are 
00913       equal.
00914       
00915       This function will call the error handler if \c lo is
00916       greater than \c hi.
00917   */
00918   template<class vec_t, class data_t> 
00919     size_t vector_bsearch_dec(const data_t x0, const vec_t &x,
00920                               size_t lo, size_t hi) {
00921     if (lo>hi) {
00922       O2SCL_ERR2("Low and high indexes backwards in ",
00923                  "vector_bsearch_dec().",gsl_einval);
00924     }
00925     while (hi>lo+1) {
00926       size_t i=(hi+lo)/2;
00927       if (x[i]<x0) {
00928         hi=i;
00929       } else {
00930         lo=i;
00931       }
00932     }
00933     
00934     return lo;
00935   }
00936 
00937   /** \brief Binary search a part of a monotonic vector for
00938       <tt>x0</tt>.
00939 
00940       This wrapper just calls \ref vector_bsearch_inc() or
00941       \ref vector_bsearch_dec() depending on the ordering
00942       of \c x. 
00943   */
00944   template<class vec_t, class data_t> 
00945     size_t vector_bsearch(const data_t x0, const vec_t &x,
00946                           size_t lo, size_t hi) {
00947     if (x[lo]<x[hi-1]) {
00948       return vector_bsearch_inc<vec_t,data_t>(x0,x,lo,hi);
00949     }
00950     return vector_bsearch_dec<vec_t,data_t>(x0,x,lo,hi);
00951   }
00952   //@}
00953 
00954   /// \name Miscellaneous mathematical functions
00955   //@{
00956   /** \brief Compute the sum of the first \c n elements of a vector
00957 
00958       If \c n is zero, this will set \c sum to zero and return 
00959       \ref gsl_success.
00960   */
00961   template<class vec_t, class data_t>
00962     data_t vector_sum(size_t n, vec_t &data) {
00963     
00964     data_t sum=0.0;
00965     for(size_t i=0;i<n;i++) {
00966       sum+=data[i];
00967     }
00968     return sum;
00969   }
00970 
00971   /** \brief Compute the norm of a vector of floating-point 
00972       (single or double precision) numbers
00973 
00974       This function is a more generic version of 
00975       \ref o2scl_cblas::dnrm2 . 
00976   */
00977   template<class vec_t, class data_t>
00978     data_t vector_norm(size_t n, const vec_t &x) {
00979     
00980     data_t scale = 0.0;
00981     data_t ssq = 1.0;
00982     
00983     if (n <= 0) {
00984       return 0.0;
00985     } else if (n == 1) {
00986       return fabs(x[0]);
00987     }
00988       
00989     for (size_t i = 0; i < n; i++) {
00990       const data_t xx = x[i];
00991 
00992       if (xx != 0.0) {
00993         const data_t ax = fabs(xx);
00994           
00995         if (scale < ax) {
00996           ssq = 1.0 + ssq * (scale / ax) * (scale / ax);
00997           scale = ax;
00998         } else {
00999           ssq += (ax / scale) * (ax / scale);
01000         }
01001       }
01002 
01003     }
01004       
01005     return scale * sqrt(ssq);
01006   }
01007   //@}
01008 
01009   /// \name Other functions
01010   //@{
01011   /** \brief "Rotate" a vector so that the kth element is now the beginning
01012 
01013       This is a generic template function which will work for
01014       any types \c data_t and \c vec_t for which
01015       - \c data_t has an <tt>operator=</tt>
01016       - <tt>vec_t::operator[]</tt> returns a reference
01017       to an object of type \c data_t 
01018 
01019       This function is used, for example, in \ref pinside.
01020 
01021       \note This function is not the same as a Givens rotation,
01022       which is typically referred to in BLAS routines as <tt>drot()</tt>.
01023   */
01024   template<class vec_t, class data_t>
01025     int vector_rotate(size_t n, vec_t &data, size_t k) {
01026 
01027     data_t *tmp=new data_t[n];
01028     for(size_t i=0;i<n;i++) {
01029       tmp[i]=data[(i+k)%n];
01030     }
01031     for(size_t i=0;i<n;i++) {
01032       data[i]=tmp[i];
01033     }
01034     delete[] tmp;
01035     
01036     return 0;
01037   }
01038 
01039   /** \brief Reverse a vector
01040 
01041       If \c n is zero, this function will silently do nothing.
01042   */
01043   template<class vec_t, class data_t>
01044     int vector_reverse(size_t n, vec_t &data) {
01045     data_t tmp;
01046 
01047     for(size_t i=0;i<n/2;i++) {
01048       tmp=data[n-1-i];
01049       data[n-1-i]=data[i];
01050       data[i]=tmp;
01051     }
01052     return 0;
01053   }
01054 
01055   /** \brief Output a vector to a stream
01056       
01057       No trailing space is output after the last element, and an
01058       endline is output only if \c endline is set to \c true.  If the
01059       parameter \c n is zero, this function silently does nothing.
01060 
01061       Note that the \o2 vector classes also have their own
01062       \c operator<<() defined for them.
01063 
01064       This works with any class <tt>vec_t</tt> which has an operator[]
01065       which returns either the value of or a reference to the ith
01066       element and the element type has its own output operator which
01067       has been defined.
01068   */
01069   template<class vec_t> 
01070     int vector_out(std::ostream &os, size_t n, const vec_t &v, 
01071                    bool endline=false) {
01072 
01073     // This next line is important since n-1 is not well-defined if n=0
01074     if (n==0) return 0;
01075 
01076     for(size_t i=0;i<n-1;i++) os << v[i] << " ";
01077     os << v[n-1];
01078     if (endline) os << std::endl;
01079     return 0;
01080   }
01081   //@}
01082   
01083   /** \brief Fill a vector with a specified grid
01084    */
01085   template<class vec_t, class data_t>
01086     void vector_grid(uniform_grid<data_t> g, vec_t &v) {
01087     g.template vector<vec_t>(v);
01088     return;
01089   }
01090 
01091   
01092 #ifndef DOXYGENP
01093 }
01094 #endif
01095 
01096 #endif
 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.