#ifndef NDPSEUDORANDOMNUMBERGENERATORTEST_H_ #define NDPSEUDORANDOMNUMBERGENERATORTEST_H_ #include <cxxtest/TestSuite.h> #include "MantidKernel/NDPseudoRandomNumberGenerator.h" #include "MantidKernel/MersenneTwister.h" #include <boost/algorithm/string/predicate.hpp> #include <boost/shared_ptr.hpp> #include <boost/make_shared.hpp> using Mantid::Kernel::NDRandomNumberGenerator; class NDPseudoRandomNumberGeneratorTest : public CxxTest::TestSuite { private: typedef boost::shared_ptr<NDRandomNumberGenerator> NDGenerator_sptr; public: void test_That_Next_Always_Returns_ND_Size_Array() { NDGenerator_sptr ndRand = createTestGenerator(12345); for(int i = 0; i < 20; ++i) { std::vector<double> point = ndRand->nextPoint(); TS_ASSERT_EQUALS(static_cast<unsigned int>(point.size()), 3); } } void test_That_Restart_Is_Passed_On_Correctly() { NDGenerator_sptr ndRand = createTestGenerator(12345); std::vector<double> firstPoint = ndRand->nextPoint(); TS_ASSERT_THROWS_NOTHING(ndRand->restart()); std::vector<double> firstPointAfterReset = ndRand->nextPoint(); for(size_t i = 0; i < firstPoint.size(); ++i) { TS_ASSERT_EQUALS(firstPoint[i], firstPointAfterReset[i]); } } void test_That_Range_Of_SingleValue_Generator_Is_Respected() { const double start(2.1), end(3.4); NDGenerator_sptr ndRand = createTestGenerator(12345, start, end); std::vector<double> firstPoint = ndRand->nextPoint(); for(size_t i = 0; i < firstPoint.size(); ++i) { TS_ASSERT(firstPoint[i] >= start && firstPoint[i] <= end); } } void test_Save_Call_Restore_Gives_Sequence_From_Saved_Point() { NDGenerator_sptr ndRand = createTestGenerator(12345); doNextValueCalls(25, *ndRand); // Move from start to test it doesn't just go back to beginning ndRand->save(); const size_t ncheck(20); auto firstValues = doNextValueCalls(ncheck, *ndRand); ndRand->restore(); auto secondValues = doNextValueCalls(ncheck, *ndRand); for(size_t i = 0; i < ncheck; ++i) { TS_ASSERT(boost::algorithm::equals(firstValues[i], secondValues[i])); } } private: boost::shared_ptr<NDRandomNumberGenerator> createTestGenerator(const size_t seedValue, const double start = -1.0, const double end = -1.0) { using namespace Mantid::Kernel; typedef NDPseudoRandomNumberGenerator<MersenneTwister> NDMersenneTwister; const unsigned int ndims(3); if(start > 0.0 && end > 0.0) return boost::make_shared<NDMersenneTwister>(ndims, seedValue, start, end); else return boost::make_shared<NDMersenneTwister>(ndims, seedValue); } std::vector<std::vector<double>> doNextValueCalls(const unsigned int ncalls, NDRandomNumberGenerator &randGen) { std::vector<std::vector<double>> values(ncalls); for(unsigned int i = 0; i < ncalls; ++i) { values[i] = randGen.nextPoint(); } return values; } }; #endif //NDPSEUDORANDOMNUMBERGENERATORTEST_H_