core/vnl/vnl_scalar_join_iterator.txx
Go to the documentation of this file.
00001 // This is core/vnl/vnl_scalar_join_iterator.txx
00002 #ifndef vnl_scalar_join_iterator_txx_
00003 #define vnl_scalar_join_iterator_txx_
00004 //:
00005 // \file
00006 //
00007 // \author Andrew W. Fitzgibbon, Oxford RRG
00008 // \date   27 Dec 96
00009 //
00010 //-----------------------------------------------------------------------------
00011 
00012 #include "vnl_scalar_join_iterator.h"
00013 #include <vcl_list.txx>
00014 
00015 #define VNL_SCALAR_JOIN_ITERATOR_INSTANTIATE(T) \
00016 template class vnl_scalar_join_iterator_indexed_pair<T >;\
00017 template class vnl_scalar_join_iterator<T >; \
00018 template vcl_ostream& operator<<(vcl_ostream& s, const vnl_scalar_join_iterator_indexed_pair<T >& p);\
00019 VCL_LIST_INSTANTIATE(vnl_scalar_join_iterator_indexed_pair<T >)
00020 
00021 #include <vcl_cassert.h>
00022 #include <vcl_iostream.h>
00023 #include <vnl/vnl_matrix.h>
00024 
00025 // Helper class to hold the sorted arrays of indices.
00026 
00027 template <class T>
00028 bool vnl_scalar_join_iterator_indexed_pair<T>::operator ==
00029     (const vnl_scalar_join_iterator_indexed_pair<T>& that) const
00030 {
00031   return (*that.object) == (*object);
00032 }
00033 
00034 template <class T>
00035 bool vnl_scalar_join_iterator_indexed_pair<T>::operator <
00036     (const vnl_scalar_join_iterator_indexed_pair<T>& that) const
00037 {
00038   return (*object) < (*that.object);
00039 }
00040 
00041 template <class T>
00042 vcl_ostream& operator<<(vcl_ostream& s,
00043                         const vnl_scalar_join_iterator_indexed_pair<T>& p)
00044 {
00045   return s << p.original_index << ' ' << *(p.object) << '\n';
00046 }
00047 
00048 template <class T>
00049 vnl_scalar_join_iterator<T>::vnl_scalar_join_iterator
00050     (const vnl_matrix<T>& relation1, unsigned column1,
00051      const vnl_matrix<T>& relation2, unsigned column2):
00052   n1(relation1.rows()),
00053   n2(relation2.rows()),
00054   pI1(new vcl_list<vnl_scalar_join_iterator_indexed_pair<T > >(n1)),
00055   pI2(new vcl_list<vnl_scalar_join_iterator_indexed_pair<T > >(n2)),
00056   I1(*pI1),
00057   I2(*pI2)
00058 {
00059   // Sort on appropriate columns
00060   {
00061     for (unsigned i = 0; i < n1; ++i)
00062       I1.push_back(vnl_scalar_join_iterator_indexed_pair<T>(&relation1(i, column1), i));
00063     I1.sort();
00064   }
00065   {
00066     for (unsigned i = 0; i < n2; ++i)
00067       I2.push_back(vnl_scalar_join_iterator_indexed_pair<T>(&relation2(i, column2), i));
00068     I2.sort();
00069   }
00070 
00071   // Initialize for iteration
00072   index1 = I1.begin();
00073   index2 = I2.begin();
00074 
00075   // Loop to first
00076   for (;;) {
00077     T star1 = *(*index1).object;
00078     T star2 = *(*index2).object;
00079     if (star1 == star2)
00080       return;
00081 
00082     if (star1 > star2)
00083       ++index2;
00084     else
00085       ++index1;
00086   }
00087 }
00088 
00089 //: Destructor
00090 template <class T>
00091 vnl_scalar_join_iterator<T>::~vnl_scalar_join_iterator()
00092 {
00093   delete pI1;
00094   delete pI2;
00095 }
00096 
00097 template <class T>
00098 bool vnl_scalar_join_iterator<T>::done() const
00099 {
00100   return (index1 == I1.end()) || (index2 == I2.end());
00101 }
00102 
00103 //: Increment the iterator to point to the next pair of rows.
00104 template <class T>
00105 void vnl_scalar_join_iterator<T>::next()
00106 {
00107   T obj1 = *(*index1).object;
00108   // increment i2, check if still valid/same
00109   if (++index2 == I2.end()) return;
00110 
00111   T nextobj2 = *(*index2).object;
00112   if (obj1 == nextobj2)
00113     return; // Found another match
00114 
00115   // nextobj2 must not be < obj1
00116   assert(!(nextobj2 < obj1));
00117 
00118   // So, objects are different (in fact, obj1 > obj2 right now), lockstep until
00119   // they match or we're done.
00120   while (!done()) {
00121     T obj1 = *(*index1).object;
00122     T obj2 = *(*index2).object;
00123 
00124     if (obj1 == obj2) {
00125       // If they're equal, hack back along obj2's array to find the start of the
00126       // stretch of equal ones.  This allows join
00127       //      1 3     3 5
00128       //      2 3     3 6
00129       // to return the kronecker product of the sets by iteration.
00130       // No that's going to be a hack.  Will be fixed RSN.
00131       return;
00132     }
00133 
00134     if (obj1 > obj2)
00135       ++index2;
00136     else
00137       ++index1;
00138   }
00139 }
00140 
00141 template <class T>
00142 unsigned vnl_scalar_join_iterator<T>::row1() const
00143 {
00144   return (*index1).original_index;
00145 }
00146 
00147 template <class T>
00148 unsigned vnl_scalar_join_iterator<T>::row2() const
00149 {
00150   return (*index2).original_index;
00151 }
00152 
00153 //: Postfix ++ should not be used. Only present for instantiation purposes.
00154 template <class T>
00155 vnl_scalar_join_iterator<T> vnl_scalar_join_iterator<T>::operator++(int)
00156 {
00157   vcl_cerr << "This should not happen! postfix ++ called\n";
00158   return *this;
00159 }
00160 
00161 #endif // vnl_scalar_join_iterator_txx_