// -*- C++ -*- // ============================================================================ /** * @file randomize.h * * Randomize the contents of an array. * * @author Ossama Othman * * @note Based on code originally found in test_config.h and Test_Output.cpp */ // ============================================================================ #ifndef ACE_TESTS_RANDOMIZE_H #define ACE_TESTS_RANDOMIZE_H #include "ace/OS_NS_stdlib.h" #include #include namespace { /** * @class randomize_index * * @brief Functor that randomly swaps the order of two array * elements. * * @internal Do not directly use this class. Use the @c randomize() * function template found below instead. * * This functor generates random array index using high-order bits (e.g., * MAX_VAL * rand() / (RAND_MAX + 1.0)) rather than low-order ones * (e.g. rand() % MAX_VAL) to improve randomness. The array element * reference by that index is then swapped with the array element * provided to the functor. * * @note The improved randomness may be overkill for this functor's * intended use cases, but it is a good thing to practice/have * nonetheless. * * @see Numerical Recipes in C: The Art of Scientific Computing * (William H. Press, Brian P. Flannery, Saul A. Teukolsky, * William T. Vetterling; New York: Cambridge University Press, * 1992 (2nd ed., p. 277). */ template class randomize_element : public std::unary_function { public: randomize_element (T * array, size_t size, unsigned int seed) : array_ (array) , coefficient_ (static_cast (size) / (RAND_MAX + 1.0f)) , seed_ (seed) { } void operator() (T & value) // We need this to be a reference! { size_t const index = static_cast ( this->coefficient_ * ACE_OS::rand_r (&this->seed_)); // Swap rather than assign so that we don't lose the original // value. std::swap (value, this->array_[index]); } private: // The array. T * const array_; // Factor out the constant coefficient. double const coefficient_; // Random number generator seed value. unsigned int seed_; }; /** * @fn randomize * * @brief Randomize the order of elements in an array. * * @param array The array whose elements will be reordered * randomly. * @param size The number of elements in the array. * @param seed The random number generator seed value. A default * value is provided so that the generated random number order may be "repeatable" if so desired. * * This function template randomizes the order of elements in an * array of any type. It is also reentrant (unless the array itself * is accessed by multiple threads). * @par * Sample usage: * @par * \verbatim static size_t const NUM_TIMES = 100; ACE_Time_Value times[NUM_TIMES] = { ... }; randomize (times, NUM_TIMES, static_cast (ACE_OS::time (0L))); \endverbatim */ template void randomize (T * array, size_t size, unsigned int seed = 0) { // Randomize all elements of the array. std::for_each (array, array + size, randomize_element (array, size, seed)); } } #endif /* !ACE_TESTS_RANDOMIZE_H */