CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/RecoJets/FFTJetAlgorithms/interface/matchOneToOne.h

Go to the documentation of this file.
00001 //
00002 // Utility function for matching elements of one vector to another
00003 // using best matching distance. All pairwise distances are calculated
00004 // and then sorted; the best match corresponds to the smallest
00005 // distance. Both matched elements are removed from the pool,
00006 // then the best match is found among the remaining elements, etc.
00007 //
00008 // I. Volobouev
00009 // April 2008
00010 
00011 #ifndef RecoJets_FFTJetAlgorithms_matchOneToOne_h
00012 #define RecoJets_FFTJetAlgorithms_matchOneToOne_h
00013 
00014 #include <vector>
00015 #include <algorithm>
00016 
00017 namespace fftjetcms {
00018     namespace Private {
00019         struct matchOneToOne_MatchInfo
00020         {
00021             double distance;
00022             unsigned i1;
00023             unsigned i2;
00024 
00025             inline bool operator<(const matchOneToOne_MatchInfo& r) const
00026                 {return distance < r.distance;}
00027 
00028             inline bool operator>(const matchOneToOne_MatchInfo& r) const
00029                 {return distance > r.distance;}
00030         };
00031     }
00032 
00033     //
00034     // (*matchFrom1To2)[idx] will be set to the index of the element in v2
00035     // which corresponds to the element at index "idx" in v1. If no match
00036     // to the element at index "idx" in v1 is found, (*matchFrom1To2)[idx]
00037     // is set to -1. All non-negative (*matchFrom1To2)[idx] values will be
00038     // unique. The function returns the total number of matches made.
00039     //
00040     template <class T1, class T2, class DistanceCalculator>
00041     unsigned matchOneToOne(const std::vector<T1>& v1, const std::vector<T2>& v2,
00042                            const DistanceCalculator& calc,
00043                            std::vector<int>* matchFrom1To2,
00044                            const double maxMatchingDistance = 1.0e300)
00045     {
00046         unsigned nused = 0;
00047         matchFrom1To2->clear();
00048 
00049         const unsigned n1 = v1.size();
00050         if (n1)
00051         {
00052             matchFrom1To2->reserve(n1);
00053             for (unsigned i1=0; i1<n1; ++i1)
00054                 matchFrom1To2->push_back(-1);
00055 
00056             const unsigned n2 = v2.size();
00057             if (n2)
00058             {
00059                 const unsigned nmatches = n1*n2;
00060                 std::vector<Private::matchOneToOne_MatchInfo> distanceTable(nmatches);
00061                 std::vector<int> taken2(n2);
00062 
00063                 for (unsigned i2=0; i2<n2; ++i2)
00064                     taken2[i2] = 0;
00065 
00066                 Private::matchOneToOne_MatchInfo* m;
00067                 for (unsigned i1=0; i1<n1; ++i1)
00068                     for (unsigned i2=0; i2<n2; ++i2)
00069                     {
00070                         m = &distanceTable[i1*n2+i2];
00071                         m->distance = calc(v1[i1], v2[i2]);
00072                         m->i1 = i1;
00073                         m->i2 = i2;
00074                     }
00075 
00076                 std::sort(distanceTable.begin(), distanceTable.end());
00077                 for (unsigned i=0; i<nmatches && nused<n1 && nused<n2; ++i)
00078                 {
00079                     m = &distanceTable[i];
00080                     if (m->distance > maxMatchingDistance)
00081                         break;
00082                     if ((*matchFrom1To2)[m->i1] < 0 && !taken2[m->i2])
00083                     {
00084                         (*matchFrom1To2)[m->i1] = static_cast<int>(m->i2);
00085                         taken2[m->i2] = 1;
00086                         ++nused;
00087                     }
00088                 }
00089             }
00090         }
00091 
00092         return nused;
00093     }
00094 }
00095 
00096 #endif // RecoJets_FFTJetAlgorithms_matchOneToOne_h