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