00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef WIFI_FRAME_FILTER_FAST_INTERSECTOR_HXX_
00023 # define WIFI_FRAME_FILTER_FAST_INTERSECTOR_HXX_
00024
00025 # include <iostream>
00026 # include <sstream>
00027 # include <boost/foreach.hpp>
00028
00029 # include "fast_intersector.hh"
00030
00031 # include <wipal/wifi/frame/filter/non_noisy_prism.hh>
00032 # include <wipal/wifi/frame/filter/uniquely_identifiable.hh>
00033
00034 namespace wifi
00035 {
00036 namespace frame
00037 {
00038 namespace filter
00039 {
00040
00041 namespace internals
00042 {
00043
00044 template <class I1, class I2, class B1, class B2>
00045 fast_intersector_iterator<I1, I2, B1, B2>::
00046 fast_intersector_iterator(const iterable_type& i, bool end):
00047 super_type (),
00048 iterable_ (&i),
00049 next_ (end ? i.last_ : i.first_)
00050 # ifdef WP_ENABLE_INFO
00051 , rhs_total_ (0),
00052 ref_total_ (0)
00053 # endif
00054 {
00055 if (not end)
00056 increment();
00057 }
00058
00059 template <class I1, class I2, class B1, class B2>
00060 bool
00061 fast_intersector_iterator<I1, I2, B1, B2>::
00062 equal(const fast_intersector_iterator& rhs) const
00063 {
00064 if (not rhs.value())
00065 return not this->value();
00066 return next_ == rhs.next_;
00067 }
00068
00069 template <class I1, class I2, class B1, class B2>
00070 void
00071 fast_intersector_iterator<I1, I2, B1, B2>::increment()
00072 {
00073 const I2& last = this->iterable_->last_;
00074 bool found (false);
00075
00076 while (next_ != last and not found)
00077 {
00078 found = check();
00079 ++next_;
00080 # ifdef WP_ENABLE_INFO
00081 ++rhs_total_;
00082 # endif // WP_ENABLE_INFO
00083 }
00084
00085 if (not found)
00086 {
00087 this->value() = lookahead_;
00088 lookahead_ = boost::none_t ();
00089 }
00090
00091 # ifdef WP_ENABLE_INFO
00092 if (not found and not this->value())
00093 {
00094 const unsigned lhs_total = this->iterable_->arrivals_.size();
00095
00096 std::cerr << "INFO: Trace 2 has " << rhs_total_
00097 << " unique frames.\n"
00098 << "INFO: " << ref_total_ << " reference frames.\n"
00099 << "INFO: " << (ref_total_ * 100.f / lhs_total)
00100 << "% of trace 1's unique frames.\n"
00101 << "INFO: " << (ref_total_ * 100.f / rhs_total_)
00102 << "% of trace 2's unique frames." << std::endl;
00103 }
00104 else
00105 ++ref_total_;
00106 # endif // WP_ENABLE_INFO
00107 }
00108
00109 template <class I1, class I2, class B1, class B2>
00110 bool
00111 fast_intersector_iterator<I1, I2, B1, B2>::check()
00112 {
00113 const arrivals_iterator i = iterable_->arrivals_.find(*next_);
00114
00115 if (i == iterable_->arrivals_.end())
00116 return false;
00117
00118 if (not lookahead_)
00119 {
00120
00121
00122
00123 lookahead_ = value_type (*i, *next_);
00124 return false;
00125 }
00126
00127 value_type& lookahead = lookahead_.get();
00128 const tool::microseconds dt1 (i->microseconds() -
00129 lookahead.first.microseconds());
00130 const tool::microseconds dt2 (next_->microseconds() -
00131 lookahead.second.microseconds());
00132
00133 if (not check_drift(dt1, dt2, *i, *next_))
00134 return false;
00135 check_consistency(dt1, dt2, *i, *next_);
00136
00137 this->value() = lookahead;
00138 lookahead = value_type (*i, *next_);
00139 return true;
00140 }
00141
00142 template <class I1, class I2, class B1, class B2>
00143 bool
00144 fast_intersector_iterator<I1, I2, B1, B2>::
00145 check_drift(const tool::microseconds& dt1,
00146 const tool::microseconds& dt2,
00147 const typename I1::value_type& f1,
00148 const typename I2::value_type& f2)
00149 {
00150 assert(lookahead_);
00151
00152 value_type& lookahead = lookahead_.get();
00153 const tool::microseconds drift (dt1 - dt2);
00154
00155 if (drift < -drift_warn_threshold or drift_warn_threshold < drift)
00156 {
00157 std::cerr << f1 << '-' << f2 << ": Dubious drift: "
00158 << (drift / 1000.f) << "ms";
00159 if (this->value())
00160 {
00161
00162
00163 std::cerr << " (ignoring reference)." << std::endl;
00164
00165 ignore(f1, f2);
00166 return false;
00167 }
00168 else
00169 {
00170
00171
00172
00173 std::cerr << ".\n"
00174 << lookahead.first << '-' << lookahead.second
00175 << ": Previous reference (ignoring, "
00176 << "potentially invalid)." << std::endl;
00177
00178 ignore(lookahead.first, lookahead.second);
00179 lookahead = value_type (f1, f2);
00180 return false;
00181 }
00182 }
00183 dont_ignore(f1, f2);
00184 return true;
00185 }
00186
00187 template <class I1, class I2, class B1, class B2>
00188 void
00189 fast_intersector_iterator<I1, I2, B1, B2>::
00190 check_consistency(const tool::microseconds& dt1,
00191 const tool::microseconds& dt2,
00192 const typename I1::value_type& f1,
00193 const typename I2::value_type& f2) const
00194 {
00195 assert(lookahead_);
00196
00197 const value_type& lookahead = lookahead_.get();
00198
00199 const tool::microseconds& f1_us = f1.microseconds();
00200 const tool::microseconds& f2_us = f2.microseconds();
00201 const tool::microseconds& la1_us = lookahead.first.microseconds();
00202 const tool::microseconds& la2_us = lookahead.second.microseconds();
00203
00204 const tool::microseconds precision = iterable_->precision_;
00205
00206
00207
00208
00209
00210
00211 if (f1_us - la1_us < -precision or f2_us - la2_us < -precision)
00212 std::cerr << f1 << '-' << f2 << ": Reference anterior to "
00213 << lookahead.first << '-' << lookahead.second << '.'
00214 << std::endl;
00215
00216 else if (dt1 > dt_warn_threshold or dt2 > dt_warn_threshold)
00217 std::cerr << f1 << '-' << f2 << ": "
00218 << (dt1 / 1000.f) << "ms and "
00219 << (dt2 / 1000.f) << "ms since "
00220 << lookahead.first << '-' << lookahead.second << '.'
00221 << std::endl;
00222 }
00223
00224 template <class I1, class I2, class B1, class B2>
00225 void
00226 fast_intersector_iterator<I1, I2, B1, B2>::
00227 ignore(const typename I1::value_type& f1,
00228 const typename I2::value_type& f2)
00229 {
00230
00231
00232
00233
00234
00235
00236 if (not ign_)
00237 ign_ = ignore_info (f1.microseconds(), f2.microseconds(),
00238 f1.frame_id(), f2.frame_id());
00239 }
00240
00241 template <class I1, class I2, class B1, class B2>
00242 void
00243 fast_intersector_iterator<I1, I2, B1, B2>::
00244 dont_ignore(const typename I1::value_type& f1,
00245 const typename I2::value_type& f2)
00246 {
00247
00248
00249 if (ign_)
00250 {
00251 std::ostringstream os;
00252
00253 os << f1 << '-' << f2 << ": ";
00254
00255 const std::string head = os.str();
00256
00257 std::cerr
00258 << head << "Frames since first ignored reference:\n"
00259 << head << "* T1: " << (f1.frame_id() - ign_->total1_)
00260 << " (" << (f1.microseconds() - ign_->stamp1_) << "us)\n"
00261 << head << "* T2: " << (f2.frame_id() - ign_->total2_)
00262 << " (" << (f2.microseconds() - ign_->stamp2_) << "us)\n"
00263 << std::flush;
00264
00265 ign_ = boost::none_t ();
00266 }
00267 }
00268
00269 template <class I1, class I2, class B1, class B2>
00270 unsigned
00271 fast_intersector_iterator<I1, I2, B1, B2>::rhs_frame_count() const
00272 {
00273 return next_.frame_count();
00274 }
00275
00276 template <class I1, class I2, class B1, class B2>
00277 unsigned
00278 fast_intersector_iterator<I1, I2, B1, B2>::rhs_uframe_count() const
00279 {
00280 return next_.unique_frame_count();
00281 }
00282
00283 template <class I1, class I2, class B1, class B2>
00284 fast_intersector_iterator<I1, I2, B1, B2>::
00285 ignore_info::ignore_info(const tool::microseconds& stamp_rhs,
00286 const tool::microseconds& stamp_lhs,
00287 const unsigned total_rhs,
00288 const unsigned total_lhs):
00289 stamp1_ (stamp_rhs),
00290 stamp2_ (stamp_lhs),
00291 total1_ (total_rhs),
00292 total2_ (total_lhs)
00293 {
00294 }
00295
00296 }
00297
00298
00299 template <class I1, class I2, class B>
00300 fast_intersector<I1, I2, B>::
00301 fast_intersector(const I1& first1, const I1& last1,
00302 const I2& first2, const I2& last2,
00303 const unsigned precision):
00304 first_ (first2),
00305 last_ (last2),
00306 # ifndef WP_DONT_USE_HASH
00307 arrivals_ (hash_bucket_count),
00308 # endif
00309 precision_ (precision)
00310 {
00311 reset_lhs(first1, last1);
00312 }
00313
00314 template <class I1, class I2, class B>
00315 void
00316 fast_intersector<I1, I2, B>::reset_lhs(const I1& first1, const I1& last1)
00317 {
00318 arrivals_type collisions;
00319
00320 arrivals_.clear();
00321 for (I1 i = first1; i != last1; ++i)
00322 {
00323 typedef typename arrivals_type::iterator iterator;
00324
00325 std::pair<iterator, bool> r = arrivals_.insert(*i);
00326
00327 if (not r.second)
00328 {
00329 collisions.insert(*i);
00330
00331 std::cerr << *i << ": Unique frame actually a duplicate of "
00332 << *r.first << " (ignoring both)." << std::endl;
00333 }
00334 }
00335
00336 BOOST_FOREACH(const typename I1::value_type& v, collisions)
00337 arrivals_.erase(v);
00338
00339 # ifdef WP_ENABLE_INFO
00340 std::cerr << "INFO: Trace 1's unique frames successfuly loaded.\n"
00341 << "INFO: Trace 1 has " << arrivals_.size()
00342 << " unique frames." << std::endl;
00343 # endif // WP_ENABLE_INFO
00344 }
00345
00346 template <class I1, class I2, class B>
00347 void
00348 fast_intersector<I1, I2, B>::reset_rhs(const I2& first2, const I2& last2)
00349 {
00350 first_ = first2;
00351 last_ = last2;
00352 }
00353
00354 }
00355
00356 }
00357
00358 }
00359
00360 #endif // ! WIFI_FRAME_FILTER_FAST_INTERSECTOR_HXX_