You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

285 lines
8.4 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: rangelib/random_range.hpp
  3. *
  4. * Purpose: Random number range class.
  5. *
  6. * Created: 31st May 2004
  7. * Updated: 10th August 2009
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 2004-2009, Matthew Wilson and Synesis Software
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright notice, this
  18. * list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  23. * any contributors may be used to endorse or promote products derived from
  24. * this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * ////////////////////////////////////////////////////////////////////// */
  39. /** \file rangelib/random_range.hpp Random number range class */
  40. #ifndef RANGELIB_INCL_RANGELIB_HPP_RANDOM_RANGE
  41. #define RANGELIB_INCL_RANGELIB_HPP_RANDOM_RANGE
  42. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  43. # define RANGELIB_VER_RANGELIB_HPP_RANDOM_RANGE_MAJOR 2
  44. # define RANGELIB_VER_RANGELIB_HPP_RANDOM_RANGE_MINOR 2
  45. # define RANGELIB_VER_RANGELIB_HPP_RANDOM_RANGE_REVISION 3
  46. # define RANGELIB_VER_RANGELIB_HPP_RANDOM_RANGE_EDIT 30
  47. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  48. /* /////////////////////////////////////////////////////////////////////////
  49. * Auto-generation and compatibility
  50. */
  51. /*
  52. [Incompatibilies-start]
  53. STLSOFT_COMPILER_IS_MSVC: _MSC_VER < 1200
  54. STLSOFT_COMPILER_IS_MWERKS: (__MWERKS__ & 0xFF00) < 0x3000
  55. [Incompatibilies-end]
  56. */
  57. /* /////////////////////////////////////////////////////////////////////////
  58. * Includes
  59. */
  60. #ifndef RANGELIB_INCL_RANGELIB_HPP_RANGELIB
  61. # include <rangelib/rangelib.hpp>
  62. #endif /* !RANGELIB_INCL_RANGELIB_HPP_RANGELIB */
  63. #ifndef RANGELIB_INCL_RANGELIB_HPP_RANGE_CATEGORIES
  64. # include <rangelib/range_categories.hpp>
  65. #endif /* !RANGELIB_INCL_RANGELIB_HPP_RANGE_CATEGORIES */
  66. #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_OPERATOR_BOOL
  67. # include <stlsoft/util/operator_bool.hpp>
  68. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_OPERATOR_BOOL */
  69. #ifndef STLSOFT_INCL_H_STDLIB
  70. # define STLSOFT_INCL_H_STDLIB
  71. # include <stdlib.h> // for rand(), srand()
  72. #endif /* !STLSOFT_INCL_H_STDLIB */
  73. /* /////////////////////////////////////////////////////////////////////////
  74. * Namespace
  75. */
  76. #ifndef RANGELIB_NO_NAMESPACE
  77. # if defined(_STLSOFT_NO_NAMESPACE) || \
  78. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  79. /* There is no stlsoft namespace, so must define ::rangelib */
  80. namespace rangelib
  81. {
  82. # else
  83. /* Define stlsoft::rangelib_project */
  84. namespace stlsoft
  85. {
  86. namespace rangelib_project
  87. {
  88. # endif /* _STLSOFT_NO_NAMESPACE */
  89. #endif /* !RANGELIB_NO_NAMESPACE */
  90. /* /////////////////////////////////////////////////////////////////////////
  91. * Classes
  92. */
  93. /** \brief This range class represents a range of random numbers.
  94. *
  95. * \ingroup group__library__rangelib
  96. *
  97. * It is categoried as a Notional Range
  98. *
  99. * It could be used as follows
  100. \code
  101. // Create a range of 10 values, whose value are between -100 and +100
  102. stlsoft::random_range r(10, -100, +100);
  103. // Dump them to stdout
  104. stlsoft::r_copy(r, std::ostream_iterator<int>(" "));
  105. \endcode
  106. */
  107. class random_range
  108. : public notional_range_tag
  109. {
  110. /// \name Types
  111. /// @{
  112. public:
  113. typedef int value_type;
  114. typedef notional_range_tag range_tag_type;
  115. typedef random_range class_type;
  116. /// @}
  117. /// \name Construction
  118. /// @{
  119. public:
  120. /// Constructs a random range
  121. ///
  122. /// \param numValues The number of values in the range
  123. /// \param minValue The lower limit of the random number range
  124. /// \param maxValue The upper limit of the random number range
  125. random_range(ss_size_t numValues, value_type minValue = 0, value_type maxValue = RAND_MAX)
  126. : m_numValues(numValues)
  127. , m_minValue(minValue)
  128. , m_maxValue(maxValue)
  129. , m_position(0)
  130. , m_value(next_value_(minValue, maxValue))
  131. {
  132. STLSOFT_ASSERT(minValue <= maxValue);
  133. STLSOFT_ASSERT((maxValue - minValue) <= RAND_MAX);
  134. }
  135. /// @}
  136. /// \name Notional Range methods
  137. /// @{
  138. private:
  139. STLSOFT_DEFINE_OPERATOR_BOOL_TYPES(class_type, operator_bool_generator_type, operator_bool_type);
  140. public:
  141. /// Indicates whether the range is open
  142. ss_bool_t is_open() const
  143. {
  144. return m_position != m_numValues;
  145. }
  146. /// Returns the current value in the range
  147. value_type current() const
  148. {
  149. STLSOFT_MESSAGE_ASSERT("Attempting to access the value of a closed range", is_open());
  150. return m_value;
  151. }
  152. /// Advances the current position in the range
  153. class_type& advance()
  154. {
  155. STLSOFT_MESSAGE_ASSERT("Attempting to advance a closed range", is_open());
  156. ++m_position;
  157. m_value = next_value_(m_minValue, m_maxValue);
  158. return *this;
  159. }
  160. /// Indicates whether the range is open
  161. operator operator_bool_type() const
  162. {
  163. return operator_bool_generator_type::translate(is_open());
  164. }
  165. /// Returns the current value in the range
  166. value_type operator *() const
  167. {
  168. return current();
  169. }
  170. /// Advances the current position in the range
  171. class_type& operator ++()
  172. {
  173. return advance();
  174. }
  175. /// Advances the current position in the range, returning a copy of the
  176. /// range prior to its being advanced
  177. class_type operator ++(int)
  178. {
  179. class_type ret(*this);
  180. operator ++();
  181. return ret;
  182. }
  183. /// @}
  184. /// \name Attributes
  185. /// @{
  186. public:
  187. /// The lower limit of the random number range
  188. value_type minimum() const
  189. {
  190. return m_minValue;
  191. }
  192. /// The upper limit of the random number range
  193. value_type maximum() const
  194. {
  195. return m_maxValue;
  196. }
  197. /// @}
  198. /// \name Comparison
  199. /// @{
  200. public:
  201. /// Evaluates whether two ranges are equal
  202. bool operator ==(class_type const& /* rhs */) const
  203. {
  204. return false;
  205. }
  206. /// Evaluates whether two ranges are unequal
  207. bool operator !=(class_type const& rhs) const
  208. {
  209. return ! operator ==(rhs);
  210. }
  211. /// @}
  212. /// \name Implementation
  213. /// @{
  214. private:
  215. static value_type next_value_(value_type minValue, value_type maxValue)
  216. {
  217. return (maxValue - minValue) ? minValue + (rand() % (maxValue - minValue)) : 0;
  218. }
  219. /// @}
  220. // Members
  221. private:
  222. const ss_size_t m_numValues;
  223. const int m_minValue;
  224. const int m_maxValue;
  225. ss_size_t m_position;
  226. int m_value;
  227. // Not to be implemented
  228. private:
  229. class_type& operator =(class_type const&);
  230. };
  231. ////////////////////////////////////////////////////////////////////////////
  232. // Unit-testing
  233. #ifdef STLSOFT_UNITTEST
  234. # include "./unittest/random_range_unittest_.h"
  235. #endif /* STLSOFT_UNITTEST */
  236. /* ////////////////////////////////////////////////////////////////////// */
  237. #ifndef RANGELIB_NO_NAMESPACE
  238. # if defined(_STLSOFT_NO_NAMESPACE) || \
  239. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  240. } // namespace rangelib
  241. # else
  242. } // namespace rangelib_project
  243. } // namespace stlsoft
  244. # endif /* _STLSOFT_NO_NAMESPACE */
  245. #endif /* !RANGELIB_NO_NAMESPACE */
  246. /* ////////////////////////////////////////////////////////////////////// */
  247. #endif /* !RANGELIB_INCL_RANGELIB_HPP_RANDOM_RANGE */
  248. /* ///////////////////////////// end of file //////////////////////////// */