Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

more/num/point_map.h

Go to the documentation of this file.
00001 
00002 //  Copyright (C) 2000--2001  Petter Urkedal (petter.urkedal@matfys.lth.se)
00003 
00004 //  This file is free software; you can redistribute it and/or modify
00005 //  it under the terms of the GNU General Public License as published by
00006 //  the Free Software Foundation; either version 2 of the License, or
00007 //  (at your option) any later version.
00008 
00009 //  This file is distributed in the hope that it will be useful,
00010 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 //  GNU General Public License for more details.
00013 
00014 //  You should have received a copy of the GNU General Public License
00015 //  along with this program; if not, write to the Free Software
00016 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 //  As a special exception, you may use this file as part of a free
00019 //  software library without restriction.  Specifically, if other files
00020 //  instantiate templates or use macros or inline functions from this
00021 //  file, or you compile this file and link it with other files to
00022 //  produce an executable, this file does not by itself cause the
00023 //  resulting executable to be covered by the GNU General Public
00024 //  License.  This exception does not however invalidate any other
00025 //  reasons why the executable file might be covered by the GNU General
00026 //  Public License.
00027 
00028 //  $Id: point_map.h,v 1.1 2002/05/30 18:01:40 petter_urkedal Exp $
00029 
00030 //  Status: experimental
00031 
00032 
00033 #include <limits>
00034 #include <iterator>
00035 #include <map>
00036 #include <more/gen/iterator.h>
00037 #include <more/gen/view.h>
00038 #include <more/gen/utility.h>
00039 #include <more/math/math.h>
00040 #include <more/num/vectin.h>
00041 
00042 #ifndef MORE_POINT_MAP_H
00043 #define MORE_POINT_MAP_H
00044 
00045 
00046 namespace more {
00047 namespace num {
00048 
00049 #ifdef CXX_HAVE_LONG_LONG
00050   typedef unsigned long long pindex_type;
00051 #else
00052   typedef unsigned long pindex_type;
00053 #endif
00054 
00055   template<typename T, int D>
00056     inline pindex_type
00057     fold(more::vectin<T, D> const& x) {
00058         const double scale = ldexp(.49, 8*sizeof(pindex_type)/D);
00059         // since std::numeric_limits<pindex_type>::max() may not work
00060         // for long long.
00061         pindex_type res = 0;
00062         for (int i = 0; i < D; ++i)
00063             res |= more::bitpow((pindex_type)((1.0+x[i])*scale), D) << i;
00064         return res;
00065     }
00066 
00067   template< typename Position, typename Data,
00068             typename Metric = euclidian_metric<Position> >
00069     struct point_map {
00070         // XXX todo: if trunc_cnt/c.size() becomes non-negligible,
00071         // reconstruct the container with a smaller scale.
00072         typedef Position position_type;
00073         typedef Position key_type;
00074         typedef Metric metric_function;
00075         typedef typename metric_function::result_type metric_type;
00076         static const int ndim = Position::CTC_size;
00077         typedef more::pindex_type pindex_type;
00078         typedef Data data_type;
00079         typedef std::pair<Position, Data> value_type;
00080 #if !defined(MORE_BACKWARD) || MORE_BACKWARD >= 20000601
00081       private:
00082 #endif
00083         typedef std::map<pindex_type, value_type> container;
00084         typedef typename container::iterator full_iterator;
00085         typedef typename container::const_iterator full_const_iterator;
00086         typedef typename container::value_type full_value_type;
00087       public:
00088 
00089         struct vicinity_filter
00090             : std::unary_function<full_value_type, bool> {
00091             vicinity_filter() {}
00092             vicinity_filter(position_type const& x_, metric_type d_,
00093                             metric_function const& met)
00094                 : x(x_), d(d_), metric(met) {}
00095             vicinity_filter(vicinity_filter const& flt)
00096                 : x(flt.x), d(flt.d), metric(flt.metric) {}
00097 
00098             bool operator()(full_value_type const& v) {
00099                 return metric(v.second.first, x) <= d;
00100             }
00101 
00102           private:
00103             position_type x;
00104             metric_type d;
00105             metric_function metric;
00106         };
00107 
00108         typedef gen::transform_if_view< full_iterator, vicinity_filter,
00109                                         gen::select2nd<full_value_type> >
00110                 vicinity_view;
00111         typedef gen::transforming_iterator< full_iterator,
00112                                             gen::select2nd<full_value_type> >
00113                 iterator;
00114         typedef gen::transforming_iterator
00115                   < full_const_iterator,
00116                     gen::select2nd<const full_value_type> >
00117                 const_iterator;
00118 
00119         point_map()
00120             : scale(1.0), trunc_cnt(0) {}
00121         point_map(metric_type radius_max)
00122             : scale(1.0/radius_max), trunc_cnt(0) {}
00123 
00124 #if defined (MORE_BACKWARD) && MORE_BACKWARD < 20000601
00125         void insert(position_type const& x, data_type const& y) {
00126             position_type z = scale_and_truncate(x);
00127             c.insert(full_value_type(fold(z), value_type(x, y)));
00128         }
00129 #endif
00130         void insert(value_type const& x) {
00131             position_type z = scale_and_truncate(x.first);
00132             c.insert(full_value_type(fold(z), x));
00133         }
00134 #if defined (MORE_BACKWARD) && MORE_BACKWARD < 20000601
00135         void insert(full_iterator hint,
00136                     position_type const& x, data_type const& y) {
00137             position_type z = scale_and_truncate(x);
00138             c.insert(hint, full_value_type(fold(z), value_type(x, y)));
00139         }
00140 #endif
00141         void insert(iterator hint, value_type const& x) {
00142             position_type z = scale_and_truncate(x);
00143             c.insert(hint.sub_iterator(), full_value_type(fold(z), x));
00144         }
00145 
00146         vicinity_view vicinity(position_type const& x, metric_type d);
00147         iterator find_closest(position_type const& x);
00148 
00149         const_iterator begin() const { return const_iterator(c.begin()); }
00150         const_iterator end() const { return const_iterator(c.end()); }
00151         iterator begin() { return iterator(c.begin()); }
00152         iterator end() { return iterator(c.end()); }
00153 
00154         void clear() { c.clear(); trunc_cnt = 0; scale = 1.0; }
00155 
00156       private:
00157         position_type
00158           scale_and_truncate(position_type x) {
00159               for (int i = 0; i < ndim; ++i) {
00160                   x[i] *= scale;
00161                   if (x[i] < -1.0) { ++trunc_cnt; x[i] = -1.0; }
00162                   else if (x[i] > 1.0) { ++trunc_cnt; x[i] = 1.0; }
00163               }
00164               return x;
00165           }
00166         void corner_indices(position_type const&, metric_type,
00167                             pindex_type&, pindex_type&);
00168 
00169         metric_type scale;
00170         int trunc_cnt;
00171         container c;
00172         metric_function metric;
00173     };
00174 
00175 
00176   template<typename T, typename U, typename Metric>
00177     inline void
00178     point_map<T, U, Metric>
00179     ::corner_indices(position_type const& x, metric_type d,
00180                      pindex_type& idx_inf, pindex_type& idx_sup) {
00181         position_type x_inf = x, x_sup = x;
00182         for (int i = 0; i < ndim; ++i) {
00183             x_inf[i] -= d;
00184             x_sup[i] += d;
00185         }
00186         position_type z_inf = scale*x_inf;
00187         position_type z_sup = scale*x_sup;
00188         for (int i = 0; i < ndim; ++i) {
00189             if (z_inf[i] < -1.0) {
00190                 z_inf[i] = -1.0;
00191                 if (z_sup[i] < -1.0)  z_sup[i] = -1.0;
00192             }
00193             if (z_sup[i] > 1.0) {
00194                 z_sup[i] = 1.0;
00195                 if (z_inf[i] > 1.0)  z_inf[i] = 1.0;
00196             }
00197         }
00198         idx_inf = more::max(fold(z_inf), c.begin()->first);
00199         full_iterator last = c.end(); --last;
00200         idx_sup = more::min(fold(z_sup), last->first);
00201     }
00202 
00203   template<typename T, typename U, typename Metric>
00204     inline typename point_map<T, U, Metric>::vicinity_view
00205     point_map<T, U, Metric>
00206     ::vicinity(position_type const& x, metric_type d) {
00207         pindex_type idx_inf, idx_sup;
00208         corner_indices(x, d, idx_inf, idx_sup);
00209         full_iterator it_inf = c.lower_bound(idx_inf);
00210         if (it_inf != c.begin()) --it_inf;
00211         return vicinity_view(it_inf, c.upper_bound(idx_sup),  
00212                              vicinity_filter(x, d, metric));
00213     }
00214 
00215   template<typename T, typename U, typename Metric>
00216     inline typename point_map<T, U, Metric>::iterator
00217     point_map<T, U, Metric>
00218     ::find_closest(position_type const& x) {
00219         if (c.size() < 2) {
00220             if (c.size() == 1) return iterator(c.begin());
00221             else throw std::logic_error
00222                    ("point_map::find_closest in empty map.");
00223         }
00224         pindex_type idx = fold(scale_and_truncate(x));
00225         full_iterator it_inc = c.lower_bound(idx);
00226         full_iterator it_dec = it_inc;
00227         full_iterator it_min = it_inc;
00228         metric_type d_min = metric(it_min->second.first, x);
00229         pindex_type idx_inf, idx_sup;
00230         corner_indices(x, d_min, idx_inf, idx_sup);
00231 
00232         bool changed;
00233         do {
00234             changed = 0;
00235             if (it_dec->first > idx_inf) {
00236                 changed = true;
00237                 --it_dec;
00238                 metric_type d = metric(it_dec->second.first, x);
00239                 if (d < d_min) {
00240                     d_min = d;
00241                     it_min = it_dec;
00242                     corner_indices(x, d_min, idx_inf, idx_sup);
00243                 }
00244             }
00245             if (it_inc->first < idx_sup) {
00246                 changed = true;
00247                 ++it_inc;
00248                 metric_type d = metric(it_inc->second.first, x);
00249                 if (d < d_min) {
00250                     d_min = d;
00251                     it_min = it_inc;
00252                     corner_indices(x, d_min, idx_inf, idx_sup);
00253                 }
00254             }
00255         }
00256         while (changed);
00257 
00258         return iterator(it_min);
00259     }
00260 }}
00261 #endif

Generated on Sat Sep 7 19:11:20 2002 for more with Doxygen 1.2.13.1. Doxygen 1.2.13.1 is written and copyright 1997-2002 by Dimitri van Heesch.