Coverage Report

Created: 2025-08-05 06:45

/src/quantlib/ql/math/randomnumbers/xoshiro256starstaruniformrng.hpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2023 Ralf Konrad Eckel
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
20
// NOTE: The following copyright notice applies to the
21
// original C implementation https://prng.di.unimi.it/xoshiro256starstar.c
22
// that has been used for this class.
23
24
/*  Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
25
26
To the extent possible under law, the author has dedicated all copyright
27
and related and neighboring rights to this software to the public domain
28
worldwide. This software is distributed without any warranty.
29
30
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
31
32
/*! \file xoshiro256starstaruniformrng.hpp
33
    \brief xoshiro256** uniform random number generator
34
*/
35
36
#ifndef quantlib_xoshiro256starstar_uniform_rng_hpp
37
#define quantlib_xoshiro256starstar_uniform_rng_hpp
38
39
#include <ql/methods/montecarlo/sample.hpp>
40
#include <ql/types.hpp>
41
#include <cstdint>
42
43
namespace QuantLib {
44
45
    //! Uniform random number generator
46
    /*! xoshiro256** random number generator of period 2**256-1
47
48
        For more details see
49
            https://prng.di.unimi.it/
50
        and its reference implementation
51
            https://prng.di.unimi.it/xoshiro256starstar.c
52
53
        \test the correctness of the returned values is tested by checking them
54
               against the reference implementation in c.
55
    */
56
    class Xoshiro256StarStarUniformRng {
57
      public:
58
        typedef Sample<Real> sample_type;
59
60
        /*! If the given seed is 0, a random seed will be chosen based on clock(). */
61
        explicit Xoshiro256StarStarUniformRng(std::uint64_t seed = 0);
62
63
        /*! Make sure that s0, s1, s2 and s3 are chosen randomly.
64
         * Otherwise, the results of the first random numbers might not be well distributed.
65
         * Especially s0 = s1 = s2 = s3 = 0 does not work and will always return 0. */
66
        Xoshiro256StarStarUniformRng(std::uint64_t s0, std::uint64_t s1, std::uint64_t s2, std::uint64_t s3);
67
68
        /*! returns a sample with weight 1.0 containing a random number
69
         * in the (0.0, 1.0) interval */
70
0
        sample_type next() const { return {nextReal(), 1.0}; }
71
72
        //! return a random number in the (0.0, 1.0)-interval
73
0
        Real nextReal() const { return (Real(nextInt64() >> 11) + 0.5) * (1.0 / Real(1ULL << 53)); }
74
75
        //! return a random integer in the [0,0xffffffffffffffffULL]-interval
76
0
        std::uint64_t nextInt64() const {
77
0
            const auto result = rotl(s1_ * 5, 7) * 9;
78
0
79
0
            const auto t = s1_ << 17;
80
0
81
0
            s2_ ^= s0_;
82
0
            s3_ ^= s1_;
83
0
            s1_ ^= s2_;
84
0
            s0_ ^= s3_;
85
0
86
0
            s2_ ^= t;
87
0
88
0
            s3_ = rotl(s3_, 45);
89
0
90
0
            return result;
91
0
        }
92
93
      private:
94
0
        static std::uint64_t rotl(std::uint64_t x, std::int32_t k) { return (x << k) | (x >> (64 - k)); }
95
        mutable std::uint64_t s0_, s1_, s2_, s3_;
96
    };
97
98
}
99
100
#endif