1 /***********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright 2008-2009  Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
5  * Copyright 2008-2009  David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
6  *
7  * THE BSD LICENSE
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *************************************************************************/
30 
31 #ifndef OPENCV_FLANN_RANDOM_H
32 #define OPENCV_FLANN_RANDOM_H
33 
34 #include <algorithm>
35 #include <cstdlib>
36 #include <vector>
37 
38 #include "general.h"
39 
40 namespace cvflann
41 {
42 
rand()43 inline int rand()
44 {
45 #ifndef OPENCV_FLANN_USE_STD_RAND
46 #   if INT_MAX == RAND_MAX
47     int v = cv::theRNG().next() & INT_MAX;
48 #   else
49     int v = cv::theRNG().uniform(0, RAND_MAX + 1);
50 #   endif
51 #else
52     int v = std::rand();
53 #endif // OPENCV_FLANN_USE_STD_RAND
54     return v;
55 }
56 
57 /**
58  * Seeds the random number generator
59  *  @param seed Random seed
60  */
seed_random(unsigned int seed)61 inline void seed_random(unsigned int seed)
62 {
63 #ifndef OPENCV_FLANN_USE_STD_RAND
64     cv::theRNG() = cv::RNG(seed);
65 #else
66     std::srand(seed);
67 #endif
68 }
69 
70 /*
71  * Generates a random double value.
72  */
73 /**
74  * Generates a random double value.
75  * @param high Upper limit
76  * @param low Lower limit
77  * @return Random double value
78  */
79 inline double rand_double(double high = 1.0, double low = 0)
80 {
81     return low + ((high-low) * (rand() / (RAND_MAX + 1.0)));
82 }
83 
84 /**
85  * Generates a random integer value.
86  * @param high Upper limit
87  * @param low Lower limit
88  * @return Random integer value
89  */
90 inline int rand_int(int high = RAND_MAX, int low = 0)
91 {
92     return low + (int) ( double(high-low) * (rand() / (RAND_MAX + 1.0)));
93 }
94 
95 /**
96  * Random number generator that returns a distinct number from
97  * the [0,n) interval each time.
98  */
99 class UniqueRandom
100 {
101     std::vector<int> vals_;
102     int size_;
103     int counter_;
104 
105 public:
106     /**
107      * Constructor.
108      * @param n Size of the interval from which to generate
109      * @return
110      */
UniqueRandom(int n)111     UniqueRandom(int n)
112     {
113         init(n);
114     }
115 
116     /**
117      * Initializes the number generator.
118      * @param n the size of the interval from which to generate random numbers.
119      */
init(int n)120     void init(int n)
121     {
122         // create and initialize an array of size n
123         vals_.resize(n);
124         size_ = n;
125         for (int i = 0; i < size_; ++i) vals_[i] = i;
126 
127         // shuffle the elements in the array
128 #ifndef OPENCV_FLANN_USE_STD_RAND
129         cv::randShuffle(vals_);
130 #else
131         std::random_shuffle(vals_.begin(), vals_.end());
132 #endif
133 
134         counter_ = 0;
135     }
136 
137     /**
138      * Return a distinct random integer in greater or equal to 0 and less
139      * than 'n' on each call. It should be called maximum 'n' times.
140      * Returns: a random integer
141      */
next()142     int next()
143     {
144         if (counter_ == size_) {
145             return -1;
146         }
147         else {
148             return vals_[counter_++];
149         }
150     }
151 };
152 
153 }
154 
155 #endif //OPENCV_FLANN_RANDOM_H
156