1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2004 StatPro Italia srl
5 Copyright (C) 2004 Walter Penschke
6
7 This file is part of QuantLib, a free-software/open-source library
8 for financial quantitative analysts and developers - http://quantlib.org/
9
10 QuantLib is free software: you can redistribute it and/or modify it
11 under the terms of the QuantLib license. You should have received a
12 copy of the license along with this program; if not, please email
13 <quantlib-dev@lists.sf.net>. The license is also available online at
14 <http://quantlib.org/license.shtml>.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the license for more details.
19*/
20
21#include "rngtraits.hpp"
22#include "utilities.hpp"
23#include <ql/math/randomnumbers/rngtraits.hpp>
24#include <ql/math/randomnumbers/ranluxuniformrng.hpp>
25#include <ql/math/comparison.hpp>
26
27using namespace QuantLib;
28using namespace boost::unit_test_framework;
29
30void RngTraitsTest::testGaussian() {
31
32 BOOST_TEST_MESSAGE("Testing Gaussian pseudo-random number generation...");
33
34 PseudoRandom::rsg_type rsg =
35 PseudoRandom::make_sequence_generator(dimension: 100, seed: 1234);
36
37 const std::vector<Real>& values = rsg.nextSequence().value;
38 Real sum = 0.0;
39 for (Real value : values)
40 sum += value;
41
42 Real stored = 4.09916;
43 Real tolerance = 1.0e-5;
44 if (std::fabs(x: sum - stored) > tolerance)
45 BOOST_FAIL("the sum of the samples does not match the stored value\n"
46 << " calculated: " << sum << "\n"
47 << " expected: " << stored);
48}
49
50
51void RngTraitsTest::testDefaultPoisson() {
52
53 BOOST_TEST_MESSAGE("Testing Poisson pseudo-random number generation...");
54
55 PoissonPseudoRandom::icInstance =
56 ext::shared_ptr<InverseCumulativePoisson>();
57 PoissonPseudoRandom::rsg_type rsg =
58 PoissonPseudoRandom::make_sequence_generator(dimension: 100, seed: 1234);
59
60 const std::vector<Real>& values = rsg.nextSequence().value;
61 Real sum = 0.0;
62 for (Real value : values)
63 sum += value;
64
65 Real stored = 108.0;
66 if (!close(x: sum, y: stored))
67 BOOST_FAIL("the sum of the samples does not match the stored value\n"
68 << " calculated: " << sum << "\n"
69 << " expected: " << stored);
70}
71
72
73void RngTraitsTest::testCustomPoisson() {
74
75 BOOST_TEST_MESSAGE("Testing custom Poisson pseudo-random number generation...");
76
77 PoissonPseudoRandom::icInstance =
78 ext::make_shared<InverseCumulativePoisson>(
79 args: 4.0);
80 PoissonPseudoRandom::rsg_type rsg =
81 PoissonPseudoRandom::make_sequence_generator(dimension: 100, seed: 1234);
82
83 const std::vector<Real>& values = rsg.nextSequence().value;
84 Real sum = 0.0;
85 for (Real value : values)
86 sum += value;
87
88 Real stored = 409.0;
89 if (!close(x: sum, y: stored))
90 BOOST_FAIL("the sum of the samples does not match the stored value\n"
91 << " calculated: " << sum << "\n"
92 << " expected: " << stored);
93}
94
95void RngTraitsTest::testRanLux() {
96 BOOST_TEST_MESSAGE("Testing known RanLux sequence...");
97
98 Ranlux3UniformRng ranlux3(2938723U);
99 Ranlux4UniformRng ranlux4(4390109U);
100
101 const Real ranlux3_expected[] = {
102 0.307448851544538826, 0.666313657894363587, 0.698528013702823358,
103 0.0217381272445322793,0.862964516238161394, 0.909193419106014034,
104 0.674484308686746914, 0.849607570377191479, 0.054626078713596371,
105 0.416474163715683687
106 };
107
108 const Real ranlux4_expected[] = {
109 0.222209169374078641, 0.420181950405986271, 0.0302156663005135329,
110 0.0836259809475237148,0.480549766594993599, 0.723472021829124401,
111 0.905819507194266293, 0.54072519936540786, 0.445908421479817463,
112 0.651084788437518824
113 };
114
115 for (Size i=0; i < 10010; ++i) {
116 ranlux3.next();
117 ranlux4.next();
118 }
119
120 for (Size i =0; i < 10; ++i) {
121 if (!close_enough(x: ranlux3.next().value, y: ranlux3_expected[i]))
122 BOOST_FAIL("failed to reproduce ranlux3 numbers...");
123
124 if (!close_enough(x: ranlux4.next().value, y: ranlux4_expected[i]))
125 BOOST_FAIL("failed to reproduce ranlux4 numbers...");
126 }
127}
128
129test_suite* RngTraitsTest::suite() {
130 auto* suite = BOOST_TEST_SUITE("RNG traits tests");
131 suite->add(QUANTLIB_TEST_CASE(&RngTraitsTest::testGaussian));
132 suite->add(QUANTLIB_TEST_CASE(&RngTraitsTest::testDefaultPoisson));
133 suite->add(QUANTLIB_TEST_CASE(&RngTraitsTest::testCustomPoisson));
134 suite->add(QUANTLIB_TEST_CASE(&RngTraitsTest::testRanLux));
135 return suite;
136}
137
138

source code of quantlib/test-suite/rngtraits.cpp