Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/random/xoshiro.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002  * Copyright Matt Borland 2022 - 2025.
0003  * Distributed under the Boost Software License, Version 1.0. (See
0004         * accompanying file LICENSE_1_0.txt or copy at
0005  * http://www.boost.org/LICENSE_1_0.txt)
0006  *
0007  * See http://www.boost.org for most recent version including documentation.
0008  *
0009  * $Id$
0010  */
0011 
0012 #ifndef BOOST_RANDOM_XOSHIRO_HPP
0013 #define BOOST_RANDOM_XOSHIRO_HPP
0014 
0015 #include <boost/random/detail/config.hpp>
0016 #include <boost/random/detail/xoshiro_base.hpp>
0017 #include <boost/core/bit.hpp>
0018 #include <array>
0019 #include <cstdint>
0020 
0021 namespace boost {
0022 namespace random {
0023 
0024 /**
0025  * This is xoshiro256++ 1.0, one of our all-purpose, rock-solid generators.
0026  * It has excellent (sub-ns) speed, a state (256 bits) that is large
0027  * enough for any parallel application, and it passes all tests we are
0028  * aware of.
0029  *
0030  * For generating just floating-point numbers, xoshiro256+ is even faster.
0031  */
0032 class xoshiro256pp final : public detail::xoshiro_base<xoshiro256pp, 4>
0033 {
0034 private:
0035 
0036     using Base = detail::xoshiro_base<xoshiro256pp, 4>;
0037 
0038 public:
0039 
0040     using Base::Base;
0041 
0042     inline result_type next() noexcept
0043     {
0044         const std::uint64_t result = boost::core::rotl(state_[0] + state_[3], 23) + state_[0];
0045         const std::uint64_t t = state_[1] << 17;
0046 
0047         state_[2] ^= state_[0];
0048         state_[3] ^= state_[1];
0049         state_[1] ^= state_[2];
0050         state_[0] ^= state_[3];
0051 
0052         state_[2] ^= t;
0053 
0054         state_[3] = boost::core::rotl(state_[3], 45);
0055 
0056         return result;
0057     }
0058 };
0059 
0060 /**
0061  * This is xoshiro256+ 1.0, our best and fastest generator for floating-point
0062  * numbers. We suggest to use its upper bits for floating-point
0063  * generation, as it is slightly faster than xoshiro256++/xoshiro256**. It
0064  * passes all tests we are aware of except for the lowest three bits,
0065  * which might fail linearity tests (and just those), so if low linear
0066  * complexity is not considered an issue (as it is usually the case) it
0067  * can be used to generate 64-bit outputs, too.
0068  */
0069 
0070 class xoshiro256d final : public detail::xoshiro_base<xoshiro256d, 4, double>
0071 {
0072 private:
0073 
0074     using Base = detail::xoshiro_base<xoshiro256d, 4, double>;
0075 
0076 public:
0077 
0078     using Base::Base;
0079 
0080     inline std::uint64_t next_int() noexcept
0081     {
0082         const std::uint64_t result = state_[0] + state_[3];
0083         const std::uint64_t t = state_[1] << 17;
0084 
0085         state_[2] ^= state_[0];
0086         state_[3] ^= state_[1];
0087         state_[1] ^= state_[2];
0088         state_[0] ^= state_[3];
0089 
0090         state_[2] ^= t;
0091 
0092         state_[3] = boost::core::rotl(state_[3], 45);
0093 
0094         return result;
0095     }
0096 
0097     inline result_type next() noexcept
0098     {
0099         #ifdef BOOST_RANDOM_HAS_HEX_FLOAT
0100         return static_cast<double>((next_int() >> 11)) * 0x1.0p-53;
0101         #else
0102         return static_cast<double>((next_int() >> 11)) * 1.11022302462515654e-16;
0103         #endif
0104     }
0105 
0106     static constexpr result_type (min)() noexcept
0107     {
0108         #ifdef BOOST_RANDOM_HAS_HEX_FLOAT
0109         return static_cast<double>((std::numeric_limits<std::uint64_t>::min)() >> 11) * 0x1.0p-53;
0110         #else
0111         return static_cast<double>((std::numeric_limits<std::uint64_t>::min)() >> 11) * 1.11022302462515654e-16;
0112         #endif
0113     }
0114 
0115     static constexpr result_type (max)() noexcept
0116     {
0117         #ifdef BOOST_RANDOM_HAS_HEX_FLOAT
0118         return static_cast<double>((std::numeric_limits<std::uint64_t>::max)()) * 0x1.0p-53;
0119         #else
0120         return static_cast<double>((std::numeric_limits<std::uint64_t>::max)()) * 1.11022302462515654e-16;
0121         #endif
0122     }
0123 };
0124 
0125 /**
0126  * This is xoshiro256** 1.0, one of our all-purpose, rock-solid
0127  * generators. It has excellent (sub-ns) speed, a state (256 bits) that is
0128  * large enough for any parallel application, and it passes all tests we
0129  * are aware of.
0130  *
0131  * For generating just floating-point numbers, xoshiro256+ is even faster.
0132  */
0133 
0134 class xoshiro256mm final : public detail::xoshiro_base<xoshiro256mm, 4>
0135 {
0136 private:
0137 
0138     using Base = detail::xoshiro_base<xoshiro256mm, 4>;
0139 
0140 public:
0141 
0142     using Base::Base;
0143 
0144     inline result_type next() noexcept
0145     {
0146         const std::uint64_t result = boost::core::rotl(state_[1] * 5, 7) * 9U;
0147         const std::uint64_t t = state_[1] << 17;
0148 
0149         state_[2] ^= state_[0];
0150         state_[3] ^= state_[1];
0151         state_[1] ^= state_[2];
0152         state_[0] ^= state_[3];
0153 
0154         state_[2] ^= t;
0155 
0156         state_[3] = boost::core::rotl(state_[3], 45);
0157 
0158         return result;
0159     }
0160 };
0161 
0162 /**
0163  * This is xoshiro512++ 1.0, one of our all-purpose, rock-solid
0164  * generators. It has excellent (about 1ns) speed, a state (512 bits) that
0165  * is large enough for any parallel application, and it passes all tests
0166  * we are aware of.
0167  *
0168  * For generating just floating-point numbers, xoshiro512+ is even faster.
0169  *
0170  * The state must be seeded so that it is not everywhere zero. If you have
0171  * a 64-bit seed, we suggest to seed a splitmix64 generator and use its
0172  * output to fill s.
0173  */
0174 
0175 class xoshiro512pp final : public detail::xoshiro_base<xoshiro512pp, 8>
0176 {
0177 private:
0178 
0179     using Base = detail::xoshiro_base<xoshiro512pp, 8>;
0180 
0181 public:
0182 
0183     using Base::Base;
0184 
0185     inline result_type next() noexcept
0186     {
0187         const std::uint64_t result = boost::core::rotl(state_[0] + state_[2], 17) + state_[2];
0188 
0189         const std::uint64_t t = state_[1] << 11;
0190 
0191         state_[2] ^= state_[0];
0192         state_[5] ^= state_[1];
0193         state_[1] ^= state_[2];
0194         state_[7] ^= state_[3];
0195         state_[3] ^= state_[4];
0196         state_[4] ^= state_[5];
0197         state_[0] ^= state_[6];
0198         state_[6] ^= state_[7];
0199 
0200         state_[6] ^= t;
0201 
0202         state_[7] = boost::core::rotl(state_[7], 21);
0203 
0204         return result;
0205     }
0206 };
0207 
0208 /**
0209  * This is xoshiro512** 1.0, one of our all-purpose, rock-solid generators
0210  * with increased state size. It has excellent (about 1ns) speed, a state
0211  * (512 bits) that is large enough for any parallel application, and it
0212  * passes all tests we are aware of.
0213  *
0214  * For generating just floating-point numbers, xoshiro512+ is even faster.
0215  *
0216  * The state must be seeded so that it is not everywhere zero. If you have
0217  * a 64-bit seed, we suggest to seed a splitmix64 generator and use its
0218  *  output to fill s.
0219  */
0220 
0221 class xoshiro512mm final : public detail::xoshiro_base<xoshiro512mm, 8>
0222 {
0223 private:
0224 
0225     using Base = detail::xoshiro_base<xoshiro512mm, 8>;
0226 
0227 public:
0228 
0229     using Base::Base;
0230 
0231     inline result_type next() noexcept
0232     {
0233         const std::uint64_t result = boost::core::rotl(state_[1] * 5, 7) * 9;
0234 
0235         const std::uint64_t t = state_[1] << 11;
0236 
0237         state_[2] ^= state_[0];
0238         state_[5] ^= state_[1];
0239         state_[1] ^= state_[2];
0240         state_[7] ^= state_[3];
0241         state_[3] ^= state_[4];
0242         state_[4] ^= state_[5];
0243         state_[0] ^= state_[6];
0244         state_[6] ^= state_[7];
0245 
0246         state_[6] ^= t;
0247 
0248         state_[7] = boost::core::rotl(state_[7], 21);
0249 
0250         return result;
0251     }
0252 };
0253 
0254 /**
0255  * This is xoshiro512+ 1.0, our generator for floating-point numbers with
0256  * increased state size. We suggest to use its upper bits for
0257  * floating-point generation, as it is slightly faster than xoshiro512**.
0258  * It passes all tests we are aware of except for the lowest three bits,
0259  * which might fail linearity tests (and just those), so if low linear
0260  * complexity is not considered an issue (as it is usually the case) it
0261  * can be used to generate 64-bit outputs, too.
0262  *
0263  * We suggest to use a sign test to extract a random Boolean value, and
0264  * right shifts to extract subsets of bits.
0265  *
0266  * The state must be seeded so that it is not everywhere zero. If you have
0267  * a 64-bit seed, we suggest to seed a splitmix64 generator and use its
0268  *  output to fill s.
0269  */
0270 
0271 class xoshiro512d final : public detail::xoshiro_base<xoshiro512d, 8, double>
0272 {
0273 private:
0274 
0275     using Base = detail::xoshiro_base<xoshiro512d, 8, double>;
0276 
0277 public:
0278 
0279     using Base::Base;
0280 
0281     inline std::uint64_t next_int() noexcept
0282     {
0283         const std::uint64_t result = state_[0] + state_[2];
0284 
0285         const std::uint64_t t = state_[1] << 11;
0286 
0287         state_[2] ^= state_[0];
0288         state_[5] ^= state_[1];
0289         state_[1] ^= state_[2];
0290         state_[7] ^= state_[3];
0291         state_[3] ^= state_[4];
0292         state_[4] ^= state_[5];
0293         state_[0] ^= state_[6];
0294         state_[6] ^= state_[7];
0295 
0296         state_[6] ^= t;
0297 
0298         state_[7] = boost::core::rotl(state_[7], 21);
0299 
0300         return result;
0301     }
0302 
0303     inline result_type next() noexcept
0304     {
0305         #ifdef BOOST_RANDOM_HAS_HEX_FLOAT
0306         return static_cast<double>((next_int() >> 11)) * 0x1.0p-53;
0307         #else
0308         return static_cast<double>((next_int() >> 11)) * 1.11022302462515654e-16;
0309         #endif
0310     }
0311 
0312     static constexpr result_type (min)() noexcept
0313     {
0314         #ifdef BOOST_RANDOM_HAS_HEX_FLOAT
0315         return static_cast<double>((std::numeric_limits<std::uint64_t>::min)() >> 11) * 0x1.0p-53;
0316         #else
0317         return static_cast<double>((std::numeric_limits<std::uint64_t>::min)() >> 11) * 1.11022302462515654e-16;
0318         #endif
0319     }
0320 
0321     static constexpr result_type (max)() noexcept
0322     {
0323         #ifdef BOOST_RANDOM_HAS_HEX_FLOAT
0324         return static_cast<double>((std::numeric_limits<std::uint64_t>::max)() >> 11) * 0x1.0p-53;
0325         #else
0326         return static_cast<double>((std::numeric_limits<std::uint64_t>::max)() >> 11) * 1.11022302462515654e-16;
0327         #endif
0328     }
0329 };
0330 
0331 /**
0332  * This is xoshiro128++ 1.0, one of our 32-bit all-purpose, rock-solid
0333  * generators. It has excellent speed, a state size (128 bits) that is
0334  * large enough for mild parallelism, and it passes all tests we are aware
0335  * of.
0336  *
0337  * For generating just single-precision (i.e., 32-bit) floating-point
0338  * numbers, xoshiro128+ is even faster.
0339  *
0340  * The state must be seeded so that it is not everywhere zero.
0341  */
0342 class xoshiro128pp final : public detail::xoshiro_base<xoshiro128pp, 4, std::uint32_t, std::uint32_t>
0343 {
0344 private:
0345 
0346     using Base = detail::xoshiro_base<xoshiro128pp, 4, std::uint32_t, std::uint32_t>;
0347 
0348 public:
0349 
0350     using Base::Base;
0351 
0352     inline result_type next() noexcept
0353     {
0354         const std::uint32_t result = boost::core::rotl(state_[0] + state_[3], 7) + state_[0];
0355 
0356         const std::uint32_t t = state_[1] << 9;
0357 
0358         state_[2] ^= state_[0];
0359         state_[3] ^= state_[1];
0360         state_[1] ^= state_[2];
0361         state_[0] ^= state_[3];
0362 
0363         state_[2] ^= t;
0364 
0365         state_[3] = boost::core::rotl(state_[3], 11);
0366 
0367         return result;
0368     }
0369 };
0370 
0371 /**
0372  * This is xoshiro128** 1.1, one of our 32-bit all-purpose, rock-solid
0373  * generators. It has excellent speed, a state size (128 bits) that is
0374  * large enough for mild parallelism, and it passes all tests we are aware
0375  * of.
0376  *
0377  * Note that version 1.0 had mistakenly state_[0] instead of state_[1] as state
0378  * word passed to the scrambler.
0379  *
0380  * For generating just single-precision (i.e., 32-bit) floating-point
0381  * numbers, xoshiro128+ is even faster.
0382  *
0383  * The state must be seeded so that it is not everywhere zero.
0384  */
0385 class xoshiro128mm final : public detail::xoshiro_base<xoshiro128mm, 4, std::uint32_t, std::uint32_t>
0386 {
0387 private:
0388 
0389     using Base = detail::xoshiro_base<xoshiro128mm, 4, std::uint32_t, std::uint32_t>;
0390 
0391 public:
0392 
0393     using Base::Base;
0394 
0395     inline result_type next() noexcept
0396     {
0397         const std::uint32_t result = boost::core::rotl(state_[1] * 5, 7) * 9;
0398 
0399         const std::uint32_t t = state_[1] << 9;
0400 
0401         state_[2] ^= state_[0];
0402         state_[3] ^= state_[1];
0403         state_[1] ^= state_[2];
0404         state_[0] ^= state_[3];
0405 
0406         state_[2] ^= t;
0407 
0408         state_[3] = boost::core::rotl(state_[3], 11);
0409 
0410         return result;
0411     }
0412 };
0413 
0414 /**
0415  * This is xoshiro128+ 1.0, our best and fastest 32-bit generator for 32-bit
0416  * floating-point numbers. We suggest to use its upper bits for
0417  * floating-point generation, as it is slightly faster than xoshiro128**.
0418  * It passes all tests we are aware of except for
0419  * linearity tests, as the lowest four bits have low linear complexity, so
0420  * if low linear complexity is not considered an issue (as it is usually
0421  * the case) it can be used to generate 32-bit outputs, too.
0422  *
0423  * We suggest to use a sign test to extract a random Boolean value, and
0424  * right shifts to extract subsets of bits.
0425  *
0426  * The state must be seeded so that it is not everywhere zero.
0427  */
0428 
0429 class xoshiro128f final : public detail::xoshiro_base<xoshiro128f, 4, float, std::uint32_t>
0430 {
0431 private:
0432 
0433     using Base = detail::xoshiro_base<xoshiro128f, 4, float, std::uint32_t>;
0434 
0435 public:
0436 
0437     using Base::Base;
0438 
0439     inline std::uint32_t next_int() noexcept
0440     {
0441         const std::uint32_t result = state_[0] + state_[3];
0442 
0443         const std::uint32_t t = state_[1] << 9;
0444 
0445         state_[2] ^= state_[0];
0446         state_[3] ^= state_[1];
0447         state_[1] ^= state_[2];
0448         state_[0] ^= state_[3];
0449 
0450         state_[2] ^= t;
0451 
0452         state_[3] = boost::core::rotl(state_[3], 11);
0453 
0454         return result;
0455     }
0456 
0457     inline result_type next() noexcept
0458     {
0459         #ifdef BOOST_RANDOM_HAS_HEX_FLOAT
0460         return static_cast<float>((next_int() >> 8)) * 0x1.0p-24f;
0461         #else
0462         return static_cast<float>((next_int() >> 8)) * 5.9604645e-08f;
0463         #endif
0464     }
0465 
0466     static constexpr result_type (min)() noexcept
0467     {
0468         #ifdef BOOST_RANDOM_HAS_HEX_FLOAT
0469         return static_cast<float>((std::numeric_limits<std::uint32_t>::min)() >> 8) * 0x1.0p-24f;
0470         #else
0471         return static_cast<float>((std::numeric_limits<std::uint64_t>::min)() >> 8) * 5.9604645e-08f;
0472         #endif
0473     }
0474 
0475     static constexpr result_type (max)() noexcept
0476     {
0477         #ifdef BOOST_RANDOM_HAS_HEX_FLOAT
0478         return static_cast<float>((std::numeric_limits<std::uint32_t>::max)() >> 8) * 0x1.0p-24f;
0479         #else
0480         return static_cast<float>((std::numeric_limits<std::uint64_t>::max)() >> 8) * 5.9604645e-08f;
0481         #endif
0482     }
0483 };
0484 
0485 } // namespace random
0486 } // namespace boost
0487 
0488 #endif //BOOST_RANDOM_XOSHIRO_HPP