QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
burley2020sobolrsg.cpp
Go to the documentation of this file.
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2023 Peter Caspers
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
22#include <ql/errors.hpp>
23
24namespace QuantLib {
25
27 unsigned long seed,
28 SobolRsg::DirectionIntegers directionIntegers,
29 unsigned long scrambleSeed)
30 : dimensionality_(dimensionality), seed_(seed), directionIntegers_(directionIntegers),
31 integerSequence_(dimensionality), sequence_(std::vector<Real>(dimensionality), 1.0) {
32 reset();
33 group4Seeds_.resize((dimensionality_ - 1) / 4 + 1);
34 MersenneTwisterUniformRng mt(scrambleSeed);
35 for (auto& s : group4Seeds_) {
36 s = static_cast<std::uint32_t>(mt.nextInt32());
37 }
38 }
39
41 sobolRsg_ = ext::make_shared<SobolRsg>(dimensionality_, seed_, directionIntegers_, false);
43 }
44
45 const std::vector<std::uint32_t>& Burley2020SobolRsg::skipTo(std::uint32_t n) const {
46 reset();
47 for (Size k = 0; k < n + 1; ++k) {
49 }
50 return integerSequence_;
51 }
52
53 namespace {
54
55 // for reverseBits() see http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable
56
57 const std::uint8_t bitReverseTable[] = {
58 0U, 128U, 64U, 192U, 32U, 160U, 96U, 224U, 16U, 144U, 80U, 208U, 48U, 176U,
59 112U, 240U, 8U, 136U, 72U, 200U, 40U, 168U, 104U, 232U, 24U, 152U, 88U, 216U,
60 56U, 184U, 120U, 248U, 4U, 132U, 68U, 196U, 36U, 164U, 100U, 228U, 20U, 148U,
61 84U, 212U, 52U, 180U, 116U, 244U, 12U, 140U, 76U, 204U, 44U, 172U, 108U, 236U,
62 28U, 156U, 92U, 220U, 60U, 188U, 124U, 252U, 2U, 130U, 66U, 194U, 34U, 162U,
63 98U, 226U, 18U, 146U, 82U, 210U, 50U, 178U, 114U, 242U, 10U, 138U, 74U, 202U,
64 42U, 170U, 106U, 234U, 26U, 154U, 90U, 218U, 58U, 186U, 122U, 250U, 6U, 134U,
65 70U, 198U, 38U, 166U, 102U, 230U, 22U, 150U, 86U, 214U, 54U, 182U, 118U, 246U,
66 14U, 142U, 78U, 206U, 46U, 174U, 110U, 238U, 30U, 158U, 94U, 222U, 62U, 190U,
67 126U, 254U, 1U, 129U, 65U, 193U, 33U, 161U, 97U, 225U, 17U, 145U, 81U, 209U,
68 49U, 177U, 113U, 241U, 9U, 137U, 73U, 201U, 41U, 169U, 105U, 233U, 25U, 153U,
69 89U, 217U, 57U, 185U, 121U, 249U, 5U, 133U, 69U, 197U, 37U, 165U, 101U, 229U,
70 21U, 149U, 85U, 213U, 53U, 181U, 117U, 245U, 13U, 141U, 77U, 205U, 45U, 173U,
71 109U, 237U, 29U, 157U, 93U, 221U, 61U, 189U, 125U, 253U, 3U, 131U, 67U, 195U,
72 35U, 163U, 99U, 227U, 19U, 147U, 83U, 211U, 51U, 179U, 115U, 243U, 11U, 139U,
73 75U, 203U, 43U, 171U, 107U, 235U, 27U, 155U, 91U, 219U, 59U, 187U, 123U, 251U,
74 7U, 135U, 71U, 199U, 39U, 167U, 103U, 231U, 23U, 151U, 87U, 215U, 55U, 183U,
75 119U, 247U, 15U, 143U, 79U, 207U, 47U, 175U, 111U, 239U, 31U, 159U, 95U, 223U,
76 63U, 191U, 127U, 255U};
77
78 inline std::uint32_t reverseBits(std::uint32_t x) {
79 return (bitReverseTable[x & 0xff] << 24) | (bitReverseTable[(x >> 8) & 0xff] << 16) |
80 (bitReverseTable[(x >> 16) & 0xff] << 8) | (bitReverseTable[(x >> 24) & 0xff]);
81 }
82
83 inline std::uint32_t laine_karras_permutation(std::uint32_t x, std::uint32_t seed) {
84 x += seed;
85 x ^= x * 0x6c50b47cU;
86 x ^= x * 0xb82f1e52U;
87 x ^= x * 0xc7afe638U;
88 x ^= x * 0x8d22f6e6U;
89 return x;
90 }
91
92 inline std::uint32_t nested_uniform_scramble(std::uint32_t x, std::uint32_t seed) {
93 x = reverseBits(x);
94 x = laine_karras_permutation(x, seed);
95 x = reverseBits(x);
96 return x;
97 }
98
99 // the results depend a lot on the details of the hash_combine() function that is used
100 // we use hash_combine() calling hash(), hash_mix() as implemented here:
101 // https://github.com/boostorg/container_hash/blob/boost-1.83.0/include/boost/container_hash/hash.hpp#L560
102 // https://github.com/boostorg/container_hash/blob/boost-1.83.0/include/boost/container_hash/hash.hpp#L115
103 // https://github.com/boostorg/container_hash/blob/boost-1.83.0/include/boost/container_hash/detail/hash_mix.hpp#L67
104
105 inline std::uint64_t local_hash_mix(std::uint64_t x) {
106 const std::uint64_t m = 0xe9846af9b1a615d;
107 x ^= x >> 32;
108 x *= m;
109 x ^= x >> 32;
110 x *= m;
111 x ^= x >> 28;
112 return x;
113 }
114
115 inline std::uint64_t local_hash(const std::uint64_t v) {
116 std::uint64_t seed = 0;
117 seed = (v >> 32) + local_hash_mix(seed);
118 seed = (v & 0xFFFFFFFF) + local_hash_mix(seed);
119 return seed;
120 }
121
122 inline std::uint64_t local_hash_combine(std::uint64_t x, const uint64_t v) {
123 return local_hash_mix(x + 0x9e3779b9 + local_hash(v));
124 }
125 }
126
127 const std::vector<std::uint32_t>& Burley2020SobolRsg::nextInt32Sequence() const {
128 auto n = nested_uniform_scramble(nextSequenceCounter_, group4Seeds_[0]);
129 const auto& seq = sobolRsg_->skipTo(n);
130 std::copy(seq.begin(), seq.end(), integerSequence_.begin());
131 Size i = 0, group = 0;
132 do {
133 std::uint64_t seed = group4Seeds_[group++];
134 for (Size g = 0; g < 4 && i < dimensionality_; ++g, ++i) {
135 seed = local_hash_combine(seed, g);
137 nested_uniform_scramble(integerSequence_[i], static_cast<std::uint32_t>(seed));
138 }
139 } while (i < dimensionality_);
141 "Burley2020SobolRsg::nextIn32Sequence(): period exceeded");
142 return integerSequence_;
143 }
144
146 const std::vector<std::uint32_t>& v = nextInt32Sequence();
147 // normalize to get a double in (0,1)
148 for (Size k = 0; k < dimensionality_; ++k) {
149 sequence_.value[k] = static_cast<double>(v[k]) / 4294967296.0;
150 }
151 return sequence_;
152 }
153}
scrambled Sobol sequence following Burley, 2020
const std::vector< std::uint32_t > & skipTo(std::uint32_t n) const
SobolRsg::DirectionIntegers directionIntegers_
const std::vector< std::uint32_t > & nextInt32Sequence() const
ext::shared_ptr< SobolRsg > sobolRsg_
std::vector< std::uint32_t > group4Seeds_
const SobolRsg::sample_type & nextSequence() const
std::vector< std::uint32_t > integerSequence_
Burley2020SobolRsg(Size dimensionality, unsigned long seed=42, SobolRsg::DirectionIntegers directionIntegers=SobolRsg::Jaeckel, unsigned long scrambleSeed=43)
Uniform random number generator.
unsigned long nextInt32() const
return a random integer in the [0,0xffffffff]-interval
Classes and functions for error handling.
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
QL_REAL Real
real number
Definition: types.hpp:50
std::size_t Size
size of a container
Definition: types.hpp:58
Mersenne Twister uniform random number generator.
Definition: any.hpp:35
STL namespace.
ext::shared_ptr< BlackVolTermStructure > v