search_vec.h

00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006, 2007, 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_SEARCH_VEC_H
00024 #define O2SCL_SEARCH_VEC_H
00025 
00026 #include <iostream>
00027 #include <string>
00028 #include <gsl/gsl_spline.h>
00029 #include <o2scl/err_hnd.h>
00030 #include <o2scl/collection.h>
00031 #include <o2scl/ovector_tlate.h>
00032 /* \file search_vec.h
00033    \brief File for definitions for \ref search_vec
00034 */
00035 
00036 #ifndef DOXYGENP
00037 namespace o2scl {
00038 #endif
00039 
00040   /** 
00041       \brief Searching class for monotonic data
00042 
00043       A searching class for monotonic vectors. A caching system
00044       similar to \c gsl_interp_accel is used.
00045       
00046       For normal usage, just use find(). If you happen to know in
00047       advance that the vector is increasing or decreasing, then you
00048       can use find_inc() or find_dec() instead. 
00049 
00050       \todo The documentation here is still kind of unclear. 
00051   */
00052   template<class vec_t> class search_vec {
00053 
00054 #ifndef DOXYGEN_INTERNAL
00055 
00056   protected:
00057 
00058     /// Storage for the most recent index
00059     size_t cache;
00060 
00061 #endif
00062 
00063   public:
00064 
00065     /** \brief Search an increasing or decreasing vector
00066      */
00067     size_t find(const double x0, size_t n, const vec_t &x) {
00068       if (x[0]<x[n-1]) return find_inc(x0,n,x);
00069       return find_dec(x0,n,x);
00070     }
00071 
00072     /** \brief Search part of a increasing vector
00073      */
00074     size_t find_inc(const double x0, size_t n, const vec_t &x) {
00075       size_t x_index=cache;
00076 
00077       // Make sure the cached value is not outside the array.
00078       if (x_index>n-1) x_index=n/2;
00079   
00080       if (x0<x[x_index]) {
00081         cache=bsearch_inc(x0,x,0,x_index);
00082       } else if (x0>x[x_index+1]) {
00083         cache=bsearch_inc(x0,x,x_index,n-1);
00084       }
00085   
00086       return cache;
00087     }
00088     
00089     /** \brief Search part of a decreasing vector
00090      */
00091     size_t find_dec(const double x0, size_t n, const vec_t &x) {
00092       size_t x_index=cache;
00093       
00094       // Make sure the cached value is not outside the array.
00095       if (x_index>n-1) x_index=n/2;
00096   
00097       if (x0>x[x_index]) {
00098         cache=bsearch_dec(x0,x,0,x_index);
00099       } else if (x0<x[x_index+1]) {
00100         cache=bsearch_dec(x0,x,x_index,n-1);
00101       }
00102   
00103       return cache;
00104     }
00105 
00106     /** 
00107         \brief Find the index of x0 in the ordered array \c x 
00108 
00109         This returns the index i for which x[i] is as close
00110         as possible to x0 if x[i] is either increasing or decreasing.
00111 
00112         If some of the values in the ovector are not finite, then
00113         the output of this function is not defined.
00114 
00115         If x[i] is non-monotonic, consider using
00116         ovector_view_tlate::lookup() or uvector_view_tlate::lookup()
00117         instead of this function.
00118         
00119     */
00120     size_t ordered_lookup(const double x0, size_t n, const vec_t &x) {
00121       size_t row;
00122       err_hnd->reset();
00123 
00124       if (x[0]<=x[n-1]) {
00125 
00126         // Increasing case
00127 
00128         if (x0>=x[n-1]) {
00129           row=n-1;
00130         } else { 
00131           row=find_inc(x0,n,x);
00132           if (row<n-1 && fabs(x[row+1]-x0)<fabs(x[row]-x0)) row++;
00133         }
00134     
00135       } else {
00136 
00137         // Decreasing case
00138     
00139         if (x0<=x[n-1]) {
00140           row=n-1;
00141         } else {
00142           row=find_dec(x0,n,x);
00143           if (row<n-1 && fabs(x[row+1]-x0)<fabs(x[row]-x0)) row++;
00144         }
00145       }
00146 
00147       return row;
00148     }
00149 
00150     /** 
00151         \brief Find the interval containing x0 in the ordered array \c x 
00152 
00153         This returns the index i for which x[i]<=x0<x[i+1]. 
00154 
00155         If the array is increasing and x0<x[0], then 0 is returned.
00156         If the array is increasing and x0>x[n-1], then nvar-1 is
00157         returned (this behavior is slightly different from GSL).  The
00158         decreasing case is handled analogously.
00159 
00160         If some of the values in the vector are not finite, then the
00161         output of this function is not defined.
00162 
00163         If x[i] is non-monotonic, consider using
00164         ovector_view_tlate::lookup() or uvector_view_tlate::lookup()
00165         instead of this function.
00166     */
00167     size_t ordered_interval(const double x0, size_t n, const vec_t &x) {
00168       size_t row;
00169       err_hnd->reset();
00170 
00171       if (x[0]<=x[n-1]) {
00172 
00173         // Increasing case
00174 
00175         if (x0>=x[n-1]) row=n-1;
00176         else row=find_inc(x0,n,x);
00177 
00178       } else {
00179         // Decreasing case
00180     
00181         if (x0<=x[n-1]) row=n-1;
00182         else row=find_dec(x0,n,x);
00183       }
00184 
00185       return row;
00186     }
00187 
00188     /** 
00189         \brief Binary search a part of an increasing vector
00190 
00191         This function performs a binary search of between
00192         <tt>x[lo]</tt> and <tt>x[hi-1]</tt>. It returns 
00193         - \c lo if \c x0 < <tt>x[lo+1]</tt>
00194         - \c i if <tt>x[i]</tt> <= \c x0 < <tt>x[i+1]</tt> 
00195         for \c lo <= \c i < \c hi
00196         - \c hi-1 if \c x0 >= \c <tt>x[hi-1]</tt>
00197     
00198         The cache is not used for this function.
00199      */
00200     size_t bsearch_inc(const double x0, const vec_t &x,
00201                        size_t lo, size_t hi) const {
00202       while (hi>lo+1) {
00203         size_t i=(hi+lo)/2;
00204         if (x[i]>x0) {
00205           hi=i;
00206         } else {
00207           lo=i;
00208         }
00209       }
00210   
00211       return lo;
00212     }
00213 
00214     /** 
00215         \brief Binary search a part of an decreasing vector
00216         
00217         This function performs a binary search of between
00218         <tt>x[lo]</tt> and <tt>x[hi-1]</tt>. It returns 
00219         - \c lo if \c x0 > <tt>x[lo+1]</tt>
00220         - \c i if <tt>x[i]</tt> >= \c x0 > <tt>x[i+1]</tt> 
00221         for \c lo <= \c i < \c hi
00222         - \c hi-1 if \c x0 <= \c <tt>x[hi-1]</tt>
00223     
00224         The cache is not used for this function.
00225      */
00226     size_t bsearch_dec(const double x0, const vec_t &x,
00227                        size_t lo, size_t hi) const {
00228       while (hi>lo+1) {
00229         size_t i=(hi+lo)/2;
00230         if (x[i]<x0) {
00231           hi=i;
00232         } else {
00233           lo=i;
00234         }
00235       }
00236   
00237       return lo;
00238     }
00239 
00240   };
00241   
00242 #ifndef DOXYGENP
00243 }
00244 #endif
00245 
00246 #endif

Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.

Project hosting provided by SourceForge.net Logo, O2scl Sourceforge Project Page