File Coverage

/usr/include/c++/5/bits/uniform_int_dist.h
Criterion Covered Total %
statement 0 18 0.0
branch 0 8 0.0
condition n/a
subroutine n/a
pod n/a
total 0 26 0.0


line stmt bran cond sub pod time code
1             // Class template uniform_int_distribution -*- C++ -*-
2              
3             // Copyright (C) 2009-2016 Free Software Foundation, Inc.
4             //
5             // This file is part of the GNU ISO C++ Library. This library is free
6             // software; you can redistribute it and/or modify it under the
7             // terms of the GNU General Public License as published by the
8             // Free Software Foundation; either version 3, or (at your option)
9             // any later version.
10              
11             // This library is distributed in the hope that it will be useful,
12             // but WITHOUT ANY WARRANTY; without even the implied warranty of
13             // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14             // GNU General Public License for more details.
15              
16             // Under Section 7 of GPL version 3, you are granted additional
17             // permissions described in the GCC Runtime Library Exception, version
18             // 3.1, as published by the Free Software Foundation.
19              
20             // You should have received a copy of the GNU General Public License and
21             // a copy of the GCC Runtime Library Exception along with this program;
22             // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23             // .
24              
25             /**
26             * @file bits/uniform_int_dist.h
27             * This is an internal header file, included by other library headers.
28             * Do not attempt to use it directly. @headername{random}
29             */
30              
31             #ifndef _GLIBCXX_BITS_UNIFORM_INT_DIST_H
32             #define _GLIBCXX_BITS_UNIFORM_INT_DIST_H
33              
34             #include
35             #include
36              
37             namespace std _GLIBCXX_VISIBILITY(default)
38             {
39             _GLIBCXX_BEGIN_NAMESPACE_VERSION
40              
41             namespace __detail
42             {
43             /* Determine whether number is a power of 2. */
44             template
45             inline bool
46             _Power_of_2(_Tp __x)
47             {
48             return ((__x - 1) & __x) == 0;
49             };
50             }
51              
52             /**
53             * @brief Uniform discrete distribution for random numbers.
54             *
55             * A discrete random distribution on the range @f$[min, max]@f$ with equal
56             * probability throughout the range.
57             *
58             * @ingroup random_distributions_uniform
59             */
60             template
61             class uniform_int_distribution
62             {
63             static_assert(std::is_integral<_IntType>::value,
64             "template argument not an integral type");
65              
66             public:
67             /** The type of the range of the distribution. */
68             typedef _IntType result_type;
69             /** Parameter type. */
70             struct param_type
71             {
72             typedef uniform_int_distribution<_IntType> distribution_type;
73              
74             explicit
75             param_type(_IntType __a = 0,
76             _IntType __b = std::numeric_limits<_IntType>::max())
77 0           : _M_a(__a), _M_b(__b)
78             {
79             _GLIBCXX_DEBUG_ASSERT(_M_a <= _M_b);
80             }
81              
82             result_type
83             a() const
84             { return _M_a; }
85              
86             result_type
87             b() const
88             { return _M_b; }
89              
90             friend bool
91             operator==(const param_type& __p1, const param_type& __p2)
92             { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; }
93              
94             private:
95             _IntType _M_a;
96             _IntType _M_b;
97             };
98              
99             public:
100             /**
101             * @brief Constructs a uniform distribution object.
102             */
103             explicit
104             uniform_int_distribution(_IntType __a = 0,
105             _IntType __b = std::numeric_limits<_IntType>::max())
106             : _M_param(__a, __b)
107             { }
108              
109             explicit
110             uniform_int_distribution(const param_type& __p)
111             : _M_param(__p)
112             { }
113              
114             /**
115             * @brief Resets the distribution state.
116             *
117             * Does nothing for the uniform integer distribution.
118             */
119             void
120             reset() { }
121              
122             result_type
123             a() const
124             { return _M_param.a(); }
125              
126             result_type
127             b() const
128             { return _M_param.b(); }
129              
130             /**
131             * @brief Returns the parameter set of the distribution.
132             */
133             param_type
134             param() const
135             { return _M_param; }
136              
137             /**
138             * @brief Sets the parameter set of the distribution.
139             * @param __param The new parameter set of the distribution.
140             */
141             void
142             param(const param_type& __param)
143             { _M_param = __param; }
144              
145             /**
146             * @brief Returns the inclusive lower bound of the distribution range.
147             */
148             result_type
149             min() const
150             { return this->a(); }
151              
152             /**
153             * @brief Returns the inclusive upper bound of the distribution range.
154             */
155             result_type
156             max() const
157             { return this->b(); }
158              
159             /**
160             * @brief Generating functions.
161             */
162             template
163             result_type
164             operator()(_UniformRandomNumberGenerator& __urng)
165 0           { return this->operator()(__urng, _M_param); }
166              
167             template
168             result_type
169             operator()(_UniformRandomNumberGenerator& __urng,
170             const param_type& __p);
171              
172             template
173             typename _UniformRandomNumberGenerator>
174             void
175             __generate(_ForwardIterator __f, _ForwardIterator __t,
176             _UniformRandomNumberGenerator& __urng)
177             { this->__generate(__f, __t, __urng, _M_param); }
178              
179             template
180             typename _UniformRandomNumberGenerator>
181             void
182             __generate(_ForwardIterator __f, _ForwardIterator __t,
183             _UniformRandomNumberGenerator& __urng,
184             const param_type& __p)
185             { this->__generate_impl(__f, __t, __urng, __p); }
186              
187             template
188             void
189             __generate(result_type* __f, result_type* __t,
190             _UniformRandomNumberGenerator& __urng,
191             const param_type& __p)
192             { this->__generate_impl(__f, __t, __urng, __p); }
193              
194             /**
195             * @brief Return true if two uniform integer distributions have
196             * the same parameters.
197             */
198             friend bool
199             operator==(const uniform_int_distribution& __d1,
200             const uniform_int_distribution& __d2)
201             { return __d1._M_param == __d2._M_param; }
202              
203             private:
204             template
205             typename _UniformRandomNumberGenerator>
206             void
207             __generate_impl(_ForwardIterator __f, _ForwardIterator __t,
208             _UniformRandomNumberGenerator& __urng,
209             const param_type& __p);
210              
211             param_type _M_param;
212             };
213              
214             template
215             template
216             typename uniform_int_distribution<_IntType>::result_type
217 0           uniform_int_distribution<_IntType>::
218             operator()(_UniformRandomNumberGenerator& __urng,
219             const param_type& __param)
220             {
221             typedef typename _UniformRandomNumberGenerator::result_type
222             _Gresult_type;
223             typedef typename std::make_unsigned::type __utype;
224             typedef typename std::common_type<_Gresult_type, __utype>::type
225             __uctype;
226              
227             const __uctype __urngmin = __urng.min();
228             const __uctype __urngmax = __urng.max();
229             const __uctype __urngrange = __urngmax - __urngmin;
230             const __uctype __urange
231 0           = __uctype(__param.b()) - __uctype(__param.a());
232              
233             __uctype __ret;
234              
235 0 0         if (__urngrange > __urange)
236             {
237             // downscaling
238 0           const __uctype __uerange = __urange + 1; // __urange can be zero
239 0           const __uctype __scaling = __urngrange / __uerange;
240 0           const __uctype __past = __uerange * __scaling;
241 0 0         do
242 0           __ret = __uctype(__urng()) - __urngmin;
243             while (__ret >= __past);
244 0           __ret /= __scaling;
245             }
246 0 0         else if (__urngrange < __urange)
247             {
248             // upscaling
249             /*
250             Note that every value in [0, urange]
251             can be written uniquely as
252              
253             (urngrange + 1) * high + low
254              
255             where
256              
257             high in [0, urange / (urngrange + 1)]
258              
259             and
260              
261             low in [0, urngrange].
262             */
263             __uctype __tmp; // wraparound control
264 0 0         do
265             {
266             const __uctype __uerngrange = __urngrange + 1;
267 0           __tmp = (__uerngrange * operator()
268 0           (__urng, param_type(0, __urange / __uerngrange)));
269 0           __ret = __tmp + (__uctype(__urng()) - __urngmin);
270             }
271             while (__ret > __urange || __ret < __tmp);
272             }
273             else
274 0           __ret = __uctype(__urng()) - __urngmin;
275              
276 0           return __ret + __param.a();
277             }
278              
279              
280             template
281             template
282             typename _UniformRandomNumberGenerator>
283             void
284             uniform_int_distribution<_IntType>::
285             __generate_impl(_ForwardIterator __f, _ForwardIterator __t,
286             _UniformRandomNumberGenerator& __urng,
287             const param_type& __param)
288             {
289             __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
290             typedef typename _UniformRandomNumberGenerator::result_type
291             _Gresult_type;
292             typedef typename std::make_unsigned::type __utype;
293             typedef typename std::common_type<_Gresult_type, __utype>::type
294             __uctype;
295              
296             const __uctype __urngmin = __urng.min();
297             const __uctype __urngmax = __urng.max();
298             const __uctype __urngrange = __urngmax - __urngmin;
299             const __uctype __urange
300             = __uctype(__param.b()) - __uctype(__param.a());
301              
302             __uctype __ret;
303              
304             if (__urngrange > __urange)
305             {
306             if (__detail::_Power_of_2(__urngrange + 1)
307             && __detail::_Power_of_2(__urange + 1))
308             {
309             while (__f != __t)
310             {
311             __ret = __uctype(__urng()) - __urngmin;
312             *__f++ = (__ret & __urange) + __param.a();
313             }
314             }
315             else
316             {
317             // downscaling
318             const __uctype __uerange = __urange + 1; // __urange can be zero
319             const __uctype __scaling = __urngrange / __uerange;
320             const __uctype __past = __uerange * __scaling;
321             while (__f != __t)
322             {
323             do
324             __ret = __uctype(__urng()) - __urngmin;
325             while (__ret >= __past);
326             *__f++ = __ret / __scaling + __param.a();
327             }
328             }
329             }
330             else if (__urngrange < __urange)
331             {
332             // upscaling
333             /*
334             Note that every value in [0, urange]
335             can be written uniquely as
336              
337             (urngrange + 1) * high + low
338              
339             where
340              
341             high in [0, urange / (urngrange + 1)]
342              
343             and
344              
345             low in [0, urngrange].
346             */
347             __uctype __tmp; // wraparound control
348             while (__f != __t)
349             {
350             do
351             {
352             const __uctype __uerngrange = __urngrange + 1;
353             __tmp = (__uerngrange * operator()
354             (__urng, param_type(0, __urange / __uerngrange)));
355             __ret = __tmp + (__uctype(__urng()) - __urngmin);
356             }
357             while (__ret > __urange || __ret < __tmp);
358             *__f++ = __ret;
359             }
360             }
361             else
362             while (__f != __t)
363             *__f++ = __uctype(__urng()) - __urngmin + __param.a();
364             }
365              
366             _GLIBCXX_END_NAMESPACE_VERSION
367             } // namespace std
368              
369             #endif