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 << "WARNING:" << f1.frame_id() << '-' << f2.frame_id()
00158 << ": Dubious drift: " << (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" "WARNING:"
00174 << lookahead.first.frame_id() << '-'
00175 << lookahead.second.frame_id()
00176 << ": Previous reference (ignoring, "
00177 << "potentially invalid)." << std::endl;
00178
00179 ignore(lookahead.first, lookahead.second);
00180 lookahead = value_type (f1, f2);
00181 return false;
00182 }
00183 }
00184 dont_ignore(f1, f2);
00185 return true;
00186 }
00187
00188 template <class I1, class I2, class B1, class B2>
00189 void
00190 fast_intersector_iterator<I1, I2, B1, B2>::
00191 check_consistency(const tool::microseconds& dt1,
00192 const tool::microseconds& dt2,
00193 const typename I1::value_type& f1,
00194 const typename I2::value_type& f2) const
00195 {
00196 assert(lookahead_);
00197
00198 const value_type& lookahead = lookahead_.get();
00199
00200 if (f1.microseconds() < lookahead.first.microseconds() or
00201 f2.microseconds() < lookahead.second.microseconds())
00202 std::cerr << "WARNING:" << f1.frame_id() << '-' << f2.frame_id()
00203 << ": Reference anterior to "
00204 << lookahead.first.frame_id() << '-'
00205 << lookahead.second.frame_id() << '.' << std::endl;
00206 else if (dt1 > dt_warn_threshold or dt2 > dt_warn_threshold)
00207 std::cerr << "WARNING:" << f1.frame_id() << '-' << f2.frame_id()
00208 << ": " << (dt1 / 1000.f) << "ms and " << (dt2 / 1000.f)
00209 << "ms since " << lookahead.first.frame_id() << '-'
00210 << lookahead.second.frame_id() << '.' << std::endl;
00211 }
00212
00213 template <class I1, class I2, class B1, class B2>
00214 void
00215 fast_intersector_iterator<I1, I2, B1, B2>::
00216 ignore(const typename I1::value_type& f1,
00217 const typename I2::value_type& f2)
00218 {
00219
00220
00221
00222
00223
00224
00225 if (not ign_)
00226 ign_ = ignore_info (f1.microseconds(), f2.microseconds(),
00227 f1.frame_id(), f2.frame_id());
00228 }
00229
00230 template <class I1, class I2, class B1, class B2>
00231 void
00232 fast_intersector_iterator<I1, I2, B1, B2>::
00233 dont_ignore(const typename I1::value_type& f1,
00234 const typename I2::value_type& f2)
00235 {
00236
00237
00238 if (ign_)
00239 {
00240 std::ostringstream os;
00241
00242 os << "WARNING:"
00243 << f1.frame_id() << '-' << f2.frame_id() << ": ";
00244
00245 const std::string head = os.str();
00246
00247 std::cerr
00248 << head << "Frames since first ignored reference:\n"
00249 << head << "* T1: " << (f1.frame_id() - ign_->total1_)
00250 << " (" << (f1.microseconds() - ign_->stamp1_) << "us)\n"
00251 << head << "* T2: " << (f2.frame_id() - ign_->total2_)
00252 << " (" << (f2.microseconds() - ign_->stamp2_) << "us)\n"
00253 << std::flush;
00254
00255 ign_ = boost::none_t ();
00256 }
00257 }
00258
00259 template <class I1, class I2, class B1, class B2>
00260 unsigned
00261 fast_intersector_iterator<I1, I2, B1, B2>::rhs_frame_count() const
00262 {
00263 return next_.frame_count();
00264 }
00265
00266 template <class I1, class I2, class B1, class B2>
00267 unsigned
00268 fast_intersector_iterator<I1, I2, B1, B2>::rhs_uframe_count() const
00269 {
00270 return next_.unique_frame_count();
00271 }
00272
00273 template <class I1, class I2, class B1, class B2>
00274 fast_intersector_iterator<I1, I2, B1, B2>::
00275 ignore_info::ignore_info(const tool::microseconds& stamp_rhs,
00276 const tool::microseconds& stamp_lhs,
00277 const unsigned total_rhs,
00278 const unsigned total_lhs):
00279 stamp1_ (stamp_rhs),
00280 stamp2_ (stamp_lhs),
00281 total1_ (total_rhs),
00282 total2_ (total_lhs)
00283 {
00284 }
00285
00286 }
00287
00288
00289 template <class I1, class I2, class B>
00290 fast_intersector<I1, I2, B>::
00291 fast_intersector(const I1& first1, const I1& last1,
00292 const I2& first2, const I2& last2):
00293 first_ (first2),
00294 last_ (last2)
00295 # ifndef WP_DONT_USE_HASH
00296 , arrivals_ (hash_bucket_count)
00297 # endif
00298 {
00299 reset_lhs(first1, last1);
00300 }
00301
00302 template <class I1, class I2, class B>
00303 void
00304 fast_intersector<I1, I2, B>::reset_lhs(const I1& first1, const I1& last1)
00305 {
00306 arrivals_type collisions;
00307
00308 arrivals_.clear();
00309 for (I1 i = first1; i != last1; ++i)
00310 {
00311 typedef typename arrivals_type::iterator iterator;
00312
00313 std::pair<iterator, bool> r = arrivals_.insert(*i);
00314
00315 if (not r.second)
00316 {
00317 collisions.insert(*i);
00318 std::cerr << "WARNING:" << i->frame_id()
00319 << ": Unique frame actually a duplicate of "
00320 << r.first->frame_id() << " (ignoring both)."
00321 << std::endl;
00322 }
00323 }
00324
00325 BOOST_FOREACH(const typename I1::value_type& v, collisions)
00326 arrivals_.erase(v);
00327
00328 # ifdef WP_ENABLE_INFO
00329 std::cerr << "INFO: Trace 1's unique frames successfuly loaded.\n"
00330 << "INFO: Trace 1 has " << arrivals_.size()
00331 << " unique frames." << std::endl;
00332 # endif // WP_ENABLE_INFO
00333 }
00334
00335 template <class I1, class I2, class B>
00336 void
00337 fast_intersector<I1, I2, B>::reset_rhs(const I2& first2, const I2& last2)
00338 {
00339 first_ = first2;
00340 last_ = last2;
00341 }
00342
00343 }
00344
00345 }
00346
00347 }
00348
00349 #endif // ! WIFI_FRAME_FILTER_FAST_INTERSECTOR_HXX_