File: mbl_select_n_from_m.cxx

package info (click to toggle)
vxl 1.17.0.dfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 153,280 kB
  • ctags: 105,123
  • sloc: cpp: 747,420; ansic: 209,130; fortran: 34,230; lisp: 14,915; sh: 6,187; python: 5,856; makefile: 340; perl: 294; xml: 160
file content (166 lines) | stat: -rw-r--r-- 3,352 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//:
// \file
// \brief A class which returns an N element subset of the integers [0..M-1]
// \author Tim Cootes

#include "mbl_select_n_from_m.h"
#include <vcl_cassert.h>
#include <vcl_iostream.h>

mbl_select_n_from_m::mbl_select_n_from_m()
 : n_(0), m_(0), is_done_(false), use_random_(false)
{
  random_.reseed(123746);
}

mbl_select_n_from_m::mbl_select_n_from_m(unsigned int new_n, unsigned int new_m)
 : n_(new_n), m_(new_m), is_done_(false), use_random_(false)
{
  set_n_m(new_n,new_m);
  random_.reseed(123746);
}

//: Reseed randomiser
void mbl_select_n_from_m::reseed(long s)
{
  random_.reseed(s);
}

  // member functions

void mbl_select_n_from_m::set_n_m(unsigned int new_n, unsigned int new_m)
{
  if (new_n>new_m)
  {
    vcl_cerr<<"mbl_select_n_from_m::set_n_m(): Warning: N>M: nothing selected\n"
            <<"N="<<new_n<<"  M="<<new_m<<vcl_endl;
    is_done_ = true;
  }

  n_=new_n;
  m_=new_m;
  index_.resize(n_);
  reset();
}

void mbl_select_n_from_m::use_random(bool flag)
{
  use_random_=flag;

  if (use_random_)
    random_.choose_n_from_m(index_,not_index_,n_,m_);
  else
    reset();
}

bool mbl_select_n_from_m::reset()
{
  is_done_ = (n_>m_);

  if (is_done_)
    return false;

  if (use_random_)
  {
    random_.choose_n_from_m(index_,not_index_,n_,m_);
    return true;
  }

  for (unsigned int i=0;i<n_;++i)
    index_[i]=i;

  return true;
}

bool mbl_select_n_from_m::next()
{
  if (is_done_) return false;

  if (use_random_)
  {
    random_.choose_n_from_m(index_,not_index_,n_,m_);
    return true;
  }

  // quick return if possible; ensures n_-1 >= 0 further down (which is used!)
  if (n_==m_ || n_ == 0) { is_done_=true; return false; }

  int* index_data = &index_[0];
  index_data[n_-1]++;  // Increment counter

  // Increment previous digit if current one has tripped over limit
  unsigned int low_trip_digit = n_;  // Lowest digit which has tripped
  int start_index=0;                 // index to start digits when trip occurs
  for (unsigned int j=n_-1;j>0;--j)
  {
    // index_[j] has range j..m-n+j
    if (index_data[j]>int(m_-n_+j))
    {
      index_data[j-1]++;
      low_trip_digit=j;
      start_index=index_data[j-1]+1;
      // Start one above previous digit value
    }
  }

  if (index_data[0]>int(m_-n_))
  {
    reset(); // to ensure valid data in index_
    is_done_=true;
    return false;
  }
  else
  if (low_trip_digit<n_)
  {
    // Reset those above
    for (unsigned int i=low_trip_digit;i<n_;i++)
    {
      index_data[i]=start_index;
      start_index++;
    }
  }

  return true;
}

const vcl_vector<int>& mbl_select_n_from_m::subset() const
{
  assert (!is_done_);
  return index_;
}

const vcl_vector<int>& mbl_select_n_from_m::complement()
{
  if (use_random_)
    return not_index_;
    // not_index_ calculated during call to next();

  assert (!is_done_);
  if (not_index_.size()!=m_-n_) not_index_.resize(m_-n_);

  // Fill not_index_ with values in range 0..m-1 not in index_
  // Use fact that index_[i+1]>index_[i]
  unsigned int j=0;  //index in not_index_ array
  unsigned int k=0;
  for (unsigned int i=0;i<n_;i++)
  {
    unsigned int ind_i = index_[i];
    while (k<ind_i)
    {
      not_index_[j]=k;
      j++;
      k++;
    }
    ++k;
  }

  // Fill out end of array
  while (k<m_)
  {
    not_index_[j]=k;
    j++;
    k++;
  }

  return not_index_;
}