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     /** 
00152         \brief Find the interval containing x0 in the ordered array \c x 
00153 
00154         This returns the index i for which x[i]<=x0<x[i+1]. 
00155 
00156         If the array is increasing and x0<x[0], then 0 is returned.
00157         If the array is increasing and x0>x[n-1], then nvar-1 is
00158         returned (this behavior is slightly different from GSL).  The
00159         decreasing case is handled analogously.
00160 
00161         If some of the values in the vector are not finite, then the
00162         output of this function is not defined.
00163 
00164         If x[i] is non-monotonic, consider using
00165         ovector_view_tlate::lookup() or uvector_view_tlate::lookup()
00166         instead of this function.
00167     */
00168     size_t ordered_interval(const double x0, size_t n, const vec_t &x) {
00169       size_t row;
00170       err_hnd->reset();
00171 
00172       if (x[0]<=x[n-1]) {
00173 
00174         // Increasing case
00175 
00176         if (x0>=x[n-1]) row=n-1;
00177         else row=find_inc(x0,n,x);
00178 
00179       } else {
00180         // Decreasing case
00181     
00182         if (x0<=x[n-1]) row=n-1;
00183         else row=find_dec(x0,n,x);
00184       }
00185 
00186       return row;
00187     }
00188 
00189     /** 
00190         \brief Binary search a part of an increasing vector
00191 
00192         The cache is not used for this function.
00193      */
00194     size_t bsearch_inc(const double x0, const vec_t &x,
00195                        size_t lo, size_t hi) const {
00196       while (hi>lo+1) {
00197         size_t i=(hi+lo)/2;
00198         if (x[i]>x0)
00199           hi=i;
00200         else
00201           lo=i;
00202       }
00203   
00204       return lo;
00205     }
00206 
00207     /** 
00208         \brief Binary search a part of an decreasing vector
00209         
00210         The cache is not used for this function.
00211      */
00212     size_t bsearch_dec(const double x0, const vec_t &x,
00213                        size_t lo, size_t hi) const {
00214       while (hi>lo+1) {
00215         size_t i=(hi+lo)/2;
00216         if (x[i]<x0)
00217           hi=i;
00218         else
00219           lo=i;
00220       }
00221   
00222       return lo;
00223     }
00224 
00225   };
00226   
00227 #ifndef DOXYGENP
00228 }
00229 #endif
00230 
00231 #endif

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