nChooseKSampleSelector.h

Go to the documentation of this file.
00001 
00016 #ifndef DLR_COMPUTERVISION_NCHOOSEKSAMPLESELECTOR_H
00017 #define DLR_COMPUTERVISION_NCHOOSEKSAMPLESELECTOR_H
00018 
00019 #include <vector>
00020 
00021 namespace dlr {
00022 
00023   namespace computerVision {
00024 
00033     template <class Sample>
00034     class NChooseKSampleSelector {
00035     public:
00036 
00037       // ========= Public typedefs. =========
00038 
00042       typedef Sample SampleType;
00043 
00049       typedef std::pair<typename std::vector<SampleType>::const_iterator,
00050                         typename std::vector<SampleType>::const_iterator>
00051       SampleSequenceType;
00052 
00053 
00054       // ========= Public member functions. =========
00055 
00071       template <class IterType>
00072       NChooseKSampleSelector(size_t sampleSize,
00073                              IterType beginIter,
00074                              IterType endIter);
00075 
00076 
00086       size_t
00087       getNumberOfSamples();
00088       
00089 
00097       SampleSequenceType
00098       getPool() {
00099         return std::make_pair(m_poolVector.begin(), m_poolVector.end());
00100       }
00101 
00102 
00110       size_t
00111       getPoolSize() {return m_poolVector.size();}
00112 
00113 
00128       SampleSequenceType
00129       getSample(size_t sampleNumber);
00130 
00131     private:
00132 
00133       size_t
00134       getFactorial(size_t argument);
00135 
00136       void
00137       incrementSampleIndices();
00138       
00139       SampleSequenceType
00140       statelessGetSample(size_t sampleNumber);
00141 
00142       size_t m_numberOfSamples;
00143       std::vector<SampleType> m_poolVector;
00144       size_t m_previousSampleNumber;
00145       std::vector<size_t> m_sampleIndices;
00146       std::vector<SampleType> m_sampleVector;
00147 
00148     };
00149 
00150   } // namespace computerVision
00151   
00152 } // namespace dlr
00153 
00154 
00155 /* ============ Definitions of inline & template functions ============ */
00156 
00157 #include <limits>
00158 #include <dlrCommon/exception.h>
00159 
00160 namespace dlr {
00161 
00162   namespace computerVision {
00163 
00164     template <class Sample>
00165     template <class IterType>
00166     NChooseKSampleSelector<Sample>::
00167     NChooseKSampleSelector(size_t sampleSize,
00168                            IterType beginIter,
00169                            IterType endIter)
00170       : m_numberOfSamples(0),
00171         m_poolVector(beginIter, endIter),
00172         m_previousSampleNumber(std::numeric_limits<size_t>::max() - 1),
00173         m_sampleIndices(sampleSize),
00174         m_sampleVector(sampleSize)
00175     {
00176       if(m_sampleIndices.size() == 0) {
00177         DLR_THROW(ValueException,
00178                   "NChooseKSampleSelector::NChooseKSampleSelector()",
00179                   "Argument sampleSize must be nonzero.");
00180       }
00181       if(m_sampleIndices.size() > m_poolVector.size()) {
00182         DLR_THROW(ValueException,
00183                   "NChooseKSampleSelector::NChooseKSampleSelector()",
00184                   "Argument sampleSize must be less than or equal to "
00185                   "the number of elements in the input sequence.");
00186       }
00187     }
00188 
00189     
00190     template <class Sample>
00191     size_t
00192     NChooseKSampleSelector<Sample>::
00193     getNumberOfSamples()
00194     {
00195       if(m_numberOfSamples == 0) {
00196         // Compute binomial coefficient "n choose k".
00197         size_t nFactorial = this->getFactorial(m_poolVector.size());
00198         size_t kFactorial = this->getFactorial(m_sampleIndices.size());
00199         size_t nMinusKFactorial = this->getFactorial(
00200           m_poolVector.size() - m_sampleIndices.size());
00201         m_numberOfSamples = nFactorial / (kFactorial * nMinusKFactorial);
00202       }
00203       return m_numberOfSamples;
00204     }
00205 
00206     
00207     template <class Sample>
00208     typename NChooseKSampleSelector<Sample>::SampleSequenceType
00209     NChooseKSampleSelector<Sample>::
00210     getSample(size_t sampleNumber)
00211     {
00212       if(sampleNumber != m_previousSampleNumber + 1) {
00213         m_previousSampleNumber = sampleNumber;
00214         return this->statelessGetSample(sampleNumber);
00215       }
00216 
00217       // This code ought to do something more efficient than this.
00218       this->incrementSampleIndices();
00219       for(size_t kk = 0; kk < m_sampleIndices.size(); ++kk) {
00220         m_sampleVector[kk] = m_poolVector[m_sampleIndices[kk]];
00221       }
00222       ++m_previousSampleNumber;
00223       return std::make_pair(m_sampleVector.begin(), m_sampleVector.end());
00224     }
00225 
00226 
00227     template <class Sample>
00228     size_t
00229     NChooseKSampleSelector<Sample>::
00230     getFactorial(size_t argument)
00231     {
00232       size_t result = 1;
00233       for(size_t ii = 2; ii <= argument; ++ii) {
00234         result *= ii;
00235       }
00236       return result;
00237     }
00238 
00239 
00240     template <class Sample>
00241     void
00242     NChooseKSampleSelector<Sample>::
00243     incrementSampleIndices()
00244     {
00245       size_t const finalIndex = m_sampleIndices.size() - 1;
00246 
00247       // Try for the naive increment, ignoring overflow.
00248       ++(m_sampleIndices[finalIndex]);
00249 
00250       // Now propagate any overflow up the chain.
00251       size_t ii = finalIndex;
00252       while(m_sampleIndices[finalIndex] >= m_poolVector.size()) {
00253         // Remember size_t wraps around: (0 - 1) is a very big number.
00254         if((--ii) > m_sampleIndices.size()) {
00255           DLR_THROW(IndexException,
00256                     "NChooseKSampleSelector::incrementSampleIndices()",
00257                     "No more samples available.");
00258         }
00259         ++(m_sampleIndices[ii]);
00260         for(size_t jj = ii + 1; jj < m_sampleIndices.size(); ++jj) {
00261           m_sampleIndices[jj] = m_sampleIndices[jj - 1] + 1;
00262         }
00263       }
00264     }
00265 
00266 
00267     template <class Sample>
00268     typename NChooseKSampleSelector<Sample>::SampleSequenceType
00269     NChooseKSampleSelector<Sample>::
00270     statelessGetSample(size_t sampleNumber)
00271     {
00272       for(size_t ii = 0; ii < m_sampleIndices.size(); ++ii) {
00273         m_sampleIndices[ii] = ii;
00274       }
00275       for(size_t jj = 0; jj < sampleNumber; ++jj) {
00276         this->incrementSampleIndices();
00277       }
00278       for(size_t kk = 0; kk < m_sampleIndices.size(); ++kk) {
00279         m_sampleVector[kk] = m_poolVector[m_sampleIndices[kk]];
00280       }
00281       return std::make_pair(m_sampleVector.begin(), m_sampleVector.end());
00282     }
00283         
00284   } // namespace computerVision
00285   
00286 } // namespace dlr
00287 
00288 #endif /* #ifndef DLR_COMPUTERVISION_NCHOOSEKSAMPLESELECTOR_H */

Generated on Wed Nov 25 12:15:05 2009 for dlrComputerVision Utility Library by  doxygen 1.5.8