diff --git a/dep/CMakeLists.txt b/dep/CMakeLists.txt index 7b851c1cc9..f70e88f982 100644 --- a/dep/CMakeLists.txt +++ b/dep/CMakeLists.txt @@ -18,7 +18,7 @@ if(SERVERS OR TOOLS) add_subdirectory(recastnavigation) add_subdirectory(jemalloc) add_subdirectory(fmt) - add_subdirectory(SFMT) + add_subdirectory(PCG) add_subdirectory(utf8cpp) add_subdirectory(valgrind) add_subdirectory(openssl) diff --git a/dep/PCG/CMakeLists.txt b/dep/PCG/CMakeLists.txt new file mode 100644 index 0000000000..605178b991 --- /dev/null +++ b/dep/PCG/CMakeLists.txt @@ -0,0 +1,17 @@ +# This file is part of the TrinityCore Project. See AUTHORS file for Copyright information +# Copyright 2019 Josua Mayer +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +add_library(pcg INTERFACE + ${PCG_SRCS}) + +target_include_directories(pcg + INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/dep/PCG/pcg_extras.hpp b/dep/PCG/pcg_extras.hpp new file mode 100644 index 0000000000..041724a917 --- /dev/null +++ b/dep/PCG/pcg_extras.hpp @@ -0,0 +1,666 @@ +/* + * PCG Random Number Generation for C++ + * + * Copyright 2014-2017 Melissa O'Neill , + * and the PCG Project contributors. + * + * SPDX-License-Identifier: (Apache-2.0 OR MIT) + * + * Licensed under the Apache License, Version 2.0 (provided in + * LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0) + * or under the MIT license (provided in LICENSE-MIT.txt and at + * http://opensource.org/licenses/MIT), at your option. This file may not + * be copied, modified, or distributed except according to those terms. + * + * Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See your chosen license for details. + * + * For additional information about the PCG random number generation scheme, + * visit http://www.pcg-random.org/. + */ + +/* + * This file provides support code that is useful for random-number generation + * but not specific to the PCG generation scheme, including: + * - 128-bit int support for platforms where it isn't available natively + * - bit twiddling operations + * - I/O of 128-bit and 8-bit integers + * - Handling the evilness of SeedSeq + * - Support for efficiently producing random numbers less than a given + * bound + */ + +#ifndef PCG_EXTRAS_HPP_INCLUDED +#define PCG_EXTRAS_HPP_INCLUDED 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __GNUC__ + #include +#endif + +/* + * Abstractions for compiler-specific directives + */ + +#ifdef __GNUC__ + #define PCG_NOINLINE __attribute__((noinline)) +#else + #define PCG_NOINLINE +#endif + +/* + * Some members of the PCG library use 128-bit math. When compiling on 64-bit + * platforms, both GCC and Clang provide 128-bit integer types that are ideal + * for the job. + * + * On 32-bit platforms (or with other compilers), we fall back to a C++ + * class that provides 128-bit unsigned integers instead. It may seem + * like we're reinventing the wheel here, because libraries already exist + * that support large integers, but most existing libraries provide a very + * generic multiprecision code, but here we're operating at a fixed size. + * Also, most other libraries are fairly heavyweight. So we use a direct + * implementation. Sadly, it's much slower than hand-coded assembly or + * direct CPU support. + * + */ +#if __SIZEOF_INT128__ && !PCG_FORCE_EMULATED_128BIT_MATH + namespace pcg_extras { + typedef __uint128_t pcg128_t; + } + #define PCG_128BIT_CONSTANT(high,low) \ + ((pcg_extras::pcg128_t(high) << 64) + low) +#else + #include "pcg_uint128.hpp" + namespace pcg_extras { + typedef pcg_extras::uint_x4 pcg128_t; + } + #define PCG_128BIT_CONSTANT(high,low) \ + pcg_extras::pcg128_t(high,low) + #define PCG_EMULATED_128BIT_MATH 1 +#endif + + +namespace pcg_extras { + +/* + * We often need to represent a "number of bits". When used normally, these + * numbers are never greater than 128, so an unsigned char is plenty. + * If you're using a nonstandard generator of a larger size, you can set + * PCG_BITCOUNT_T to have it define it as a larger size. (Some compilers + * might produce faster code if you set it to an unsigned int.) + */ + +#ifndef PCG_BITCOUNT_T + typedef uint8_t bitcount_t; +#else + typedef PCG_BITCOUNT_T bitcount_t; +#endif + +/* + * C++ requires us to be able to serialize RNG state by printing or reading + * it from a stream. Because we use 128-bit ints, we also need to be able + * ot print them, so here is code to do so. + * + * This code provides enough functionality to print 128-bit ints in decimal + * and zero-padded in hex. It's not a full-featured implementation. + */ + +template +std::basic_ostream& +operator<<(std::basic_ostream& out, pcg128_t value) +{ + auto desired_base = out.flags() & out.basefield; + bool want_hex = desired_base == out.hex; + + if (want_hex) { + uint64_t highpart = uint64_t(value >> 64); + uint64_t lowpart = uint64_t(value); + auto desired_width = out.width(); + if (desired_width > 16) { + out.width(desired_width - 16); + } + if (highpart != 0 || desired_width > 16) + out << highpart; + CharT oldfill = '\0'; + if (highpart != 0) { + out.width(16); + oldfill = out.fill('0'); + } + auto oldflags = out.setf(decltype(desired_base){}, out.showbase); + out << lowpart; + out.setf(oldflags); + if (highpart != 0) { + out.fill(oldfill); + } + return out; + } + constexpr size_t MAX_CHARS_128BIT = 40; + + char buffer[MAX_CHARS_128BIT]; + char* pos = buffer+sizeof(buffer); + *(--pos) = '\0'; + constexpr auto BASE = pcg128_t(10ULL); + do { + auto div = value / BASE; + auto mod = uint32_t(value - (div * BASE)); + *(--pos) = '0' + char(mod); + value = div; + } while(value != pcg128_t(0ULL)); + return out << pos; +} + +template +std::basic_istream& +operator>>(std::basic_istream& in, pcg128_t& value) +{ + typename std::basic_istream::sentry s(in); + + if (!s) + return in; + + constexpr auto BASE = pcg128_t(10ULL); + pcg128_t current(0ULL); + bool did_nothing = true; + bool overflow = false; + for(;;) { + CharT wide_ch = in.get(); + if (!in.good()) { + in.clear(std::ios::eofbit); + break; + } + auto ch = in.narrow(wide_ch, '\0'); + if (ch < '0' || ch > '9') { + in.unget(); + break; + } + did_nothing = false; + pcg128_t digit(uint32_t(ch - '0')); + pcg128_t timesbase = current*BASE; + overflow = overflow || timesbase < current; + current = timesbase + digit; + overflow = overflow || current < digit; + } + + if (did_nothing || overflow) { + in.setstate(std::ios::failbit); + if (overflow) + current = ~pcg128_t(0ULL); + } + + value = current; + + return in; +} + +/* + * Likewise, if people use tiny rngs, we'll be serializing uint8_t. + * If we just used the provided IO operators, they'd read/write chars, + * not ints, so we need to define our own. We *can* redefine this operator + * here because we're in our own namespace. + */ + +template +std::basic_ostream& +operator<<(std::basic_ostream&out, uint8_t value) +{ + return out << uint32_t(value); +} + +template +std::basic_istream& +operator>>(std::basic_istream& in, uint8_t& target) +{ + uint32_t value = 0xdecea5edU; + in >> value; + if (!in && value == 0xdecea5edU) + return in; + if (value > uint8_t(~0)) { + in.setstate(std::ios::failbit); + value = ~0U; + } + target = uint8_t(value); + return in; +} + +/* Unfortunately, the above functions don't get found in preference to the + * built in ones, so we create some more specific overloads that will. + * Ugh. + */ + +inline std::ostream& operator<<(std::ostream& out, uint8_t value) +{ + return pcg_extras::operator<< (out, value); +} + +inline std::istream& operator>>(std::istream& in, uint8_t& value) +{ + return pcg_extras::operator>> (in, value); +} + + + +/* + * Useful bitwise operations. + */ + +/* + * XorShifts are invertable, but they are someting of a pain to invert. + * This function backs them out. It's used by the whacky "inside out" + * generator defined later. + */ + +template +inline itype unxorshift(itype x, bitcount_t bits, bitcount_t shift) +{ + if (2*shift >= bits) { + return x ^ (x >> shift); + } + itype lowmask1 = (itype(1U) << (bits - shift*2)) - 1; + itype highmask1 = ~lowmask1; + itype top1 = x; + itype bottom1 = x & lowmask1; + top1 ^= top1 >> shift; + top1 &= highmask1; + x = top1 | bottom1; + itype lowmask2 = (itype(1U) << (bits - shift)) - 1; + itype bottom2 = x & lowmask2; + bottom2 = unxorshift(bottom2, bits - shift, shift); + bottom2 &= lowmask1; + return top1 | bottom2; +} + +/* + * Rotate left and right. + * + * In ideal world, compilers would spot idiomatic rotate code and convert it + * to a rotate instruction. Of course, opinions vary on what the correct + * idiom is and how to spot it. For clang, sometimes it generates better + * (but still crappy) code if you define PCG_USE_ZEROCHECK_ROTATE_IDIOM. + */ + +template +inline itype rotl(itype value, bitcount_t rot) +{ + constexpr bitcount_t bits = sizeof(itype) * 8; + constexpr bitcount_t mask = bits - 1; +#if PCG_USE_ZEROCHECK_ROTATE_IDIOM + return rot ? (value << rot) | (value >> (bits - rot)) : value; +#else + return (value << rot) | (value >> ((- rot) & mask)); +#endif +} + +template +inline itype rotr(itype value, bitcount_t rot) +{ + constexpr bitcount_t bits = sizeof(itype) * 8; + constexpr bitcount_t mask = bits - 1; +#if PCG_USE_ZEROCHECK_ROTATE_IDIOM + return rot ? (value >> rot) | (value << (bits - rot)) : value; +#else + return (value >> rot) | (value << ((- rot) & mask)); +#endif +} + +/* Unfortunately, both Clang and GCC sometimes perform poorly when it comes + * to properly recognizing idiomatic rotate code, so for we also provide + * assembler directives (enabled with PCG_USE_INLINE_ASM). Boo, hiss. + * (I hope that these compilers get better so that this code can die.) + * + * These overloads will be preferred over the general template code above. + */ +#if PCG_USE_INLINE_ASM && __GNUC__ && (__x86_64__ || __i386__) + +inline uint8_t rotr(uint8_t value, bitcount_t rot) +{ + asm ("rorb %%cl, %0" : "=r" (value) : "0" (value), "c" (rot)); + return value; +} + +inline uint16_t rotr(uint16_t value, bitcount_t rot) +{ + asm ("rorw %%cl, %0" : "=r" (value) : "0" (value), "c" (rot)); + return value; +} + +inline uint32_t rotr(uint32_t value, bitcount_t rot) +{ + asm ("rorl %%cl, %0" : "=r" (value) : "0" (value), "c" (rot)); + return value; +} + +#if __x86_64__ +inline uint64_t rotr(uint64_t value, bitcount_t rot) +{ + asm ("rorq %%cl, %0" : "=r" (value) : "0" (value), "c" (rot)); + return value; +} +#endif // __x86_64__ + +#elif defined(_MSC_VER) + // Use MSVC++ bit rotation intrinsics + +#pragma intrinsic(_rotr, _rotr64, _rotr8, _rotr16) + +inline uint8_t rotr(uint8_t value, bitcount_t rot) +{ + return _rotr8(value, rot); +} + +inline uint16_t rotr(uint16_t value, bitcount_t rot) +{ + return _rotr16(value, rot); +} + +inline uint32_t rotr(uint32_t value, bitcount_t rot) +{ + return _rotr(value, rot); +} + +inline uint64_t rotr(uint64_t value, bitcount_t rot) +{ + return _rotr64(value, rot); +} + +#endif // PCG_USE_INLINE_ASM + + +/* + * The C++ SeedSeq concept (modelled by seed_seq) can fill an array of + * 32-bit integers with seed data, but sometimes we want to produce + * larger or smaller integers. + * + * The following code handles this annoyance. + * + * uneven_copy will copy an array of 32-bit ints to an array of larger or + * smaller ints (actually, the code is general it only needing forward + * iterators). The copy is identical to the one that would be performed if + * we just did memcpy on a standard little-endian machine, but works + * regardless of the endian of the machine (or the weirdness of the ints + * involved). + * + * generate_to initializes an array of integers using a SeedSeq + * object. It is given the size as a static constant at compile time and + * tries to avoid memory allocation. If we're filling in 32-bit constants + * we just do it directly. If we need a separate buffer and it's small, + * we allocate it on the stack. Otherwise, we fall back to heap allocation. + * Ugh. + * + * generate_one produces a single value of some integral type using a + * SeedSeq object. + */ + + /* uneven_copy helper, case where destination ints are less than 32 bit. */ + +template +SrcIter uneven_copy_impl( + SrcIter src_first, DestIter dest_first, DestIter dest_last, + std::true_type) +{ + typedef typename std::iterator_traits::value_type src_t; + typedef typename std::iterator_traits::value_type dest_t; + + constexpr bitcount_t SRC_SIZE = sizeof(src_t); + constexpr bitcount_t DEST_SIZE = sizeof(dest_t); + constexpr bitcount_t DEST_BITS = DEST_SIZE * 8; + constexpr bitcount_t SCALE = SRC_SIZE / DEST_SIZE; + + size_t count = 0; + src_t value = 0; + + while (dest_first != dest_last) { + if ((count++ % SCALE) == 0) + value = *src_first++; // Get more bits + else + value >>= DEST_BITS; // Move down bits + + *dest_first++ = dest_t(value); // Truncates, ignores high bits. + } + return src_first; +} + + /* uneven_copy helper, case where destination ints are more than 32 bit. */ + +template +SrcIter uneven_copy_impl( + SrcIter src_first, DestIter dest_first, DestIter dest_last, + std::false_type) +{ + typedef typename std::iterator_traits::value_type src_t; + typedef typename std::iterator_traits::value_type dest_t; + + constexpr auto SRC_SIZE = sizeof(src_t); + constexpr auto SRC_BITS = SRC_SIZE * 8; + constexpr auto DEST_SIZE = sizeof(dest_t); + constexpr auto SCALE = (DEST_SIZE+SRC_SIZE-1) / SRC_SIZE; + + while (dest_first != dest_last) { + dest_t value(0UL); + unsigned int shift = 0; + + for (size_t i = 0; i < SCALE; ++i) { + value |= dest_t(*src_first++) << shift; + shift += SRC_BITS; + } + + *dest_first++ = value; + } + return src_first; +} + +/* uneven_copy, call the right code for larger vs. smaller */ + +template +inline SrcIter uneven_copy(SrcIter src_first, + DestIter dest_first, DestIter dest_last) +{ + typedef typename std::iterator_traits::value_type src_t; + typedef typename std::iterator_traits::value_type dest_t; + + constexpr bool DEST_IS_SMALLER = sizeof(dest_t) < sizeof(src_t); + + return uneven_copy_impl(src_first, dest_first, dest_last, + std::integral_constant{}); +} + +/* generate_to, fill in a fixed-size array of integral type using a SeedSeq + * (actually works for any random-access iterator) + */ + +template +inline void generate_to_impl(SeedSeq&& generator, DestIter dest, + std::true_type) +{ + generator.generate(dest, dest+size); +} + +template +void generate_to_impl(SeedSeq&& generator, DestIter dest, + std::false_type) +{ + typedef typename std::iterator_traits::value_type dest_t; + constexpr auto DEST_SIZE = sizeof(dest_t); + constexpr auto GEN_SIZE = sizeof(uint32_t); + + constexpr bool GEN_IS_SMALLER = GEN_SIZE < DEST_SIZE; + constexpr size_t FROM_ELEMS = + GEN_IS_SMALLER + ? size * ((DEST_SIZE+GEN_SIZE-1) / GEN_SIZE) + : (size + (GEN_SIZE / DEST_SIZE) - 1) + / ((GEN_SIZE / DEST_SIZE) + GEN_IS_SMALLER); + // this odd code ^^^^^^^^^^^^^^^^^ is work-around for + // a bug: http://llvm.org/bugs/show_bug.cgi?id=21287 + + if (FROM_ELEMS <= 1024) { + uint32_t buffer[FROM_ELEMS]; + generator.generate(buffer, buffer+FROM_ELEMS); + uneven_copy(buffer, dest, dest+size); + } else { + uint32_t* buffer = static_cast(malloc(GEN_SIZE * FROM_ELEMS)); + generator.generate(buffer, buffer+FROM_ELEMS); + uneven_copy(buffer, dest, dest+size); + free(static_cast(buffer)); + } +} + +template +inline void generate_to(SeedSeq&& generator, DestIter dest) +{ + typedef typename std::iterator_traits::value_type dest_t; + constexpr bool IS_32BIT = sizeof(dest_t) == sizeof(uint32_t); + + generate_to_impl(std::forward(generator), dest, + std::integral_constant{}); +} + +/* generate_one, produce a value of integral type using a SeedSeq + * (optionally, we can have it produce more than one and pick which one + * we want) + */ + +template +inline UInt generate_one(SeedSeq&& generator) +{ + UInt result[N]; + generate_to(std::forward(generator), result); + return result[i]; +} + +template +auto bounded_rand(RngType& rng, typename RngType::result_type upper_bound) + -> typename RngType::result_type +{ + typedef typename RngType::result_type rtype; + rtype threshold = (RngType::max() - RngType::min() + rtype(1) - upper_bound) + % upper_bound; + for (;;) { + rtype r = rng() - RngType::min(); + if (r >= threshold) + return r % upper_bound; + } +} + +template +void shuffle(Iter from, Iter to, RandType&& rng) +{ + typedef typename std::iterator_traits::difference_type delta_t; + typedef typename std::remove_reference::type::result_type result_t; + auto count = to - from; + while (count > 1) { + delta_t chosen = delta_t(bounded_rand(rng, result_t(count))); + --count; + --to; + using std::swap; + swap(*(from + chosen), *to); + } +} + +/* + * Although std::seed_seq is useful, it isn't everything. Often we want to + * initialize a random-number generator some other way, such as from a random + * device. + * + * Technically, it does not meet the requirements of a SeedSequence because + * it lacks some of the rarely-used member functions (some of which would + * be impossible to provide). However the C++ standard is quite specific + * that actual engines only called the generate method, so it ought not to be + * a problem in practice. + */ + +template +class seed_seq_from { +private: + RngType rng_; + + typedef uint_least32_t result_type; + +public: + template + seed_seq_from(Args&&... args) : + rng_(std::forward(args)...) + { + // Nothing (else) to do... + } + + template + void generate(Iter start, Iter finish) + { + for (auto i = start; i != finish; ++i) + *i = result_type(rng_()); + } + + constexpr size_t size() const + { + return (sizeof(typename RngType::result_type) > sizeof(result_type) + && RngType::max() > ~size_t(0UL)) + ? ~size_t(0UL) + : size_t(RngType::max()); + } +}; + +/* + * Sometimes you might want a distinct seed based on when the program + * was compiled. That way, a particular instance of the program will + * behave the same way, but when recompiled it'll produce a different + * value. + */ + +template +struct static_arbitrary_seed { +private: + static constexpr IntType fnv(IntType hash, const char* pos) { + return *pos == '\0' + ? hash + : fnv((hash * IntType(16777619U)) ^ *pos, (pos+1)); + } + +public: + static constexpr IntType value = fnv(IntType(2166136261U ^ sizeof(IntType)), + __DATE__ __TIME__ __FILE__); +}; + +// Sometimes, when debugging or testing, it's handy to be able print the name +// of a (in human-readable form). This code allows the idiom: +// +// cout << printable_typename() +// +// to print out my_foo_type_t (or its concrete type if it is a synonym) + +#if __cpp_rtti || __GXX_RTTI + +template +struct printable_typename {}; + +template +std::ostream& operator<<(std::ostream& out, printable_typename) { + const char *implementation_typename = typeid(T).name(); +#ifdef __GNUC__ + int status; + char* pretty_name = + abi::__cxa_demangle(implementation_typename, nullptr, nullptr, &status); + if (status == 0) + out << pretty_name; + free(static_cast(pretty_name)); + if (status == 0) + return out; +#endif + out << implementation_typename; + return out; +} + +#endif // __cpp_rtti || __GXX_RTTI + +} // namespace pcg_extras + +#endif // PCG_EXTRAS_HPP_INCLUDED diff --git a/dep/PCG/pcg_random.hpp b/dep/PCG/pcg_random.hpp new file mode 100644 index 0000000000..d479a81519 --- /dev/null +++ b/dep/PCG/pcg_random.hpp @@ -0,0 +1,1951 @@ +/* + * PCG Random Number Generation for C++ + * + * Copyright 2014-2022 Melissa O'Neill , + * and the PCG Project contributors. + * + * SPDX-License-Identifier: (Apache-2.0 OR MIT) + * + * Licensed under the Apache License, Version 2.0 (provided in + * LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0) + * or under the MIT license (provided in LICENSE-MIT.txt and at + * http://opensource.org/licenses/MIT), at your option. This file may not + * be copied, modified, or distributed except according to those terms. + * + * Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See your chosen license for details. + * + * For additional information about the PCG random number generation scheme, + * visit http://www.pcg-random.org/. + */ + +/* + * This code provides the reference implementation of the PCG family of + * random number generators. The code is complex because it implements + * + * - several members of the PCG family, specifically members corresponding + * to the output functions: + * - XSH RR (good for 64-bit state, 32-bit output) + * - XSH RS (good for 64-bit state, 32-bit output) + * - XSL RR (good for 128-bit state, 64-bit output) + * - RXS M XS (statistically most powerful generator) + * - XSL RR RR (good for 128-bit state, 128-bit output) + * - and RXS, RXS M, XSH, XSL (mostly for testing) + * - at potentially *arbitrary* bit sizes + * - with four different techniques for random streams (MCG, one-stream + * LCG, settable-stream LCG, unique-stream LCG) + * - and the extended generation schemes allowing arbitrary periods + * - with all features of C++11 random number generation (and more), + * some of which are somewhat painful, including + * - initializing with a SeedSequence which writes 32-bit values + * to memory, even though the state of the generator may not + * use 32-bit values (it might use smaller or larger integers) + * - I/O for RNGs and a prescribed format, which needs to handle + * the issue that 8-bit and 128-bit integers don't have working + * I/O routines (e.g., normally 8-bit = char, not integer) + * - equality and inequality for RNGs + * - and a number of convenience typedefs to mask all the complexity + * + * The code employees a fairly heavy level of abstraction, and has to deal + * with various C++ minutia. If you're looking to learn about how the PCG + * scheme works, you're probably best of starting with one of the other + * codebases (see www.pcg-random.org). But if you're curious about the + * constants for the various output functions used in those other, simpler, + * codebases, this code shows how they are calculated. + * + * On the positive side, at least there are convenience typedefs so that you + * can say + * + * pcg32 myRNG; + * + * rather than: + * + * pcg_detail::engine< + * uint32_t, // Output Type + * uint64_t, // State Type + * pcg_detail::xsh_rr_mixin, true, // Output Func + * pcg_detail::specific_stream, // Stream Kind + * pcg_detail::default_multiplier // LCG Mult + * > myRNG; + * + */ + +#ifndef PCG_RAND_HPP_INCLUDED +#define PCG_RAND_HPP_INCLUDED 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER + #pragma warning(disable:4146) +#endif + +#ifdef _MSC_VER + #define PCG_ALWAYS_INLINE __forceinline +#elif __GNUC__ + #define PCG_ALWAYS_INLINE __attribute__((always_inline)) +#else + #define PCG_ALWAYS_INLINE inline +#endif + +/* + * The pcg_extras namespace contains some support code that is likely to + * be useful for a variety of RNGs, including: + * - 128-bit int support for platforms where it isn't available natively + * - bit twiddling operations + * - I/O of 128-bit and 8-bit integers + * - Handling the evilness of SeedSeq + * - Support for efficiently producing random numbers less than a given + * bound + */ + +#include "pcg_extras.hpp" + +namespace pcg_detail { + +using namespace pcg_extras; + +/* + * The LCG generators need some constants to function. This code lets you + * look up the constant by *type*. For example + * + * default_multiplier::multiplier() + * + * gives you the default multiplier for 32-bit integers. We use the name + * of the constant and not a generic word like value to allow these classes + * to be used as mixins. + */ + +template +struct default_multiplier { + // Not defined for an arbitrary type +}; + +template +struct default_increment { + // Not defined for an arbitrary type +}; + +#define PCG_DEFINE_CONSTANT(type, what, kind, constant) \ + template <> \ + struct what ## _ ## kind { \ + static constexpr type kind() { \ + return constant; \ + } \ + }; + +PCG_DEFINE_CONSTANT(uint8_t, default, multiplier, 141U) +PCG_DEFINE_CONSTANT(uint8_t, default, increment, 77U) + +PCG_DEFINE_CONSTANT(uint16_t, default, multiplier, 12829U) +PCG_DEFINE_CONSTANT(uint16_t, default, increment, 47989U) + +PCG_DEFINE_CONSTANT(uint32_t, default, multiplier, 747796405U) +PCG_DEFINE_CONSTANT(uint32_t, default, increment, 2891336453U) + +PCG_DEFINE_CONSTANT(uint64_t, default, multiplier, 6364136223846793005ULL) +PCG_DEFINE_CONSTANT(uint64_t, default, increment, 1442695040888963407ULL) + +PCG_DEFINE_CONSTANT(pcg128_t, default, multiplier, + PCG_128BIT_CONSTANT(2549297995355413924ULL,4865540595714422341ULL)) +PCG_DEFINE_CONSTANT(pcg128_t, default, increment, + PCG_128BIT_CONSTANT(6364136223846793005ULL,1442695040888963407ULL)) + +/* Alternative (cheaper) multipliers for 128-bit */ + +template +struct cheap_multiplier : public default_multiplier { + // For most types just use the default. +}; + +template <> +struct cheap_multiplier { + static constexpr uint64_t multiplier() { + return 0xda942042e4dd58b5ULL; + } +}; + + +/* + * Each PCG generator is available in four variants, based on how it applies + * the additive constant for its underlying LCG; the variations are: + * + * single stream - all instances use the same fixed constant, thus + * the RNG always somewhere in same sequence + * mcg - adds zero, resulting in a single stream and reduced + * period + * specific stream - the constant can be changed at any time, selecting + * a different random sequence + * unique stream - the constant is based on the memory address of the + * object, thus every RNG has its own unique sequence + * + * This variation is provided though mixin classes which define a function + * value called increment() that returns the necessary additive constant. + */ + + + +/* + * unique stream + */ + + +template +class unique_stream { +protected: + static constexpr bool is_mcg = false; + + // Is never called, but is provided for symmetry with specific_stream + void set_stream(...) + { + abort(); + } + +public: + typedef itype state_type; + + constexpr itype increment() const { + return itype(reinterpret_cast(this) | 1); + } + + constexpr itype stream() const + { + return increment() >> 1; + } + + static constexpr bool can_specify_stream = false; + + static constexpr size_t streams_pow2() + { + return (sizeof(itype) < sizeof(size_t) ? sizeof(itype) + : sizeof(size_t))*8 - 1u; + } + +protected: + constexpr unique_stream() = default; +}; + + +/* + * no stream (mcg) + */ + +template +class no_stream { +protected: + static constexpr bool is_mcg = true; + + // Is never called, but is provided for symmetry with specific_stream + void set_stream(...) + { + abort(); + } + +public: + typedef itype state_type; + + static constexpr itype increment() { + return 0; + } + + static constexpr bool can_specify_stream = false; + + static constexpr size_t streams_pow2() + { + return 0u; + } + +protected: + constexpr no_stream() = default; +}; + + +/* + * single stream/sequence (oneseq) + */ + +template +class oneseq_stream : public default_increment { +protected: + static constexpr bool is_mcg = false; + + // Is never called, but is provided for symmetry with specific_stream + void set_stream(...) + { + abort(); + } + +public: + typedef itype state_type; + + static constexpr itype stream() + { + return default_increment::increment() >> 1; + } + + static constexpr bool can_specify_stream = false; + + static constexpr size_t streams_pow2() + { + return 0u; + } + +protected: + constexpr oneseq_stream() = default; +}; + + +/* + * specific stream + */ + +template +class specific_stream { +protected: + static constexpr bool is_mcg = false; + + itype inc_ = default_increment::increment(); + +public: + typedef itype state_type; + typedef itype stream_state; + + constexpr itype increment() const { + return inc_; + } + + itype stream() + { + return inc_ >> 1; + } + + void set_stream(itype specific_seq) + { + inc_ = (specific_seq << 1) | 1; + } + + static constexpr bool can_specify_stream = true; + + static constexpr size_t streams_pow2() + { + return (sizeof(itype)*8) - 1u; + } + +protected: + specific_stream() = default; + + specific_stream(itype specific_seq) + : inc_(itype(specific_seq << 1) | itype(1U)) + { + // Nothing (else) to do. + } +}; + + +/* + * This is where it all comes together. This function joins together three + * mixin classes which define + * - the LCG additive constant (the stream) + * - the LCG multiplier + * - the output function + * in addition, we specify the type of the LCG state, and the result type, + * and whether to use the pre-advance version of the state for the output + * (increasing instruction-level parallelism) or the post-advance version + * (reducing register pressure). + * + * Given the high level of parameterization, the code has to use some + * template-metaprogramming tricks to handle some of the subtle variations + * involved. + */ + +template , + typename multiplier_mixin = default_multiplier > +class engine : protected output_mixin, + public stream_mixin, + protected multiplier_mixin { +protected: + itype state_; + + struct can_specify_stream_tag {}; + struct no_specifiable_stream_tag {}; + + using stream_mixin::increment; + using multiplier_mixin::multiplier; + +public: + typedef xtype result_type; + typedef itype state_type; + + static constexpr size_t period_pow2() + { + return sizeof(state_type)*8 - 2*stream_mixin::is_mcg; + } + + // It would be nice to use std::numeric_limits for these, but + // we can't be sure that it'd be defined for the 128-bit types. + + static constexpr result_type min() + { + return result_type(0UL); + } + + static constexpr result_type max() + { + return result_type(~result_type(0UL)); + } + +protected: + itype bump(itype state) + { + return state * multiplier() + increment(); + } + + itype base_generate() + { + return state_ = bump(state_); + } + + itype base_generate0() + { + itype old_state = state_; + state_ = bump(state_); + return old_state; + } + +public: + result_type operator()() + { + if (output_previous) + return this->output(base_generate0()); + else + return this->output(base_generate()); + } + + result_type operator()(result_type upper_bound) + { + return bounded_rand(*this, upper_bound); + } + +protected: + static itype advance(itype state, itype delta, + itype cur_mult, itype cur_plus); + + static itype distance(itype cur_state, itype newstate, itype cur_mult, + itype cur_plus, itype mask = ~itype(0U)); + + itype distance(itype newstate, itype mask = itype(~itype(0U))) const + { + return distance(state_, newstate, multiplier(), increment(), mask); + } + +public: + void advance(itype delta) + { + state_ = advance(state_, delta, this->multiplier(), this->increment()); + } + + void backstep(itype delta) + { + advance(-delta); + } + + void discard(itype delta) + { + advance(delta); + } + + bool wrapped() + { + if (stream_mixin::is_mcg) { + // For MCGs, the low order two bits never change. In this + // implementation, we keep them fixed at 3 to make this test + // easier. + return state_ == 3; + } else { + return state_ == 0; + } + } + + engine(itype state = itype(0xcafef00dd15ea5e5ULL)) + : state_(this->is_mcg ? state|state_type(3U) + : bump(state + this->increment())) + { + // Nothing else to do. + } + + // This function may or may not exist. It thus has to be a template + // to use SFINAE; users don't have to worry about its template-ness. + + template + engine(itype state, typename sm::stream_state stream_seed) + : stream_mixin(stream_seed), + state_(this->is_mcg ? state|state_type(3U) + : bump(state + this->increment())) + { + // Nothing else to do. + } + + template + engine(SeedSeq&& seedSeq, typename std::enable_if< + !stream_mixin::can_specify_stream + && !std::is_convertible::value + && !std::is_convertible::value, + no_specifiable_stream_tag>::type = {}) + : engine(generate_one(std::forward(seedSeq))) + { + // Nothing else to do. + } + + template + engine(SeedSeq&& seedSeq, typename std::enable_if< + stream_mixin::can_specify_stream + && !std::is_convertible::value + && !std::is_convertible::value, + can_specify_stream_tag>::type = {}) + { + itype seeddata[2]; + generate_to<2>(std::forward(seedSeq), seeddata); + seed(seeddata[1], seeddata[0]); + } + + + template + void seed(Args&&... args) + { + new (this) engine(std::forward(args)...); + } + + template + friend bool operator==(const engine&, + const engine&); + + template + friend itype1 operator-(const engine&, + const engine&); + + template + friend std::basic_ostream& + operator<<(std::basic_ostream& out, + const engine&); + + template + friend std::basic_istream& + operator>>(std::basic_istream& in, + engine& rng); +}; + +template +std::basic_ostream& +operator<<(std::basic_ostream& out, + const engine& rng) +{ + using pcg_extras::operator<<; + + auto orig_flags = out.flags(std::ios_base::dec | std::ios_base::left); + auto space = out.widen(' '); + auto orig_fill = out.fill(); + + out << rng.multiplier() << space + << rng.increment() << space + << rng.state_; + + out.flags(orig_flags); + out.fill(orig_fill); + return out; +} + + +template +std::basic_istream& +operator>>(std::basic_istream& in, + engine& rng) +{ + using pcg_extras::operator>>; + + auto orig_flags = in.flags(std::ios_base::dec | std::ios_base::skipws); + + itype multiplier, increment, state; + in >> multiplier >> increment >> state; + + if (!in.fail()) { + bool good = true; + if (multiplier != rng.multiplier()) { + good = false; + } else if (rng.can_specify_stream) { + rng.set_stream(increment >> 1); + } else if (increment != rng.increment()) { + good = false; + } + if (good) { + rng.state_ = state; + } else { + in.clear(std::ios::failbit); + } + } + + in.flags(orig_flags); + return in; +} + + +template +itype engine::advance( + itype state, itype delta, itype cur_mult, itype cur_plus) +{ + // The method used here is based on Brown, "Random Number Generation + // with Arbitrary Stride,", Transactions of the American Nuclear + // Society (Nov. 1994). The algorithm is very similar to fast + // exponentiation. + // + // Even though delta is an unsigned integer, we can pass a + // signed integer to go backwards, it just goes "the long way round". + + constexpr itype ZERO = 0u; // itype may be a non-trivial types, so + constexpr itype ONE = 1u; // we define some ugly constants. + itype acc_mult = 1; + itype acc_plus = 0; + while (delta > ZERO) { + if (delta & ONE) { + acc_mult *= cur_mult; + acc_plus = acc_plus*cur_mult + cur_plus; + } + cur_plus = (cur_mult+ONE)*cur_plus; + cur_mult *= cur_mult; + delta >>= 1; + } + return acc_mult * state + acc_plus; +} + +template +itype engine::distance( + itype cur_state, itype newstate, itype cur_mult, itype cur_plus, itype mask) +{ + constexpr itype ONE = 1u; // itype could be weird, so use constant + bool is_mcg = cur_plus == itype(0); + itype the_bit = is_mcg ? itype(4u) : itype(1u); + itype distance = 0u; + while ((cur_state & mask) != (newstate & mask)) { + if ((cur_state & the_bit) != (newstate & the_bit)) { + cur_state = cur_state * cur_mult + cur_plus; + distance |= the_bit; + } + assert((cur_state & the_bit) == (newstate & the_bit)); + the_bit <<= 1; + cur_plus = (cur_mult+ONE)*cur_plus; + cur_mult *= cur_mult; + } + return is_mcg ? distance >> 2 : distance; +} + +template +itype operator-(const engine& lhs, + const engine& rhs) +{ + static_assert( + std::is_same::value && + std::is_same::value, + "Incomparable generators"); + if (lhs.increment() == rhs.increment()) { + return rhs.distance(lhs.state_); + } else { + constexpr itype ONE = 1u; + itype lhs_diff = lhs.increment() + (lhs.multiplier()-ONE) * lhs.state_; + itype rhs_diff = rhs.increment() + (rhs.multiplier()-ONE) * rhs.state_; + if ((lhs_diff & itype(3u)) != (rhs_diff & itype(3u))) { + rhs_diff = -rhs_diff; + } + return rhs.distance(rhs_diff, lhs_diff, rhs.multiplier(), itype(0u)); + } +} + + +template +bool operator==(const engine& lhs, + const engine& rhs) +{ + return (lhs.multiplier() == rhs.multiplier()) + && (lhs.increment() == rhs.increment()) + && (lhs.state_ == rhs.state_); +} + +template +inline bool operator!=(const engine& lhs, + const engine& rhs) +{ + return !operator==(lhs,rhs); +} + + +template class output_mixin, + bool output_previous = (sizeof(itype) <= 8), + template class multiplier_mixin = default_multiplier> +using oneseq_base = engine, output_previous, + oneseq_stream, + multiplier_mixin >; + +template class output_mixin, + bool output_previous = (sizeof(itype) <= 8), + template class multiplier_mixin = default_multiplier> +using unique_base = engine, output_previous, + unique_stream, + multiplier_mixin >; + +template class output_mixin, + bool output_previous = (sizeof(itype) <= 8), + template class multiplier_mixin = default_multiplier> +using setseq_base = engine, output_previous, + specific_stream, + multiplier_mixin >; + +template class output_mixin, + bool output_previous = (sizeof(itype) <= 8), + template class multiplier_mixin = default_multiplier> +using mcg_base = engine, output_previous, + no_stream, + multiplier_mixin >; + +/* + * OUTPUT FUNCTIONS. + * + * These are the core of the PCG generation scheme. They specify how to + * turn the base LCG's internal state into the output value of the final + * generator. + * + * They're implemented as mixin classes. + * + * All of the classes have code that is written to allow it to be applied + * at *arbitrary* bit sizes, although in practice they'll only be used at + * standard sizes supported by C++. + */ + +/* + * XSH RS -- high xorshift, followed by a random shift + * + * Fast. A good performer. + */ + +template +struct xsh_rs_mixin { + static xtype output(itype internal) + { + constexpr bitcount_t bits = bitcount_t(sizeof(itype) * 8); + constexpr bitcount_t xtypebits = bitcount_t(sizeof(xtype) * 8); + constexpr bitcount_t sparebits = bits - xtypebits; + constexpr bitcount_t opbits = + sparebits-5 >= 64 ? 5 + : sparebits-4 >= 32 ? 4 + : sparebits-3 >= 16 ? 3 + : sparebits-2 >= 4 ? 2 + : sparebits-1 >= 1 ? 1 + : 0; + constexpr bitcount_t mask = (1 << opbits) - 1; + constexpr bitcount_t maxrandshift = mask; + constexpr bitcount_t topspare = opbits; + constexpr bitcount_t bottomspare = sparebits - topspare; + constexpr bitcount_t xshift = topspare + (xtypebits+maxrandshift)/2; + bitcount_t rshift = + opbits ? bitcount_t(internal >> (bits - opbits)) & mask : 0; + internal ^= internal >> xshift; + xtype result = xtype(internal >> (bottomspare - maxrandshift + rshift)); + return result; + } +}; + +/* + * XSH RR -- high xorshift, followed by a random rotate + * + * Fast. A good performer. Slightly better statistically than XSH RS. + */ + +template +struct xsh_rr_mixin { + static xtype output(itype internal) + { + constexpr bitcount_t bits = bitcount_t(sizeof(itype) * 8); + constexpr bitcount_t xtypebits = bitcount_t(sizeof(xtype)*8); + constexpr bitcount_t sparebits = bits - xtypebits; + constexpr bitcount_t wantedopbits = + xtypebits >= 128 ? 7 + : xtypebits >= 64 ? 6 + : xtypebits >= 32 ? 5 + : xtypebits >= 16 ? 4 + : 3; + constexpr bitcount_t opbits = + sparebits >= wantedopbits ? wantedopbits + : sparebits; + constexpr bitcount_t amplifier = wantedopbits - opbits; + constexpr bitcount_t mask = (1 << opbits) - 1; + constexpr bitcount_t topspare = opbits; + constexpr bitcount_t bottomspare = sparebits - topspare; + constexpr bitcount_t xshift = (topspare + xtypebits)/2; + bitcount_t rot = opbits ? bitcount_t(internal >> (bits - opbits)) & mask + : 0; + bitcount_t amprot = (rot << amplifier) & mask; + internal ^= internal >> xshift; + xtype result = xtype(internal >> bottomspare); + result = rotr(result, amprot); + return result; + } +}; + +/* + * RXS -- random xorshift + */ + +template +struct rxs_mixin { +static xtype output_rxs(itype internal) + { + constexpr bitcount_t bits = bitcount_t(sizeof(itype) * 8); + constexpr bitcount_t xtypebits = bitcount_t(sizeof(xtype)*8); + constexpr bitcount_t shift = bits - xtypebits; + constexpr bitcount_t extrashift = (xtypebits - shift)/2; + bitcount_t rshift = shift > 64+8 ? (internal >> (bits - 6)) & 63 + : shift > 32+4 ? (internal >> (bits - 5)) & 31 + : shift > 16+2 ? (internal >> (bits - 4)) & 15 + : shift > 8+1 ? (internal >> (bits - 3)) & 7 + : shift > 4+1 ? (internal >> (bits - 2)) & 3 + : shift > 2+1 ? (internal >> (bits - 1)) & 1 + : 0; + internal ^= internal >> (shift + extrashift - rshift); + xtype result = internal >> rshift; + return result; + } +}; + +/* + * RXS M XS -- random xorshift, mcg multiply, fixed xorshift + * + * The most statistically powerful generator, but all those steps + * make it slower than some of the others. We give it the rottenest jobs. + * + * Because it's usually used in contexts where the state type and the + * result type are the same, it is a permutation and is thus invertable. + * We thus provide a function to invert it. This function is used to + * for the "inside out" generator used by the extended generator. + */ + +/* Defined type-based concepts for the multiplication step. They're actually + * all derived by truncating the 128-bit, which was computed to be a good + * "universal" constant. + */ + +template +struct mcg_multiplier { + // Not defined for an arbitrary type +}; + +template +struct mcg_unmultiplier { + // Not defined for an arbitrary type +}; + +PCG_DEFINE_CONSTANT(uint8_t, mcg, multiplier, 217U) +PCG_DEFINE_CONSTANT(uint8_t, mcg, unmultiplier, 105U) + +PCG_DEFINE_CONSTANT(uint16_t, mcg, multiplier, 62169U) +PCG_DEFINE_CONSTANT(uint16_t, mcg, unmultiplier, 28009U) + +PCG_DEFINE_CONSTANT(uint32_t, mcg, multiplier, 277803737U) +PCG_DEFINE_CONSTANT(uint32_t, mcg, unmultiplier, 2897767785U) + +PCG_DEFINE_CONSTANT(uint64_t, mcg, multiplier, 12605985483714917081ULL) +PCG_DEFINE_CONSTANT(uint64_t, mcg, unmultiplier, 15009553638781119849ULL) + +PCG_DEFINE_CONSTANT(pcg128_t, mcg, multiplier, + PCG_128BIT_CONSTANT(17766728186571221404ULL, 12605985483714917081ULL)) +PCG_DEFINE_CONSTANT(pcg128_t, mcg, unmultiplier, + PCG_128BIT_CONSTANT(14422606686972528997ULL, 15009553638781119849ULL)) + + +template +struct rxs_m_xs_mixin { + static xtype output(itype internal) + { + constexpr bitcount_t xtypebits = bitcount_t(sizeof(xtype) * 8); + constexpr bitcount_t bits = bitcount_t(sizeof(itype) * 8); + constexpr bitcount_t opbits = xtypebits >= 128 ? 6 + : xtypebits >= 64 ? 5 + : xtypebits >= 32 ? 4 + : xtypebits >= 16 ? 3 + : 2; + constexpr bitcount_t shift = bits - xtypebits; + constexpr bitcount_t mask = (1 << opbits) - 1; + bitcount_t rshift = + opbits ? bitcount_t(internal >> (bits - opbits)) & mask : 0; + internal ^= internal >> (opbits + rshift); + internal *= mcg_multiplier::multiplier(); + xtype result = internal >> shift; + result ^= result >> ((2U*xtypebits+2U)/3U); + return result; + } + + static itype unoutput(itype internal) + { + constexpr bitcount_t bits = bitcount_t(sizeof(itype) * 8); + constexpr bitcount_t opbits = bits >= 128 ? 6 + : bits >= 64 ? 5 + : bits >= 32 ? 4 + : bits >= 16 ? 3 + : 2; + constexpr bitcount_t mask = (1 << opbits) - 1; + + internal = unxorshift(internal, bits, (2U*bits+2U)/3U); + + internal *= mcg_unmultiplier::unmultiplier(); + + bitcount_t rshift = opbits ? (internal >> (bits - opbits)) & mask : 0; + internal = unxorshift(internal, bits, opbits + rshift); + + return internal; + } +}; + + +/* + * RXS M -- random xorshift, mcg multiply + */ + +template +struct rxs_m_mixin { + static xtype output(itype internal) + { + constexpr bitcount_t xtypebits = bitcount_t(sizeof(xtype) * 8); + constexpr bitcount_t bits = bitcount_t(sizeof(itype) * 8); + constexpr bitcount_t opbits = xtypebits >= 128 ? 6 + : xtypebits >= 64 ? 5 + : xtypebits >= 32 ? 4 + : xtypebits >= 16 ? 3 + : 2; + constexpr bitcount_t shift = bits - xtypebits; + constexpr bitcount_t mask = (1 << opbits) - 1; + bitcount_t rshift = opbits ? (internal >> (bits - opbits)) & mask : 0; + internal ^= internal >> (opbits + rshift); + internal *= mcg_multiplier::multiplier(); + xtype result = internal >> shift; + return result; + } +}; + + +/* + * DXSM -- double xorshift multiply + * + * This is a new, more powerful output permutation (added in 2019). It's + * a more comprehensive scrambling than RXS M, but runs faster on 128-bit + * types. Although primarily intended for use at large sizes, also works + * at smaller sizes as well. + * + * This permutation is similar to xorshift multiply hash functions, except + * that one of the multipliers is the LCG multiplier (to avoid needing to + * have a second constant) and the other is based on the low-order bits. + * This latter aspect means that the scrambling applied to the high bits + * depends on the low bits, and makes it (to my eye) impractical to back + * out the permutation without having the low-order bits. + */ + +template +struct dxsm_mixin { + inline xtype output(itype internal) + { + constexpr bitcount_t xtypebits = bitcount_t(sizeof(xtype) * 8); + constexpr bitcount_t itypebits = bitcount_t(sizeof(itype) * 8); + static_assert(xtypebits <= itypebits/2, + "Output type must be half the size of the state type."); + + xtype hi = xtype(internal >> (itypebits - xtypebits)); + xtype lo = xtype(internal); + + lo |= 1; + hi ^= hi >> (xtypebits/2); + hi *= xtype(cheap_multiplier::multiplier()); + hi ^= hi >> (3*(xtypebits/4)); + hi *= lo; + return hi; + } +}; + + +/* + * XSL RR -- fixed xorshift (to low bits), random rotate + * + * Useful for 128-bit types that are split across two CPU registers. + */ + +template +struct xsl_rr_mixin { + static xtype output(itype internal) + { + constexpr bitcount_t xtypebits = bitcount_t(sizeof(xtype) * 8); + constexpr bitcount_t bits = bitcount_t(sizeof(itype) * 8); + constexpr bitcount_t sparebits = bits - xtypebits; + constexpr bitcount_t wantedopbits = xtypebits >= 128 ? 7 + : xtypebits >= 64 ? 6 + : xtypebits >= 32 ? 5 + : xtypebits >= 16 ? 4 + : 3; + constexpr bitcount_t opbits = sparebits >= wantedopbits ? wantedopbits + : sparebits; + constexpr bitcount_t amplifier = wantedopbits - opbits; + constexpr bitcount_t mask = (1 << opbits) - 1; + constexpr bitcount_t topspare = sparebits; + constexpr bitcount_t bottomspare = sparebits - topspare; + constexpr bitcount_t xshift = (topspare + xtypebits) / 2; + + bitcount_t rot = + opbits ? bitcount_t(internal >> (bits - opbits)) & mask : 0; + bitcount_t amprot = (rot << amplifier) & mask; + internal ^= internal >> xshift; + xtype result = xtype(internal >> bottomspare); + result = rotr(result, amprot); + return result; + } +}; + + +/* + * XSL RR RR -- fixed xorshift (to low bits), random rotate (both parts) + * + * Useful for 128-bit types that are split across two CPU registers. + * If you really want an invertable 128-bit RNG, I guess this is the one. + */ + +template struct halfsize_trait {}; +template <> struct halfsize_trait { typedef uint64_t type; }; +template <> struct halfsize_trait { typedef uint32_t type; }; +template <> struct halfsize_trait { typedef uint16_t type; }; +template <> struct halfsize_trait { typedef uint8_t type; }; + +template +struct xsl_rr_rr_mixin { + typedef typename halfsize_trait::type htype; + + static itype output(itype internal) + { + constexpr bitcount_t htypebits = bitcount_t(sizeof(htype) * 8); + constexpr bitcount_t bits = bitcount_t(sizeof(itype) * 8); + constexpr bitcount_t sparebits = bits - htypebits; + constexpr bitcount_t wantedopbits = htypebits >= 128 ? 7 + : htypebits >= 64 ? 6 + : htypebits >= 32 ? 5 + : htypebits >= 16 ? 4 + : 3; + constexpr bitcount_t opbits = sparebits >= wantedopbits ? wantedopbits + : sparebits; + constexpr bitcount_t amplifier = wantedopbits - opbits; + constexpr bitcount_t mask = (1 << opbits) - 1; + constexpr bitcount_t topspare = sparebits; + constexpr bitcount_t xshift = (topspare + htypebits) / 2; + + bitcount_t rot = + opbits ? bitcount_t(internal >> (bits - opbits)) & mask : 0; + bitcount_t amprot = (rot << amplifier) & mask; + internal ^= internal >> xshift; + htype lowbits = htype(internal); + lowbits = rotr(lowbits, amprot); + htype highbits = htype(internal >> topspare); + bitcount_t rot2 = lowbits & mask; + bitcount_t amprot2 = (rot2 << amplifier) & mask; + highbits = rotr(highbits, amprot2); + return (itype(highbits) << topspare) ^ itype(lowbits); + } +}; + + +/* + * XSH -- fixed xorshift (to high bits) + * + * You shouldn't use this at 64-bits or less. + */ + +template +struct xsh_mixin { + static xtype output(itype internal) + { + constexpr bitcount_t xtypebits = bitcount_t(sizeof(xtype) * 8); + constexpr bitcount_t bits = bitcount_t(sizeof(itype) * 8); + constexpr bitcount_t sparebits = bits - xtypebits; + constexpr bitcount_t topspare = 0; + constexpr bitcount_t bottomspare = sparebits - topspare; + constexpr bitcount_t xshift = (topspare + xtypebits) / 2; + + internal ^= internal >> xshift; + xtype result = internal >> bottomspare; + return result; + } +}; + +/* + * XSL -- fixed xorshift (to low bits) + * + * You shouldn't use this at 64-bits or less. + */ + +template +struct xsl_mixin { + inline xtype output(itype internal) + { + constexpr bitcount_t xtypebits = bitcount_t(sizeof(xtype) * 8); + constexpr bitcount_t bits = bitcount_t(sizeof(itype) * 8); + constexpr bitcount_t sparebits = bits - xtypebits; + constexpr bitcount_t topspare = sparebits; + constexpr bitcount_t bottomspare = sparebits - topspare; + constexpr bitcount_t xshift = (topspare + xtypebits) / 2; + + internal ^= internal >> xshift; + xtype result = internal >> bottomspare; + return result; + } +}; + + +/* ---- End of Output Functions ---- */ + + +template +struct inside_out : private baseclass { + inside_out() = delete; + + typedef typename baseclass::result_type result_type; + typedef typename baseclass::state_type state_type; + static_assert(sizeof(result_type) == sizeof(state_type), + "Require a RNG whose output function is a permutation"); + + static bool external_step(result_type& randval, size_t i) + { + state_type state = baseclass::unoutput(randval); + state = state * baseclass::multiplier() + baseclass::increment() + + state_type(i*2); + result_type result = baseclass::output(state); + randval = result; + state_type zero = + baseclass::is_mcg ? state & state_type(3U) : state_type(0U); + return result == zero; + } + + static bool external_advance(result_type& randval, size_t i, + result_type delta, bool forwards = true) + { + state_type state = baseclass::unoutput(randval); + state_type mult = baseclass::multiplier(); + state_type inc = baseclass::increment() + state_type(i*2); + state_type zero = + baseclass::is_mcg ? state & state_type(3U) : state_type(0U); + state_type dist_to_zero = baseclass::distance(state, zero, mult, inc); + bool crosses_zero = + forwards ? dist_to_zero <= delta + : (-dist_to_zero) <= delta; + if (!forwards) + delta = -delta; + state = baseclass::advance(state, delta, mult, inc); + randval = baseclass::output(state); + return crosses_zero; + } +}; + + +template +class extended : public baseclass { +public: + typedef typename baseclass::state_type state_type; + typedef typename baseclass::result_type result_type; + typedef inside_out insideout; + +private: + static constexpr bitcount_t rtypebits = sizeof(result_type)*8; + static constexpr bitcount_t stypebits = sizeof(state_type)*8; + + static constexpr bitcount_t tick_limit_pow2 = 64U; + + static constexpr size_t table_size = 1UL << table_pow2; + static constexpr size_t table_shift = stypebits - table_pow2; + static constexpr state_type table_mask = + (state_type(1U) << table_pow2) - state_type(1U); + + static constexpr bool may_tick = + (advance_pow2 < stypebits) && (advance_pow2 < tick_limit_pow2); + static constexpr size_t tick_shift = stypebits - advance_pow2; + static constexpr state_type tick_mask = + may_tick ? state_type( + (uint64_t(1) << (advance_pow2*may_tick)) - 1) + // ^-- stupidity to appease GCC warnings + : ~state_type(0U); + + static constexpr bool may_tock = stypebits < tick_limit_pow2; + + result_type data_[table_size]; + + PCG_NOINLINE void advance_table(); + + PCG_NOINLINE void advance_table(state_type delta, bool isForwards = true); + + result_type& get_extended_value() + { + state_type state = this->state_; + if (kdd && baseclass::is_mcg) { + // The low order bits of an MCG are constant, so drop them. + state >>= 2; + } + size_t index = kdd ? state & table_mask + : state >> table_shift; + + if (may_tick) { + bool tick = kdd ? (state & tick_mask) == state_type(0u) + : (state >> tick_shift) == state_type(0u); + if (tick) + advance_table(); + } + if (may_tock) { + bool tock = state == state_type(0u); + if (tock) + advance_table(); + } + return data_[index]; + } + +public: + static constexpr size_t period_pow2() + { + return baseclass::period_pow2() + table_size*extvalclass::period_pow2(); + } + + PCG_ALWAYS_INLINE result_type operator()() + { + result_type rhs = get_extended_value(); + result_type lhs = this->baseclass::operator()(); + return lhs ^ rhs; + } + + result_type operator()(result_type upper_bound) + { + return bounded_rand(*this, upper_bound); + } + + void set(result_type wanted) + { + result_type& rhs = get_extended_value(); + result_type lhs = this->baseclass::operator()(); + rhs = lhs ^ wanted; + } + + void advance(state_type distance, bool forwards = true); + + void backstep(state_type distance) + { + advance(distance, false); + } + + extended(const result_type* data) + : baseclass() + { + datainit(data); + } + + extended(const result_type* data, state_type seed) + : baseclass(seed) + { + datainit(data); + } + + // This function may or may not exist. It thus has to be a template + // to use SFINAE; users don't have to worry about its template-ness. + + template + extended(const result_type* data, state_type seed, + typename bc::stream_state stream_seed) + : baseclass(seed, stream_seed) + { + datainit(data); + } + + extended() + : baseclass() + { + selfinit(); + } + + extended(state_type seed) + : baseclass(seed) + { + selfinit(); + } + + // This function may or may not exist. It thus has to be a template + // to use SFINAE; users don't have to worry about its template-ness. + + template + extended(state_type seed, typename bc::stream_state stream_seed) + : baseclass(seed, stream_seed) + { + selfinit(); + } + +private: + void selfinit(); + void datainit(const result_type* data); + +public: + + template::value + && !std::is_convertible::value>::type> + extended(SeedSeq&& seedSeq) + : baseclass(seedSeq) + { + generate_to(seedSeq, data_); + } + + template + void seed(Args&&... args) + { + new (this) extended(std::forward(args)...); + } + + template + friend bool operator==(const extended&, + const extended&); + + template + friend std::basic_ostream& + operator<<(std::basic_ostream& out, + const extended&); + + template + friend std::basic_istream& + operator>>(std::basic_istream& in, + extended&); + +}; + + +template +void extended::datainit( + const result_type* data) +{ + for (size_t i = 0; i < table_size; ++i) + data_[i] = data[i]; +} + +template +void extended::selfinit() +{ + // We need to fill the extended table with something, and we have + // very little provided data, so we use the base generator to + // produce values. Although not ideal (use a seed sequence, folks!), + // unexpected correlations are mitigated by + // - using XOR differences rather than the number directly + // - the way the table is accessed, its values *won't* be accessed + // in the same order the were written. + // - any strange correlations would only be apparent if we + // were to backstep the generator so that the base generator + // was generating the same values again + result_type lhs = baseclass::operator()(); + result_type rhs = baseclass::operator()(); + result_type xdiff = lhs - rhs; + for (size_t i = 0; i < table_size; ++i) { + data_[i] = baseclass::operator()() ^ xdiff; + } +} + +template +bool operator==(const extended& lhs, + const extended& rhs) +{ + auto& base_lhs = static_cast(lhs); + auto& base_rhs = static_cast(rhs); + return base_lhs == base_rhs + && std::equal( + std::begin(lhs.data_), std::end(lhs.data_), + std::begin(rhs.data_) + ); +} + +template +inline bool operator!=(const extended& lhs, + const extended& rhs) +{ + return !operator==(lhs, rhs); +} + +template +std::basic_ostream& +operator<<(std::basic_ostream& out, + const extended& rng) +{ + using pcg_extras::operator<<; + + auto orig_flags = out.flags(std::ios_base::dec | std::ios_base::left); + auto space = out.widen(' '); + auto orig_fill = out.fill(); + + out << rng.multiplier() << space + << rng.increment() << space + << rng.state_; + + for (const auto& datum : rng.data_) + out << space << datum; + + out.flags(orig_flags); + out.fill(orig_fill); + return out; +} + +template +std::basic_istream& +operator>>(std::basic_istream& in, + extended& rng) +{ + extended new_rng; + auto& base_rng = static_cast(new_rng); + in >> base_rng; + + if (in.fail()) + return in; + + using pcg_extras::operator>>; + + auto orig_flags = in.flags(std::ios_base::dec | std::ios_base::skipws); + + for (auto& datum : new_rng.data_) { + in >> datum; + if (in.fail()) + goto bail; + } + + rng = new_rng; + +bail: + in.flags(orig_flags); + return in; +} + + + +template +void +extended::advance_table() +{ + bool carry = false; + for (size_t i = 0; i < table_size; ++i) { + if (carry) { + carry = insideout::external_step(data_[i],i+1); + } + bool carry2 = insideout::external_step(data_[i],i+1); + carry = carry || carry2; + } +} + +template +void +extended::advance_table( + state_type delta, bool isForwards) +{ + typedef typename baseclass::state_type base_state_t; + typedef typename extvalclass::state_type ext_state_t; + constexpr bitcount_t basebits = sizeof(base_state_t)*8; + constexpr bitcount_t extbits = sizeof(ext_state_t)*8; + static_assert(basebits <= extbits || advance_pow2 > 0, + "Current implementation might overflow its carry"); + + base_state_t carry = 0; + for (size_t i = 0; i < table_size; ++i) { + base_state_t total_delta = carry + delta; + ext_state_t trunc_delta = ext_state_t(total_delta); + if (basebits > extbits) { + carry = total_delta >> extbits; + } else { + carry = 0; + } + carry += + insideout::external_advance(data_[i],i+1, trunc_delta, isForwards); + } +} + +template +void extended::advance( + state_type distance, bool forwards) +{ + static_assert(kdd, + "Efficient advance is too hard for non-kdd extension. " + "For a weak advance, cast to base class"); + state_type zero = + baseclass::is_mcg ? this->state_ & state_type(3U) : state_type(0U); + if (may_tick) { + state_type ticks = distance >> (advance_pow2*may_tick); + // ^-- stupidity to appease GCC + // warnings + state_type adv_mask = + baseclass::is_mcg ? tick_mask << 2 : tick_mask; + state_type next_advance_distance = this->distance(zero, adv_mask); + if (!forwards) + next_advance_distance = (-next_advance_distance) & tick_mask; + if (next_advance_distance < (distance & tick_mask)) { + ++ticks; + } + if (ticks) + advance_table(ticks, forwards); + } + if (forwards) { + if (may_tock && this->distance(zero) <= distance) + advance_table(); + baseclass::advance(distance); + } else { + if (may_tock && -(this->distance(zero)) <= distance) + advance_table(state_type(1U), false); + baseclass::advance(-distance); + } +} + +} // namespace pcg_detail + +namespace pcg_engines { + +using namespace pcg_detail; + +/* Predefined types for XSH RS */ + +typedef oneseq_base oneseq_xsh_rs_16_8; +typedef oneseq_base oneseq_xsh_rs_32_16; +typedef oneseq_base oneseq_xsh_rs_64_32; +typedef oneseq_base oneseq_xsh_rs_128_64; +typedef oneseq_base + cm_oneseq_xsh_rs_128_64; + +typedef unique_base unique_xsh_rs_16_8; +typedef unique_base unique_xsh_rs_32_16; +typedef unique_base unique_xsh_rs_64_32; +typedef unique_base unique_xsh_rs_128_64; +typedef unique_base + cm_unique_xsh_rs_128_64; + +typedef setseq_base setseq_xsh_rs_16_8; +typedef setseq_base setseq_xsh_rs_32_16; +typedef setseq_base setseq_xsh_rs_64_32; +typedef setseq_base setseq_xsh_rs_128_64; +typedef setseq_base + cm_setseq_xsh_rs_128_64; + +typedef mcg_base mcg_xsh_rs_16_8; +typedef mcg_base mcg_xsh_rs_32_16; +typedef mcg_base mcg_xsh_rs_64_32; +typedef mcg_base mcg_xsh_rs_128_64; +typedef mcg_base + cm_mcg_xsh_rs_128_64; + +/* Predefined types for XSH RR */ + +typedef oneseq_base oneseq_xsh_rr_16_8; +typedef oneseq_base oneseq_xsh_rr_32_16; +typedef oneseq_base oneseq_xsh_rr_64_32; +typedef oneseq_base oneseq_xsh_rr_128_64; +typedef oneseq_base + cm_oneseq_xsh_rr_128_64; + +typedef unique_base unique_xsh_rr_16_8; +typedef unique_base unique_xsh_rr_32_16; +typedef unique_base unique_xsh_rr_64_32; +typedef unique_base unique_xsh_rr_128_64; +typedef unique_base + cm_unique_xsh_rr_128_64; + +typedef setseq_base setseq_xsh_rr_16_8; +typedef setseq_base setseq_xsh_rr_32_16; +typedef setseq_base setseq_xsh_rr_64_32; +typedef setseq_base setseq_xsh_rr_128_64; +typedef setseq_base + cm_setseq_xsh_rr_128_64; + +typedef mcg_base mcg_xsh_rr_16_8; +typedef mcg_base mcg_xsh_rr_32_16; +typedef mcg_base mcg_xsh_rr_64_32; +typedef mcg_base mcg_xsh_rr_128_64; +typedef mcg_base + cm_mcg_xsh_rr_128_64; + + +/* Predefined types for RXS M XS */ + +typedef oneseq_base oneseq_rxs_m_xs_8_8; +typedef oneseq_base oneseq_rxs_m_xs_16_16; +typedef oneseq_base oneseq_rxs_m_xs_32_32; +typedef oneseq_base oneseq_rxs_m_xs_64_64; +typedef oneseq_base + oneseq_rxs_m_xs_128_128; +typedef oneseq_base + cm_oneseq_rxs_m_xs_128_128; + +typedef unique_base unique_rxs_m_xs_8_8; +typedef unique_base unique_rxs_m_xs_16_16; +typedef unique_base unique_rxs_m_xs_32_32; +typedef unique_base unique_rxs_m_xs_64_64; +typedef unique_base unique_rxs_m_xs_128_128; +typedef unique_base + cm_unique_rxs_m_xs_128_128; + +typedef setseq_base setseq_rxs_m_xs_8_8; +typedef setseq_base setseq_rxs_m_xs_16_16; +typedef setseq_base setseq_rxs_m_xs_32_32; +typedef setseq_base setseq_rxs_m_xs_64_64; +typedef setseq_base setseq_rxs_m_xs_128_128; +typedef setseq_base + cm_setseq_rxs_m_xs_128_128; + + // MCG versions don't make sense here, so aren't defined. + +/* Predefined types for RXS M */ + +typedef oneseq_base oneseq_rxs_m_16_8; +typedef oneseq_base oneseq_rxs_m_32_16; +typedef oneseq_base oneseq_rxs_m_64_32; +typedef oneseq_base oneseq_rxs_m_128_64; +typedef oneseq_base + cm_oneseq_rxs_m_128_64; + +typedef unique_base unique_rxs_m_16_8; +typedef unique_base unique_rxs_m_32_16; +typedef unique_base unique_rxs_m_64_32; +typedef unique_base unique_rxs_m_128_64; +typedef unique_base + cm_unique_rxs_m_128_64; + +typedef setseq_base setseq_rxs_m_16_8; +typedef setseq_base setseq_rxs_m_32_16; +typedef setseq_base setseq_rxs_m_64_32; +typedef setseq_base setseq_rxs_m_128_64; +typedef setseq_base + cm_setseq_rxs_m_128_64; + +typedef mcg_base mcg_rxs_m_16_8; +typedef mcg_base mcg_rxs_m_32_16; +typedef mcg_base mcg_rxs_m_64_32; +typedef mcg_base mcg_rxs_m_128_64; +typedef mcg_base + cm_mcg_rxs_m_128_64; + +/* Predefined types for DXSM */ + +typedef oneseq_base oneseq_dxsm_16_8; +typedef oneseq_base oneseq_dxsm_32_16; +typedef oneseq_base oneseq_dxsm_64_32; +typedef oneseq_base oneseq_dxsm_128_64; +typedef oneseq_base + cm_oneseq_dxsm_128_64; + +typedef unique_base unique_dxsm_16_8; +typedef unique_base unique_dxsm_32_16; +typedef unique_base unique_dxsm_64_32; +typedef unique_base unique_dxsm_128_64; +typedef unique_base + cm_unique_dxsm_128_64; + +typedef setseq_base setseq_dxsm_16_8; +typedef setseq_base setseq_dxsm_32_16; +typedef setseq_base setseq_dxsm_64_32; +typedef setseq_base setseq_dxsm_128_64; +typedef setseq_base + cm_setseq_dxsm_128_64; + +typedef mcg_base mcg_dxsm_16_8; +typedef mcg_base mcg_dxsm_32_16; +typedef mcg_base mcg_dxsm_64_32; +typedef mcg_base mcg_dxsm_128_64; +typedef mcg_base + cm_mcg_dxsm_128_64; + +/* Predefined types for XSL RR (only defined for "large" types) */ + +typedef oneseq_base oneseq_xsl_rr_64_32; +typedef oneseq_base oneseq_xsl_rr_128_64; +typedef oneseq_base + cm_oneseq_xsl_rr_128_64; + +typedef unique_base unique_xsl_rr_64_32; +typedef unique_base unique_xsl_rr_128_64; +typedef unique_base + cm_unique_xsl_rr_128_64; + +typedef setseq_base setseq_xsl_rr_64_32; +typedef setseq_base setseq_xsl_rr_128_64; +typedef setseq_base + cm_setseq_xsl_rr_128_64; + +typedef mcg_base mcg_xsl_rr_64_32; +typedef mcg_base mcg_xsl_rr_128_64; +typedef mcg_base + cm_mcg_xsl_rr_128_64; + + +/* Predefined types for XSL RR RR (only defined for "large" types) */ + +typedef oneseq_base + oneseq_xsl_rr_rr_64_64; +typedef oneseq_base + oneseq_xsl_rr_rr_128_128; +typedef oneseq_base + cm_oneseq_xsl_rr_rr_128_128; + +typedef unique_base + unique_xsl_rr_rr_64_64; +typedef unique_base + unique_xsl_rr_rr_128_128; +typedef unique_base + cm_unique_xsl_rr_rr_128_128; + +typedef setseq_base + setseq_xsl_rr_rr_64_64; +typedef setseq_base + setseq_xsl_rr_rr_128_128; +typedef setseq_base + cm_setseq_xsl_rr_rr_128_128; + + // MCG versions don't make sense here, so aren't defined. + +/* Extended generators */ + +template +using ext_std8 = extended; + +template +using ext_std16 = extended; + +template +using ext_std32 = extended; + +template +using ext_std64 = extended; + + +template +using ext_oneseq_rxs_m_xs_32_32 = + ext_std32; + +template +using ext_mcg_xsh_rs_64_32 = + ext_std32; + +template +using ext_oneseq_xsh_rs_64_32 = + ext_std32; + +template +using ext_setseq_xsh_rr_64_32 = + ext_std32; + +template +using ext_mcg_xsl_rr_128_64 = + ext_std64; + +template +using ext_oneseq_xsl_rr_128_64 = + ext_std64; + +template +using ext_setseq_xsl_rr_128_64 = + ext_std64; + +} // namespace pcg_engines + +typedef pcg_engines::setseq_xsh_rr_64_32 pcg32; +typedef pcg_engines::oneseq_xsh_rr_64_32 pcg32_oneseq; +typedef pcg_engines::unique_xsh_rr_64_32 pcg32_unique; +typedef pcg_engines::mcg_xsh_rs_64_32 pcg32_fast; + +typedef pcg_engines::setseq_xsl_rr_128_64 pcg64; +typedef pcg_engines::oneseq_xsl_rr_128_64 pcg64_oneseq; +typedef pcg_engines::unique_xsl_rr_128_64 pcg64_unique; +typedef pcg_engines::mcg_xsl_rr_128_64 pcg64_fast; + +typedef pcg_engines::setseq_rxs_m_xs_8_8 pcg8_once_insecure; +typedef pcg_engines::setseq_rxs_m_xs_16_16 pcg16_once_insecure; +typedef pcg_engines::setseq_rxs_m_xs_32_32 pcg32_once_insecure; +typedef pcg_engines::setseq_rxs_m_xs_64_64 pcg64_once_insecure; +typedef pcg_engines::setseq_xsl_rr_rr_128_128 pcg128_once_insecure; + +typedef pcg_engines::oneseq_rxs_m_xs_8_8 pcg8_oneseq_once_insecure; +typedef pcg_engines::oneseq_rxs_m_xs_16_16 pcg16_oneseq_once_insecure; +typedef pcg_engines::oneseq_rxs_m_xs_32_32 pcg32_oneseq_once_insecure; +typedef pcg_engines::oneseq_rxs_m_xs_64_64 pcg64_oneseq_once_insecure; +typedef pcg_engines::oneseq_xsl_rr_rr_128_128 pcg128_oneseq_once_insecure; + + +// These two extended RNGs provide two-dimensionally equidistributed +// 32-bit generators. pcg32_k2_fast occupies the same space as pcg64, +// and can be called twice to generate 64 bits, but does not required +// 128-bit math; on 32-bit systems, it's faster than pcg64 as well. + +typedef pcg_engines::ext_setseq_xsh_rr_64_32<1,16,true> pcg32_k2; +typedef pcg_engines::ext_oneseq_xsh_rs_64_32<1,32,true> pcg32_k2_fast; + +// These eight extended RNGs have about as much state as arc4random +// +// - the k variants are k-dimensionally equidistributed +// - the c variants offer are intended to be harder to predict +// +// (neither is intended for use in cryptographic applications) + +typedef pcg_engines::ext_setseq_xsh_rr_64_32<6,16,true> pcg32_k64; +typedef pcg_engines::ext_mcg_xsh_rs_64_32<6,32,true> pcg32_k64_oneseq; +typedef pcg_engines::ext_oneseq_xsh_rs_64_32<6,32,true> pcg32_k64_fast; + +typedef pcg_engines::ext_setseq_xsh_rr_64_32<6,16,false> pcg32_c64; +typedef pcg_engines::ext_oneseq_xsh_rs_64_32<6,32,false> pcg32_c64_oneseq; +typedef pcg_engines::ext_mcg_xsh_rs_64_32<6,32,false> pcg32_c64_fast; + +typedef pcg_engines::ext_setseq_xsl_rr_128_64<5,16,true> pcg64_k32; +typedef pcg_engines::ext_oneseq_xsl_rr_128_64<5,128,true> pcg64_k32_oneseq; +typedef pcg_engines::ext_mcg_xsl_rr_128_64<5,128,true> pcg64_k32_fast; + +typedef pcg_engines::ext_setseq_xsl_rr_128_64<5,16,false> pcg64_c32; +typedef pcg_engines::ext_oneseq_xsl_rr_128_64<5,128,false> pcg64_c32_oneseq; +typedef pcg_engines::ext_mcg_xsl_rr_128_64<5,128,false> pcg64_c32_fast; + +// These eight extended RNGs have more state than the Mersenne twister +// +// - the k variants are k-dimensionally equidistributed +// - the c variants offer are intended to be harder to predict +// +// (neither is intended for use in cryptographic applications) + +typedef pcg_engines::ext_setseq_xsh_rr_64_32<10,16,true> pcg32_k1024; +typedef pcg_engines::ext_oneseq_xsh_rs_64_32<10,32,true> pcg32_k1024_fast; + +typedef pcg_engines::ext_setseq_xsh_rr_64_32<10,16,false> pcg32_c1024; +typedef pcg_engines::ext_oneseq_xsh_rs_64_32<10,32,false> pcg32_c1024_fast; + +typedef pcg_engines::ext_setseq_xsl_rr_128_64<10,16,true> pcg64_k1024; +typedef pcg_engines::ext_oneseq_xsl_rr_128_64<10,128,true> pcg64_k1024_fast; + +typedef pcg_engines::ext_setseq_xsl_rr_128_64<10,16,false> pcg64_c1024; +typedef pcg_engines::ext_oneseq_xsl_rr_128_64<10,128,false> pcg64_c1024_fast; + +// These generators have an insanely huge period (2^524352), and is suitable +// for silly party tricks, such as dumping out 64 KB ZIP files at an arbitrary +// point in the future. [Actually, over the full period of the generator, it +// will produce every 64 KB ZIP file 2^64 times!] + +typedef pcg_engines::ext_setseq_xsh_rr_64_32<14,16,true> pcg32_k16384; +typedef pcg_engines::ext_oneseq_xsh_rs_64_32<14,32,true> pcg32_k16384_fast; + +#ifdef _MSC_VER + #pragma warning(default:4146) +#endif + +#endif // PCG_RAND_HPP_INCLUDED diff --git a/dep/PCG/pcg_uint128.hpp b/dep/PCG/pcg_uint128.hpp new file mode 100644 index 0000000000..75c569916f --- /dev/null +++ b/dep/PCG/pcg_uint128.hpp @@ -0,0 +1,1006 @@ +/* + * PCG Random Number Generation for C++ + * + * Copyright 2014-2021 Melissa O'Neill , + * and the PCG Project contributors. + * + * SPDX-License-Identifier: (Apache-2.0 OR MIT) + * + * Licensed under the Apache License, Version 2.0 (provided in + * LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0) + * or under the MIT license (provided in LICENSE-MIT.txt and at + * http://opensource.org/licenses/MIT), at your option. This file may not + * be copied, modified, or distributed except according to those terms. + * + * Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See your chosen license for details. + * + * For additional information about the PCG random number generation scheme, + * visit http://www.pcg-random.org/. + */ + +/* + * This code provides a a C++ class that can provide 128-bit (or higher) + * integers. To produce 2K-bit integers, it uses two K-bit integers, + * placed in a union that allowes the code to also see them as four K/2 bit + * integers (and access them either directly name, or by index). + * + * It may seem like we're reinventing the wheel here, because several + * libraries already exist that support large integers, but most existing + * libraries provide a very generic multiprecision code, but here we're + * operating at a fixed size. Also, most other libraries are fairly + * heavyweight. So we use a direct implementation. Sadly, it's much slower + * than hand-coded assembly or direct CPU support. + */ + +#ifndef PCG_UINT128_HPP_INCLUDED +#define PCG_UINT128_HPP_INCLUDED 1 + +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) // Use MSVC++ intrinsics +#include +#endif + +/* + * We want to lay the type out the same way that a native type would be laid + * out, which means we must know the machine's endian, at compile time. + * This ugliness attempts to do so. + */ + +#ifndef PCG_LITTLE_ENDIAN + #if defined(__BYTE_ORDER__) + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + #define PCG_LITTLE_ENDIAN 1 + #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + #define PCG_LITTLE_ENDIAN 0 + #else + #error __BYTE_ORDER__ does not match a standard endian, pick a side + #endif + #elif __LITTLE_ENDIAN__ || _LITTLE_ENDIAN + #define PCG_LITTLE_ENDIAN 1 + #elif __BIG_ENDIAN__ || _BIG_ENDIAN + #define PCG_LITTLE_ENDIAN 0 + #elif __x86_64 || __x86_64__ || _M_X64 || __i386 || __i386__ || _M_IX86 + #define PCG_LITTLE_ENDIAN 1 + #elif __powerpc__ || __POWERPC__ || __ppc__ || __PPC__ \ + || __m68k__ || __mc68000__ + #define PCG_LITTLE_ENDIAN 0 + #else + #error Unable to determine target endianness + #endif +#endif + +#if INTPTR_MAX == INT64_MAX && !defined(PCG_64BIT_SPECIALIZATIONS) + #define PCG_64BIT_SPECIALIZATIONS 1 +#endif + +namespace pcg_extras { + +// Recent versions of GCC have intrinsics we can use to quickly calculate +// the number of leading and trailing zeros in a number. If possible, we +// use them, otherwise we fall back to old-fashioned bit twiddling to figure +// them out. + +#ifndef PCG_BITCOUNT_T + typedef uint8_t bitcount_t; +#else + typedef PCG_BITCOUNT_T bitcount_t; +#endif + +/* + * Provide some useful helper functions + * * flog2 floor(log2(x)) + * * trailingzeros number of trailing zero bits + */ + +#if defined(__GNUC__) // Any GNU-compatible compiler supporting C++11 has + // some useful intrinsics we can use. + +inline bitcount_t flog2(uint32_t v) +{ + return 31 - __builtin_clz(v); +} + +inline bitcount_t trailingzeros(uint32_t v) +{ + return __builtin_ctz(v); +} + +inline bitcount_t flog2(uint64_t v) +{ +#if UINT64_MAX == ULONG_MAX + return 63 - __builtin_clzl(v); +#elif UINT64_MAX == ULLONG_MAX + return 63 - __builtin_clzll(v); +#else + #error Cannot find a function for uint64_t +#endif +} + +inline bitcount_t trailingzeros(uint64_t v) +{ +#if UINT64_MAX == ULONG_MAX + return __builtin_ctzl(v); +#elif UINT64_MAX == ULLONG_MAX + return __builtin_ctzll(v); +#else + #error Cannot find a function for uint64_t +#endif +} + +#elif defined(_MSC_VER) // Use MSVC++ intrinsics + +#pragma intrinsic(_BitScanReverse, _BitScanForward) +#if defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64) +#pragma intrinsic(_BitScanReverse64, _BitScanForward64) +#endif + +inline bitcount_t flog2(uint32_t v) +{ + unsigned long i; + _BitScanReverse(&i, v); + return bitcount_t(i); +} + +inline bitcount_t trailingzeros(uint32_t v) +{ + unsigned long i; + _BitScanForward(&i, v); + return bitcount_t(i); +} + +inline bitcount_t flog2(uint64_t v) +{ +#if defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64) + unsigned long i; + _BitScanReverse64(&i, v); + return bitcount_t(i); +#else + // 32-bit x86 + uint32_t high = v >> 32; + uint32_t low = uint32_t(v); + return high ? 32+flog2(high) : flog2(low); +#endif +} + +inline bitcount_t trailingzeros(uint64_t v) +{ +#if defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64) + unsigned long i; + _BitScanForward64(&i, v); + return bitcount_t(i); +#else + // 32-bit x86 + uint32_t high = v >> 32; + uint32_t low = uint32_t(v); + return low ? trailingzeros(low) : trailingzeros(high)+32; +#endif +} + +#else // Otherwise, we fall back to bit twiddling + // implementations + +inline bitcount_t flog2(uint32_t v) +{ + // Based on code by Eric Cole and Mark Dickinson, which appears at + // https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn + + static const uint8_t multiplyDeBruijnBitPos[32] = { + 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 + }; + + v |= v >> 1; // first round down to one less than a power of 2 + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + + return multiplyDeBruijnBitPos[(uint32_t)(v * 0x07C4ACDDU) >> 27]; +} + +inline bitcount_t trailingzeros(uint32_t v) +{ + static const uint8_t multiplyDeBruijnBitPos[32] = { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + + return multiplyDeBruijnBitPos[((uint32_t)((v & -v) * 0x077CB531U)) >> 27]; +} + +inline bitcount_t flog2(uint64_t v) +{ + uint32_t high = v >> 32; + uint32_t low = uint32_t(v); + + return high ? 32+flog2(high) : flog2(low); +} + +inline bitcount_t trailingzeros(uint64_t v) +{ + uint32_t high = v >> 32; + uint32_t low = uint32_t(v); + + return low ? trailingzeros(low) : trailingzeros(high)+32; +} + +#endif + +inline bitcount_t flog2(uint8_t v) +{ + return flog2(uint32_t(v)); +} + +inline bitcount_t flog2(uint16_t v) +{ + return flog2(uint32_t(v)); +} + +#if __SIZEOF_INT128__ +inline bitcount_t flog2(__uint128_t v) +{ + uint64_t high = uint64_t(v >> 64); + uint64_t low = uint64_t(v); + + return high ? 64+flog2(high) : flog2(low); +} +#endif + +inline bitcount_t trailingzeros(uint8_t v) +{ + return trailingzeros(uint32_t(v)); +} + +inline bitcount_t trailingzeros(uint16_t v) +{ + return trailingzeros(uint32_t(v)); +} + +#if __SIZEOF_INT128__ +inline bitcount_t trailingzeros(__uint128_t v) +{ + uint64_t high = uint64_t(v >> 64); + uint64_t low = uint64_t(v); + return low ? trailingzeros(low) : trailingzeros(high)+64; +} +#endif + +template +inline bitcount_t clog2(UInt v) +{ + return flog2(v) + ((v & (-v)) != v); +} + +template +inline UInt addwithcarry(UInt x, UInt y, bool carryin, bool* carryout) +{ + UInt half_result = y + carryin; + UInt result = x + half_result; + *carryout = (half_result < y) || (result < x); + return result; +} + +template +inline UInt subwithcarry(UInt x, UInt y, bool carryin, bool* carryout) +{ + UInt half_result = y + carryin; + UInt result = x - half_result; + *carryout = (half_result < y) || (result > x); + return result; +} + + +template +class uint_x4 { +// private: + static constexpr unsigned int UINT_BITS = sizeof(UInt) * CHAR_BIT; +public: + union { +#if PCG_LITTLE_ENDIAN + struct { + UInt v0, v1, v2, v3; + } w; + struct { + UIntX2 v01, v23; + } d; +#else + struct { + UInt v3, v2, v1, v0; + } w; + struct { + UIntX2 v23, v01; + } d; +#endif + // For the array access versions, the code that uses the array + // must handle endian itself. Yuck. + UInt wa[4]; + }; + +public: + uint_x4() = default; + + constexpr uint_x4(UInt v3, UInt v2, UInt v1, UInt v0) +#if PCG_LITTLE_ENDIAN + : w{v0, v1, v2, v3} +#else + : w{v3, v2, v1, v0} +#endif + { + // Nothing (else) to do + } + + constexpr uint_x4(UIntX2 v23, UIntX2 v01) +#if PCG_LITTLE_ENDIAN + : d{v01,v23} +#else + : d{v23,v01} +#endif + { + // Nothing (else) to do + } + + constexpr uint_x4(UIntX2 v01) +#if PCG_LITTLE_ENDIAN + : d{v01, UIntX2(0)} +#else + : d{UIntX2(0),v01} +#endif + { + // Nothing (else) to do + } + + template::value + && sizeof(Integral) <= sizeof(UIntX2)) + >::type* = nullptr> + constexpr uint_x4(Integral v01) +#if PCG_LITTLE_ENDIAN + : d{UIntX2(v01), UIntX2(0)} +#else + : d{UIntX2(0), UIntX2(v01)} +#endif + { + // Nothing (else) to do + } + + explicit constexpr operator UIntX2() const + { + return d.v01; + } + + template::value + && sizeof(Integral) <= sizeof(UIntX2)) + >::type* = nullptr> + explicit constexpr operator Integral() const + { + return Integral(d.v01); + } + + explicit constexpr operator bool() const + { + return d.v01 || d.v23; + } + + template + friend uint_x4 operator*(const uint_x4&, const uint_x4&); + + template + friend uint_x4 operator*(const uint_x4&, V); + + template + friend std::pair< uint_x4,uint_x4 > + divmod(const uint_x4&, const uint_x4&); + + template + friend uint_x4 operator+(const uint_x4&, const uint_x4&); + + template + friend uint_x4 operator-(const uint_x4&, const uint_x4&); + + template + friend uint_x4 operator<<(const uint_x4&, const bitcount_t shift); + + template + friend uint_x4 operator>>(const uint_x4&, const bitcount_t shift); + +#if PCG_64BIT_SPECIALIZATIONS + template + friend uint_x4 operator<<(const uint_x4&, const bitcount_t shift); + + template + friend uint_x4 operator>>(const uint_x4&, const bitcount_t shift); +#endif + + template + friend uint_x4 operator&(const uint_x4&, const uint_x4&); + + template + friend uint_x4 operator|(const uint_x4&, const uint_x4&); + + template + friend uint_x4 operator^(const uint_x4&, const uint_x4&); + + template + friend bool operator==(const uint_x4&, const uint_x4&); + + template + friend bool operator!=(const uint_x4&, const uint_x4&); + + template + friend bool operator<(const uint_x4&, const uint_x4&); + + template + friend bool operator<=(const uint_x4&, const uint_x4&); + + template + friend bool operator>(const uint_x4&, const uint_x4&); + + template + friend bool operator>=(const uint_x4&, const uint_x4&); + + template + friend uint_x4 operator~(const uint_x4&); + + template + friend uint_x4 operator-(const uint_x4&); + + template + friend bitcount_t flog2(const uint_x4&); + + template + friend bitcount_t trailingzeros(const uint_x4&); + +#if PCG_64BIT_SPECIALIZATIONS + template + friend bitcount_t flog2(const uint_x4&); + + template + friend bitcount_t trailingzeros(const uint_x4&); +#endif + + uint_x4& operator*=(const uint_x4& rhs) + { + uint_x4 result = *this * rhs; + return *this = result; + } + + uint_x4& operator*=(UIntX2 rhs) + { + uint_x4 result = *this * rhs; + return *this = result; + } + + uint_x4& operator/=(const uint_x4& rhs) + { + uint_x4 result = *this / rhs; + return *this = result; + } + + uint_x4& operator%=(const uint_x4& rhs) + { + uint_x4 result = *this % rhs; + return *this = result; + } + + uint_x4& operator+=(const uint_x4& rhs) + { + uint_x4 result = *this + rhs; + return *this = result; + } + + uint_x4& operator-=(const uint_x4& rhs) + { + uint_x4 result = *this - rhs; + return *this = result; + } + + uint_x4& operator&=(const uint_x4& rhs) + { + uint_x4 result = *this & rhs; + return *this = result; + } + + uint_x4& operator|=(const uint_x4& rhs) + { + uint_x4 result = *this | rhs; + return *this = result; + } + + uint_x4& operator^=(const uint_x4& rhs) + { + uint_x4 result = *this ^ rhs; + return *this = result; + } + + uint_x4& operator>>=(bitcount_t shift) + { + uint_x4 result = *this >> shift; + return *this = result; + } + + uint_x4& operator<<=(bitcount_t shift) + { + uint_x4 result = *this << shift; + return *this = result; + } + +}; + +template +bitcount_t flog2(const uint_x4& v) +{ +#if PCG_LITTLE_ENDIAN + for (uint8_t i = 4; i !=0; /* dec in loop */) { + --i; +#else + for (uint8_t i = 0; i < 4; ++i) { +#endif + if (v.wa[i] == 0) + continue; + return flog2(v.wa[i]) + uint_x4::UINT_BITS*i; + } + abort(); +} + +template +bitcount_t trailingzeros(const uint_x4& v) +{ +#if PCG_LITTLE_ENDIAN + for (uint8_t i = 0; i < 4; ++i) { +#else + for (uint8_t i = 4; i !=0; /* dec in loop */) { + --i; +#endif + if (v.wa[i] != 0) + return trailingzeros(v.wa[i]) + uint_x4::UINT_BITS*i; + } + return uint_x4::UINT_BITS*4; +} + +#if PCG_64BIT_SPECIALIZATIONS +template +bitcount_t flog2(const uint_x4& v) +{ + return v.d.v23 > 0 ? flog2(v.d.v23) + uint_x4::UINT_BITS*2 + : flog2(v.d.v01); +} + +template +bitcount_t trailingzeros(const uint_x4& v) +{ + return v.d.v01 == 0 ? trailingzeros(v.d.v23) + uint_x4::UINT_BITS*2 + : trailingzeros(v.d.v01); +} +#endif + +template +std::pair< uint_x4, uint_x4 > + divmod(const uint_x4& orig_dividend, + const uint_x4& divisor) +{ + // If the dividend is less than the divisor, the answer is always zero. + // This takes care of boundary cases like 0/x (which would otherwise be + // problematic because we can't take the log of zero. (The boundary case + // of division by zero is undefined.) + if (orig_dividend < divisor) + return { uint_x4(UIntX2(0)), orig_dividend }; + + auto dividend = orig_dividend; + + auto log2_divisor = flog2(divisor); + auto log2_dividend = flog2(dividend); + // assert(log2_dividend >= log2_divisor); + bitcount_t logdiff = log2_dividend - log2_divisor; + + constexpr uint_x4 ONE(UIntX2(1)); + if (logdiff == 0) + return { ONE, dividend - divisor }; + + // Now we change the log difference to + // floor(log2(divisor)) - ceil(log2(dividend)) + // to ensure that we *underestimate* the result. + logdiff -= 1; + + uint_x4 quotient(UIntX2(0)); + + auto qfactor = ONE << logdiff; + auto factor = divisor << logdiff; + + do { + dividend -= factor; + quotient += qfactor; + while (dividend < factor) { + factor >>= 1; + qfactor >>= 1; + } + } while (dividend >= divisor); + + return { quotient, dividend }; +} + +template +uint_x4 operator/(const uint_x4& dividend, + const uint_x4& divisor) +{ + return divmod(dividend, divisor).first; +} + +template +uint_x4 operator%(const uint_x4& dividend, + const uint_x4& divisor) +{ + return divmod(dividend, divisor).second; +} + + +template +uint_x4 operator*(const uint_x4& a, + const uint_x4& b) +{ + constexpr auto UINT_BITS = uint_x4::UINT_BITS; + uint_x4 r = {0U, 0U, 0U, 0U}; + bool carryin = false; + bool carryout; + UIntX2 a0b0 = UIntX2(a.w.v0) * UIntX2(b.w.v0); + r.w.v0 = UInt(a0b0); + r.w.v1 = UInt(a0b0 >> UINT_BITS); + + UIntX2 a1b0 = UIntX2(a.w.v1) * UIntX2(b.w.v0); + r.w.v2 = UInt(a1b0 >> UINT_BITS); + r.w.v1 = addwithcarry(r.w.v1, UInt(a1b0), carryin, &carryout); + carryin = carryout; + r.w.v2 = addwithcarry(r.w.v2, UInt(0U), carryin, &carryout); + carryin = carryout; + r.w.v3 = addwithcarry(r.w.v3, UInt(0U), carryin, &carryout); + + UIntX2 a0b1 = UIntX2(a.w.v0) * UIntX2(b.w.v1); + carryin = false; + r.w.v2 = addwithcarry(r.w.v2, UInt(a0b1 >> UINT_BITS), carryin, &carryout); + carryin = carryout; + r.w.v3 = addwithcarry(r.w.v3, UInt(0U), carryin, &carryout); + + carryin = false; + r.w.v1 = addwithcarry(r.w.v1, UInt(a0b1), carryin, &carryout); + carryin = carryout; + r.w.v2 = addwithcarry(r.w.v2, UInt(0U), carryin, &carryout); + carryin = carryout; + r.w.v3 = addwithcarry(r.w.v3, UInt(0U), carryin, &carryout); + + UIntX2 a1b1 = UIntX2(a.w.v1) * UIntX2(b.w.v1); + carryin = false; + r.w.v2 = addwithcarry(r.w.v2, UInt(a1b1), carryin, &carryout); + carryin = carryout; + r.w.v3 = addwithcarry(r.w.v3, UInt(a1b1 >> UINT_BITS), carryin, &carryout); + + r.d.v23 += a.d.v01 * b.d.v23 + a.d.v23 * b.d.v01; + + return r; +} + + +template +uint_x4 operator*(const uint_x4& a, + UIntX2 b01) +{ + constexpr auto UINT_BITS = uint_x4::UINT_BITS; + uint_x4 r = {0U, 0U, 0U, 0U}; + bool carryin = false; + bool carryout; + UIntX2 a0b0 = UIntX2(a.w.v0) * UIntX2(UInt(b01)); + r.w.v0 = UInt(a0b0); + r.w.v1 = UInt(a0b0 >> UINT_BITS); + + UIntX2 a1b0 = UIntX2(a.w.v1) * UIntX2(UInt(b01)); + r.w.v2 = UInt(a1b0 >> UINT_BITS); + r.w.v1 = addwithcarry(r.w.v1, UInt(a1b0), carryin, &carryout); + carryin = carryout; + r.w.v2 = addwithcarry(r.w.v2, UInt(0U), carryin, &carryout); + carryin = carryout; + r.w.v3 = addwithcarry(r.w.v3, UInt(0U), carryin, &carryout); + + UIntX2 a0b1 = UIntX2(a.w.v0) * UIntX2(b01 >> UINT_BITS); + carryin = false; + r.w.v2 = addwithcarry(r.w.v2, UInt(a0b1 >> UINT_BITS), carryin, &carryout); + carryin = carryout; + r.w.v3 = addwithcarry(r.w.v3, UInt(0U), carryin, &carryout); + + carryin = false; + r.w.v1 = addwithcarry(r.w.v1, UInt(a0b1), carryin, &carryout); + carryin = carryout; + r.w.v2 = addwithcarry(r.w.v2, UInt(0U), carryin, &carryout); + carryin = carryout; + r.w.v3 = addwithcarry(r.w.v3, UInt(0U), carryin, &carryout); + + UIntX2 a1b1 = UIntX2(a.w.v1) * UIntX2(b01 >> UINT_BITS); + carryin = false; + r.w.v2 = addwithcarry(r.w.v2, UInt(a1b1), carryin, &carryout); + carryin = carryout; + r.w.v3 = addwithcarry(r.w.v3, UInt(a1b1 >> UINT_BITS), carryin, &carryout); + + r.d.v23 += a.d.v23 * b01; + + return r; +} + +#if PCG_64BIT_SPECIALIZATIONS +#if defined(_MSC_VER) +#pragma intrinsic(_umul128) +#endif + +#if defined(_MSC_VER) || __SIZEOF_INT128__ +template +uint_x4 operator*(const uint_x4& a, + const uint_x4& b) +{ +#if defined(_MSC_VER) + uint64_t hi; + uint64_t lo = _umul128(a.d.v01, b.d.v01, &hi); +#else + __uint128_t r = __uint128_t(a.d.v01) * __uint128_t(b.d.v01); + uint64_t lo = uint64_t(r); + uint64_t hi = r >> 64; +#endif + hi += a.d.v23 * b.d.v01 + a.d.v01 * b.d.v23; + return {hi, lo}; +} +#endif +#endif + + +template +uint_x4 operator+(const uint_x4& a, + const uint_x4& b) +{ + uint_x4 r = {0U, 0U, 0U, 0U}; + + bool carryin = false; + bool carryout; + r.w.v0 = addwithcarry(a.w.v0, b.w.v0, carryin, &carryout); + carryin = carryout; + r.w.v1 = addwithcarry(a.w.v1, b.w.v1, carryin, &carryout); + carryin = carryout; + r.w.v2 = addwithcarry(a.w.v2, b.w.v2, carryin, &carryout); + carryin = carryout; + r.w.v3 = addwithcarry(a.w.v3, b.w.v3, carryin, &carryout); + + return r; +} + +template +uint_x4 operator-(const uint_x4& a, + const uint_x4& b) +{ + uint_x4 r = {0U, 0U, 0U, 0U}; + + bool carryin = false; + bool carryout; + r.w.v0 = subwithcarry(a.w.v0, b.w.v0, carryin, &carryout); + carryin = carryout; + r.w.v1 = subwithcarry(a.w.v1, b.w.v1, carryin, &carryout); + carryin = carryout; + r.w.v2 = subwithcarry(a.w.v2, b.w.v2, carryin, &carryout); + carryin = carryout; + r.w.v3 = subwithcarry(a.w.v3, b.w.v3, carryin, &carryout); + + return r; +} + +#if PCG_64BIT_SPECIALIZATIONS +template +uint_x4 operator+(const uint_x4& a, + const uint_x4& b) +{ + uint_x4 r = {uint64_t(0u), uint64_t(0u)}; + + bool carryin = false; + bool carryout; + r.d.v01 = addwithcarry(a.d.v01, b.d.v01, carryin, &carryout); + carryin = carryout; + r.d.v23 = addwithcarry(a.d.v23, b.d.v23, carryin, &carryout); + + return r; +} + +template +uint_x4 operator-(const uint_x4& a, + const uint_x4& b) +{ + uint_x4 r = {uint64_t(0u), uint64_t(0u)}; + + bool carryin = false; + bool carryout; + r.d.v01 = subwithcarry(a.d.v01, b.d.v01, carryin, &carryout); + carryin = carryout; + r.d.v23 = subwithcarry(a.d.v23, b.d.v23, carryin, &carryout); + + return r; +} +#endif + +template +uint_x4 operator&(const uint_x4& a, + const uint_x4& b) +{ + return uint_x4(a.d.v23 & b.d.v23, a.d.v01 & b.d.v01); +} + +template +uint_x4 operator|(const uint_x4& a, + const uint_x4& b) +{ + return uint_x4(a.d.v23 | b.d.v23, a.d.v01 | b.d.v01); +} + +template +uint_x4 operator^(const uint_x4& a, + const uint_x4& b) +{ + return uint_x4(a.d.v23 ^ b.d.v23, a.d.v01 ^ b.d.v01); +} + +template +uint_x4 operator~(const uint_x4& v) +{ + return uint_x4(~v.d.v23, ~v.d.v01); +} + +template +uint_x4 operator-(const uint_x4& v) +{ + return uint_x4(0UL,0UL) - v; +} + +template +bool operator==(const uint_x4& a, const uint_x4& b) +{ + return (a.d.v01 == b.d.v01) && (a.d.v23 == b.d.v23); +} + +template +bool operator!=(const uint_x4& a, const uint_x4& b) +{ + return !operator==(a,b); +} + + +template +bool operator<(const uint_x4& a, const uint_x4& b) +{ + return (a.d.v23 < b.d.v23) + || ((a.d.v23 == b.d.v23) && (a.d.v01 < b.d.v01)); +} + +template +bool operator>(const uint_x4& a, const uint_x4& b) +{ + return operator<(b,a); +} + +template +bool operator<=(const uint_x4& a, const uint_x4& b) +{ + return !(operator<(b,a)); +} + +template +bool operator>=(const uint_x4& a, const uint_x4& b) +{ + return !(operator<(a,b)); +} + + + +template +uint_x4 operator<<(const uint_x4& v, + const bitcount_t shift) +{ + uint_x4 r = {0U, 0U, 0U, 0U}; + const bitcount_t bits = uint_x4::UINT_BITS; + const bitcount_t bitmask = bits - 1; + const bitcount_t shiftdiv = shift / bits; + const bitcount_t shiftmod = shift & bitmask; + + if (shiftmod) { + UInt carryover = 0; +#if PCG_LITTLE_ENDIAN + for (uint8_t out = shiftdiv, in = 0; out < 4; ++out, ++in) { +#else + for (uint8_t out = 4-shiftdiv, in = 4; out != 0; /* dec in loop */) { + --out, --in; +#endif + r.wa[out] = (v.wa[in] << shiftmod) | carryover; + carryover = (v.wa[in] >> (bits - shiftmod)); + } + } else { +#if PCG_LITTLE_ENDIAN + for (uint8_t out = shiftdiv, in = 0; out < 4; ++out, ++in) { +#else + for (uint8_t out = 4-shiftdiv, in = 4; out != 0; /* dec in loop */) { + --out, --in; +#endif + r.wa[out] = v.wa[in]; + } + } + + return r; +} + +template +uint_x4 operator>>(const uint_x4& v, + const bitcount_t shift) +{ + uint_x4 r = {0U, 0U, 0U, 0U}; + const bitcount_t bits = uint_x4::UINT_BITS; + const bitcount_t bitmask = bits - 1; + const bitcount_t shiftdiv = shift / bits; + const bitcount_t shiftmod = shift & bitmask; + + if (shiftmod) { + UInt carryover = 0; +#if PCG_LITTLE_ENDIAN + for (uint8_t out = 4-shiftdiv, in = 4; out != 0; /* dec in loop */) { + --out, --in; +#else + for (uint8_t out = shiftdiv, in = 0; out < 4; ++out, ++in) { +#endif + r.wa[out] = (v.wa[in] >> shiftmod) | carryover; + carryover = (v.wa[in] << (bits - shiftmod)); + } + } else { +#if PCG_LITTLE_ENDIAN + for (uint8_t out = 4-shiftdiv, in = 4; out != 0; /* dec in loop */) { + --out, --in; +#else + for (uint8_t out = shiftdiv, in = 0; out < 4; ++out, ++in) { +#endif + r.wa[out] = v.wa[in]; + } + } + + return r; +} + +#if PCG_64BIT_SPECIALIZATIONS +template +uint_x4 operator<<(const uint_x4& v, + const bitcount_t shift) +{ + constexpr bitcount_t bits2 = uint_x4::UINT_BITS * 2; + + if (shift >= bits2) { + return {v.d.v01 << (shift-bits2), uint64_t(0u)}; + } else { + return {shift ? (v.d.v23 << shift) | (v.d.v01 >> (bits2-shift)) + : v.d.v23, + v.d.v01 << shift}; + } +} + +template +uint_x4 operator>>(const uint_x4& v, + const bitcount_t shift) +{ + constexpr bitcount_t bits2 = uint_x4::UINT_BITS * 2; + + if (shift >= bits2) { + return {uint64_t(0u), v.d.v23 >> (shift-bits2)}; + } else { + return {v.d.v23 >> shift, + shift ? (v.d.v01 >> shift) | (v.d.v23 << (bits2-shift)) + : v.d.v01}; + } +} +#endif + +} // namespace pcg_extras + +#endif // PCG_UINT128_HPP_INCLUDED diff --git a/dep/SFMT/CHANGE-LOG.txt b/dep/SFMT/CHANGE-LOG.txt deleted file mode 100644 index 69d67f390d..0000000000 --- a/dep/SFMT/CHANGE-LOG.txt +++ /dev/null @@ -1,69 +0,0 @@ -ver 1.5 -------- -bug fix to_res53 reported by Akio Takahashi. - -ver 1.4.1 -------- -fix MSC compile error reported by Dirk Steenpass. - -ver 1.4 -------- -internal state of SFMT is kept in structure. -function and macro names are changed to have sfmt_ prefix. -ALTIVEC OR BIGENDIAN ARE NOT TESTED AT ALL. - -ver 1.3.3 -------- -change condition compile of do_recursion in SFMT.c - -ver 1.3.2 -------- -bug fix to_res53_mix and genrand_res53_mix. - -ver 1.3.1 -------- -gcc compile option changed from -O9 to -O3. -add functions genrand_res53_mix and to_res53_mix. -bug fix about definition of ALWAYS_INLINE. -add new definition PRE_ALWAYS for MSC. - -ver 1.3 -------- -bug fixed: -DONLY64 without -DBIG_ENIAN64 had been generating -wrong sequence. -bug fixed: There is no documentation about BIG_ENDIAN64. -add automatic endian check by __BIG_ENDIAN__ predefined macro. -bug fixed: change == in check.sh to = -add SFMT-params216091.h -add AltiVec parameter format for systems which are not osx. -change Makefile for systems which are not osx and support AltiVec. -change sample2 of howto-compile for Free BSD. -change source files for BORLANDC and Visual Studio. -change period certification code more smart. -add params directory. - -ver 1.2.1 -------- -Fix typo in SFMT-alti.c SFMT-sse2.c -marge SFMT-alti.c and SFMT-alti.h into SFMT-alti.h -marge SFMT-sse2.c and SFMT-sse2.h into SFMT-sse2.h -This version is not released. - -ver 1.2 -------- -Support many periods: 2^{607}, 2^{1279}, 2^{2281}, 2^{4253}, 2^{11213}, -2^{19937}, 2^{44497}, 2^{86243}, 2^{132049} -Fix typo in LICENSE.txt. -Add cast to vec_perm for SFMT-alti.c, SFMT-alti64.c. -combine source codes. - -ver 1.1 -------- -The period certification method is changed from constant to function. -The convert functions from 32-bit and 64-bit integer to double are added. -The documentation is changed. -Sample programs are added. - -ver 1.0 -------- -The first version. diff --git a/dep/SFMT/CMakeLists.txt b/dep/SFMT/CMakeLists.txt deleted file mode 100644 index 0e66f6598e..0000000000 --- a/dep/SFMT/CMakeLists.txt +++ /dev/null @@ -1,80 +0,0 @@ -# This file is part of the TrinityCore Project. See AUTHORS file for Copyright information -# Copyright 2019 Josua Mayer -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -set(SFMT_SOURCES - SFMT.c - SFMT.h - SFMT-alti.h - SFMT-common.h - SFMT-neon.h - SFMT-params.h - SFMT-params607.h - SFMT-params1279.h - SFMT-params2281.h - SFMT-params4253.h - SFMT-params11213.h - SFMT-params19937.h - SFMT-params44497.h - SFMT-params86243.h - SFMT-params132049.h - SFMT-params216091.h - SFMT-sse2.h - SFMT-sse2-msc.h) - -add_library(sfmt STATIC ${SFMT_SOURCES}) - -target_include_directories(sfmt - INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR}) - -# using the standard Mersenne exponent 19937 -target_compile_definitions(sfmt PUBLIC -DSFMT_MEXP=19937) - -# enable SIMD instructions if available -include(CheckCCompilerFlag) -if (CMAKE_SYSTEM_PROCESSOR MATCHES "(powerpc|ppc)64|(powerpc|ppc)64le") - check_c_compiler_flag("-maltivec" HAVE_ALTIVEC) - if (HAVE_ALTIVEC) - target_compile_options(sfmt PRIVATE -mabi=altivec -maltivec) - target_compile_definitions(sfmt PUBLIC -DHAVE_ALTIVEC) - else () - message(WARNING "Altivec not available - performance will be poor!") - endif () -elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "arm|ARM") - check_c_compiler_flag(-mfpu=neon HAVE_NEON) - if (HAVE_NEON) - target_compile_options(sfmt PRIVATE -mfpu=neon -ftree-vectorize) - target_compile_definitions(sfmt PUBLIC -DHAVE_NEON) - else () - message(WARNING "Neon not available - performance will be poor!") - endif () -elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|AARCH64") - check_c_compiler_flag(-march=armv8-a+simd HAVE_NEON) - if (HAVE_NEON) - target_compile_options(sfmt PRIVATE -ftree-vectorize) - target_compile_definitions(sfmt PUBLIC -DHAVE_NEON) - else () - message(WARNING "Neon not available - performance will be poor!") - endif () -elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "i686|amd64|x86_64|AMD64") - #SSE2 is always available - set(HAVE_SSE2 1) - - if (NOT CMAKE_C_COMPILER_ID MATCHES "MSVC") - target_compile_options(sfmt PRIVATE -msse2) - endif () - target_compile_definitions(sfmt PUBLIC -DHAVE_SSE2) -endif () - -set_target_properties(sfmt PROPERTIES LINKER_LANGUAGE CXX) - -# inherit trinitycore generic build options (e.g. fPIC) -target_link_libraries(sfmt PRIVATE trinity-dependency-interface) diff --git a/dep/SFMT/LICENSE.txt b/dep/SFMT/LICENSE.txt deleted file mode 100644 index 6f9c4a6d6a..0000000000 --- a/dep/SFMT/LICENSE.txt +++ /dev/null @@ -1,32 +0,0 @@ -Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima -University. -Copyright (c) 2012 Mutsuo Saito, Makoto Matsumoto, Hiroshima University -and The University of Tokyo. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the names of Hiroshima University, The University of - Tokyo nor the names of its contributors may be used to endorse - or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/dep/SFMT/README.txt b/dep/SFMT/README.txt deleted file mode 100644 index 271fc40b65..0000000000 --- a/dep/SFMT/README.txt +++ /dev/null @@ -1,27 +0,0 @@ - ================================================================= - SFMT ver. 1.5 - SIMD oriented Fast Mersenne Twister(SFMT) - - Mutsuo Saito (Hiroshima University) and - Makoto Matsumoto (The University of Tokyo) - - Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima - University. - Copyright (c) 2012 Mutsuo Saito, Makoto Matsumoto, Hiroshima University - and The University of Tokyo. - All rights reserved. - - The (modified) BSD License is applied to this software, see LICENSE.txt - ================================================================= - CAUTION: - BIGENDIAN OR ALTIVEC FEATURES ARE NOT TESTED AT ALL. - - To see documents, see html/index.html. - - To make test program, see html/howto-compile.html - - If you want to redistribute and/or change source files, see LICENSE.txt. - - When you change these files and redistribute them, PLEASE write your - e-mail address in redistribution and write to contact YOU first if - users of your changed source encounter troubles. diff --git a/dep/SFMT/SFMT-alti.h b/dep/SFMT/SFMT-alti.h deleted file mode 100644 index 81c98b12b4..0000000000 --- a/dep/SFMT/SFMT-alti.h +++ /dev/null @@ -1,156 +0,0 @@ -#pragma once -/** - * @file SFMT-alti.h - * - * @brief SIMD oriented Fast Mersenne Twister(SFMT) - * pseudorandom number generator - * - * @author Mutsuo Saito (Hiroshima University) - * @author Makoto Matsumoto (Hiroshima University) - * - * Copyright (C) 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima - * University. All rights reserved. - * - * The new BSD License is applied to this software. - * see LICENSE.txt - */ - -#ifndef SFMT_ALTI_H -#define SFMT_ALTI_H - -inline static vector unsigned int vec_recursion(vector unsigned int a, - vector unsigned int b, - vector unsigned int c, - vector unsigned int d); - -/** - * This function represents the recursion formula in AltiVec and BIG ENDIAN. - * @param a a 128-bit part of the interal state array - * @param b a 128-bit part of the interal state array - * @param c a 128-bit part of the interal state array - * @param d a 128-bit part of the interal state array - * @return output - */ -inline static vector unsigned int vec_recursion(vector unsigned int a, - vector unsigned int b, - vector unsigned int c, - vector unsigned int d) { - - const vector unsigned int sl1 = SFMT_ALTI_SL1; - const vector unsigned int sr1 = SFMT_ALTI_SR1; -#ifdef ONLY64 - const vector unsigned int mask = SFMT_ALTI_MSK64; - const vector unsigned char perm_sl = SFMT_ALTI_SL2_PERM64; - const vector unsigned char perm_sr = SFMT_ALTI_SR2_PERM64; -#else - const vector unsigned int mask = SFMT_ALTI_MSK; - const vector unsigned char perm_sl = SFMT_ALTI_SL2_PERM; - const vector unsigned char perm_sr = SFMT_ALTI_SR2_PERM; -#endif - vector unsigned int v, w, x, y, z; - x = vec_perm(a, (vector unsigned int)perm_sl, perm_sl); - v = a; - y = vec_sr(b, sr1); - z = vec_perm(c, (vector unsigned int)perm_sr, perm_sr); - w = vec_sl(d, sl1); - z = vec_xor(z, w); - y = vec_and(y, mask); - v = vec_xor(v, x); - z = vec_xor(z, y); - z = vec_xor(z, v); - return z; -} - -/** - * This function fills the internal state array with pseudorandom - * integers. - */ -void sfmt_gen_rand_all(sfmt_t * sfmt) { - int i; - vector unsigned int r, r1, r2; - - r1 = sfmt->state[N - 2].s; - r2 = sfmt->state[N - 1].s; - for (i = 0; i < N - POS1; i++) { - r = vec_recursion(sfmt->state[i].s, sfmt->state[i + POS1].s, r1, r2); - sfmt->state[i].s = r; - r1 = r2; - r2 = r; - } - for (; i < N; i++) { - r = vec_recursion(sfmt->state[i].s, sfmt->state[i + POS1 - N].s, r1, r2); - sfmt->state[i].s = r; - r1 = r2; - r2 = r; - } -} - -/** - * This function fills the user-specified array with pseudorandom - * integers. - * - * @param array an 128-bit array to be filled by pseudorandom numbers. - * @param size number of 128-bit pesudorandom numbers to be generated. - */ -inline static void gen_rand_array(sfmt_t * sfmt, w128_t *array, int size) { - int i, j; - vector unsigned int r, r1, r2; - - r1 = sfmt->state[N - 2].s; - r2 = sfmt->state[N - 1].s; - for (i = 0; i < N - POS1; i++) { - r = vec_recursion(sfmt->state[i].s, sfmt->state[i + POS1].s, r1, r2); - array[i].s = r; - r1 = r2; - r2 = r; - } - for (; i < N; i++) { - r = vec_recursion(sfmt->state[i].s, array[i + POS1 - N].s, r1, r2); - array[i].s = r; - r1 = r2; - r2 = r; - } - /* main loop */ - for (; i < size - N; i++) { - r = vec_recursion(array[i - N].s, array[i + POS1 - N].s, r1, r2); - array[i].s = r; - r1 = r2; - r2 = r; - } - for (j = 0; j < 2 * N - size; j++) { - sfmt->state[j].s = array[j + size - N].s; - } - for (; i < size; i++) { - r = vec_recursion(array[i - N].s, array[i + POS1 - N].s, r1, r2); - array[i].s = r; - sfmt->state[j++].s = r; - r1 = r2; - r2 = r; - } -} - -#ifndef ONLY64 -#if defined(__APPLE__) -#define SFMT_ALTI_SWAP (vector unsigned char) \ - (4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11) -#else -#define SFMT_ALTI_SWAP {4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11} -#endif -/** - * This function swaps high and low 32-bit of 64-bit integers in user - * specified array. - * - * @param array an 128-bit array to be swaped. - * @param size size of 128-bit array. - */ -inline static void swap(w128_t *array, int size) { - int i; - const vector unsigned char perm = SFMT_ALTI_SWAP; - - for (i = 0; i < size; i++) { - array[i].s = vec_perm(array[i].s, (vector unsigned int)perm, perm); - } -} -#endif - -#endif diff --git a/dep/SFMT/SFMT-common.h b/dep/SFMT/SFMT-common.h deleted file mode 100644 index a5a9b05047..0000000000 --- a/dep/SFMT/SFMT-common.h +++ /dev/null @@ -1,164 +0,0 @@ -#pragma once -/** - * @file SFMT-common.h - * - * @brief SIMD oriented Fast Mersenne Twister(SFMT) pseudorandom - * number generator with jump function. This file includes common functions - * used in random number generation and jump. - * - * @author Mutsuo Saito (Hiroshima University) - * @author Makoto Matsumoto (The University of Tokyo) - * - * Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima - * University. - * Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, Hiroshima - * University and The University of Tokyo. - * All rights reserved. - * - * The 3-clause BSD License is applied to this software, see - * LICENSE.txt - */ -#ifndef SFMT_COMMON_H -#define SFMT_COMMON_H - -#if defined(__cplusplus) -extern "C" { -#endif - -#include "SFMT.h" - -inline static void do_recursion(w128_t * r, w128_t * a, w128_t * b, - w128_t * c, w128_t * d); - -inline static void rshift128(w128_t *out, w128_t const *in, int shift); -inline static void lshift128(w128_t *out, w128_t const *in, int shift); - -/** - * This function simulates SIMD 128-bit right shift by the standard C. - * The 128-bit integer given in in is shifted by (shift * 8) bits. - * This function simulates the LITTLE ENDIAN SIMD. - * @param out the output of this function - * @param in the 128-bit data to be shifted - * @param shift the shift value - */ -#ifdef ONLY64 -inline static void rshift128(w128_t *out, w128_t const *in, int shift) { - uint64_t th, tl, oh, ol; - - th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]); - tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]); - - oh = th >> (shift * 8); - ol = tl >> (shift * 8); - ol |= th << (64 - shift * 8); - out->u[0] = (uint32_t)(ol >> 32); - out->u[1] = (uint32_t)ol; - out->u[2] = (uint32_t)(oh >> 32); - out->u[3] = (uint32_t)oh; -} -#else -inline static void rshift128(w128_t *out, w128_t const *in, int shift) -{ - uint64_t th, tl, oh, ol; - - th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]); - tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]); - - oh = th >> (shift * 8); - ol = tl >> (shift * 8); - ol |= th << (64 - shift * 8); - out->u[1] = (uint32_t)(ol >> 32); - out->u[0] = (uint32_t)ol; - out->u[3] = (uint32_t)(oh >> 32); - out->u[2] = (uint32_t)oh; -} -#endif -/** - * This function simulates SIMD 128-bit left shift by the standard C. - * The 128-bit integer given in in is shifted by (shift * 8) bits. - * This function simulates the LITTLE ENDIAN SIMD. - * @param out the output of this function - * @param in the 128-bit data to be shifted - * @param shift the shift value - */ -#ifdef ONLY64 -inline static void lshift128(w128_t *out, w128_t const *in, int shift) { - uint64_t th, tl, oh, ol; - - th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]); - tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]); - - oh = th << (shift * 8); - ol = tl << (shift * 8); - oh |= tl >> (64 - shift * 8); - out->u[0] = (uint32_t)(ol >> 32); - out->u[1] = (uint32_t)ol; - out->u[2] = (uint32_t)(oh >> 32); - out->u[3] = (uint32_t)oh; -} -#else -inline static void lshift128(w128_t *out, w128_t const *in, int shift) -{ - uint64_t th, tl, oh, ol; - - th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]); - tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]); - - oh = th << (shift * 8); - ol = tl << (shift * 8); - oh |= tl >> (64 - shift * 8); - out->u[1] = (uint32_t)(ol >> 32); - out->u[0] = (uint32_t)ol; - out->u[3] = (uint32_t)(oh >> 32); - out->u[2] = (uint32_t)oh; -} -#endif -/** - * This function represents the recursion formula. - * @param r output - * @param a a 128-bit part of the internal state array - * @param b a 128-bit part of the internal state array - * @param c a 128-bit part of the internal state array - * @param d a 128-bit part of the internal state array - */ -#ifdef ONLY64 -inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c, - w128_t *d) { - w128_t x; - w128_t y; - - lshift128(&x, a, SFMT_SL2); - rshift128(&y, c, SFMT_SR2); - r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SFMT_SR1) & SFMT_MSK2) ^ y.u[0] - ^ (d->u[0] << SFMT_SL1); - r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SFMT_SR1) & SFMT_MSK1) ^ y.u[1] - ^ (d->u[1] << SFMT_SL1); - r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SFMT_SR1) & SFMT_MSK4) ^ y.u[2] - ^ (d->u[2] << SFMT_SL1); - r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SFMT_SR1) & SFMT_MSK3) ^ y.u[3] - ^ (d->u[3] << SFMT_SL1); -} -#else -inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, - w128_t *c, w128_t *d) -{ - w128_t x; - w128_t y; - - lshift128(&x, a, SFMT_SL2); - rshift128(&y, c, SFMT_SR2); - r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SFMT_SR1) & SFMT_MSK1) - ^ y.u[0] ^ (d->u[0] << SFMT_SL1); - r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SFMT_SR1) & SFMT_MSK2) - ^ y.u[1] ^ (d->u[1] << SFMT_SL1); - r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SFMT_SR1) & SFMT_MSK3) - ^ y.u[2] ^ (d->u[2] << SFMT_SL1); - r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SFMT_SR1) & SFMT_MSK4) - ^ y.u[3] ^ (d->u[3] << SFMT_SL1); -} -#endif -#if defined(__cplusplus) -} -#endif - -#endif // SFMT_COMMON_H diff --git a/dep/SFMT/SFMT-neon.h b/dep/SFMT/SFMT-neon.h deleted file mode 100644 index 8790b8b60e..0000000000 --- a/dep/SFMT/SFMT-neon.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @file SFMT-neon.h - * @brief SIMD oriented Fast Mersenne Twister(SFMT) for ARM with 128b NEON - * - * @author Masaki Ota - * - * @note We assume LITTLE ENDIAN in this file - */ - -#ifndef SFMT_NEON_H -#define SFMT_NEON_H - -inline static void neon_recursion(uint32x4_t * r, uint32x4_t a, uint32x4_t b, - uint32x4_t c, uint32x4_t d); - - - -/** - * This function represents the recursion formula. - * @param r an output - * @param a a 128-bit part of the interal state array - * @param b a 128-bit part of the interal state array - * @param c a 128-bit part of the interal state array - * @param d a 128-bit part of the interal state array - */ -inline static void neon_recursion(uint32x4_t * r, uint32x4_t a, uint32x4_t b, - uint32x4_t c, uint32x4_t d) -{ - uint32x4_t v, x, y, z; - static const uint32x4_t vzero = {0,0,0,0}; - static const uint32x4_t vmask = {SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4}; - -#define rotate_bytes(A, B, C) vreinterpretq_u32_u8(vextq_u8(vreinterpretq_u8_u32(A),vreinterpretq_u8_u32(B),(C))) - - y = vshrq_n_u32(b, SFMT_SR1); - z = rotate_bytes(c, vzero, SFMT_SR2); - v = vshlq_n_u32(d, SFMT_SL1); - z = veorq_u32(z, a); - z = veorq_u32(z, v); - x = rotate_bytes(vzero, a, 16-SFMT_SL2); - y = vandq_u32(y, vmask); - z = veorq_u32(z, x); - z = veorq_u32(z, y); - *r = z; -} - -/** - * This function fills the internal state array with pseudorandom - * integers. - * @param sfmt SFMT internal state - */ -void sfmt_gen_rand_all(sfmt_t * sfmt) { - int i; - uint32x4_t r1, r2; - w128_t * pstate = sfmt->state; - - r1 = pstate[SFMT_N - 2].si; - r2 = pstate[SFMT_N - 1].si; - for (i = 0; i < SFMT_N - SFMT_POS1; i++) { - neon_recursion(&pstate[i].si, pstate[i].si, pstate[i + SFMT_POS1].si, r1, r2); - r1 = r2; - r2 = pstate[i].si; - } - for (; i < SFMT_N; i++) { - neon_recursion(&pstate[i].si, pstate[i].si, pstate[i + SFMT_POS1 - SFMT_N].si, r1, r2); - r1 = r2; - r2 = pstate[i].si; - } -} - -/** - * This function fills the user-specified array with pseudorandom - * integers. - * @param sfmt SFMT internal state. - * @param array an 128-bit array to be filled by pseudorandom numbers. - * @param size number of 128-bit pseudorandom numbers to be generated. - */ -static void gen_rand_array(sfmt_t * sfmt, w128_t * array, int size) -{ - int i, j; - uint32x4_t r1, r2; - w128_t * pstate = sfmt->state; - - r1 = pstate[SFMT_N - 2].si; - r2 = pstate[SFMT_N - 1].si; - for (i = 0; i < SFMT_N - SFMT_POS1; i++) { - neon_recursion(&array[i].si, pstate[i].si, pstate[i + SFMT_POS1].si, r1, r2); - r1 = r2; - r2 = array[i].si; - } - for (; i < SFMT_N; i++) { - neon_recursion(&array[i].si, pstate[i].si, array[i + SFMT_POS1 - SFMT_N].si, r1, r2); - r1 = r2; - r2 = array[i].si; - } - for (; i < size - SFMT_N; i++) { - neon_recursion(&array[i].si, array[i - SFMT_N].si, array[i + SFMT_POS1 - SFMT_N].si, r1, r2); - r1 = r2; - r2 = array[i].si; - } - for (j = 0; j < 2 * SFMT_N - size; j++) { - pstate[j] = array[j + size - SFMT_N]; - } - for (; i < size; i++, j++) { - neon_recursion(&array[i].si, array[i - SFMT_N].si, array[i + SFMT_POS1 - SFMT_N].si, r1, r2); - r1 = r2; - r2 = pstate[j].si = array[i].si; - } -} - -#endif diff --git a/dep/SFMT/SFMT-params.h b/dep/SFMT/SFMT-params.h deleted file mode 100644 index 2fe663ab65..0000000000 --- a/dep/SFMT/SFMT-params.h +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once -#ifndef SFMT_PARAMS_H -#define SFMT_PARAMS_H - -#if !defined(SFMT_MEXP) -#if defined(__GNUC__) && !defined(__ICC) - #warning "SFMT_MEXP is not defined. I assume MEXP is 19937." -#endif - #define SFMT_MEXP 19937 -#endif -/*----------------- - BASIC DEFINITIONS - -----------------*/ -/** Mersenne Exponent. The period of the sequence - * is a multiple of 2^MEXP-1. - * #define SFMT_MEXP 19937 */ -/** SFMT generator has an internal state array of 128-bit integers, - * and N is its size. */ -#define SFMT_N (SFMT_MEXP / 128 + 1) -/** N32 is the size of internal state array when regarded as an array - * of 32-bit integers.*/ -#define SFMT_N32 (SFMT_N * 4) -/** N64 is the size of internal state array when regarded as an array - * of 64-bit integers.*/ -#define SFMT_N64 (SFMT_N * 2) - -/*---------------------- - the parameters of SFMT - following definitions are in paramsXXXX.h file. - ----------------------*/ -/** the pick up position of the array. -#define SFMT_POS1 122 -*/ - -/** the parameter of shift left as four 32-bit registers. -#define SFMT_SL1 18 - */ - -/** the parameter of shift left as one 128-bit register. - * The 128-bit integer is shifted by (SFMT_SL2 * 8) bits. -#define SFMT_SL2 1 -*/ - -/** the parameter of shift right as four 32-bit registers. -#define SFMT_SR1 11 -*/ - -/** the parameter of shift right as one 128-bit register. - * The 128-bit integer is shifted by (SFMT_SR2 * 8) bits. -#define SFMT_SR2 1 -*/ - -/** A bitmask, used in the recursion. These parameters are introduced - * to break symmetry of SIMD. -#define SFMT_MSK1 0xdfffffefU -#define SFMT_MSK2 0xddfecb7fU -#define SFMT_MSK3 0xbffaffffU -#define SFMT_MSK4 0xbffffff6U -*/ - -/** These definitions are part of a 128-bit period certification vector. -#define SFMT_PARITY1 0x00000001U -#define SFMT_PARITY2 0x00000000U -#define SFMT_PARITY3 0x00000000U -#define SFMT_PARITY4 0xc98e126aU -*/ - -#if SFMT_MEXP == 607 - #include "SFMT-params607.h" -#elif SFMT_MEXP == 1279 - #include "SFMT-params1279.h" -#elif SFMT_MEXP == 2281 - #include "SFMT-params2281.h" -#elif SFMT_MEXP == 4253 - #include "SFMT-params4253.h" -#elif SFMT_MEXP == 11213 - #include "SFMT-params11213.h" -#elif SFMT_MEXP == 19937 - #include "SFMT-params19937.h" -#elif SFMT_MEXP == 44497 - #include "SFMT-params44497.h" -#elif SFMT_MEXP == 86243 - #include "SFMT-params86243.h" -#elif SFMT_MEXP == 132049 - #include "SFMT-params132049.h" -#elif SFMT_MEXP == 216091 - #include "SFMT-params216091.h" -#else -#if defined(__GNUC__) && !defined(__ICC) - #error "SFMT_MEXP is not valid." - #undef SFMT_MEXP -#else - #undef SFMT_MEXP -#endif - -#endif - -#endif /* SFMT_PARAMS_H */ diff --git a/dep/SFMT/SFMT-params11213.h b/dep/SFMT/SFMT-params11213.h deleted file mode 100644 index 5727747790..0000000000 --- a/dep/SFMT/SFMT-params11213.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#ifndef SFMT_PARAMS11213_H -#define SFMT_PARAMS11213_H - -#define SFMT_POS1 68 -#define SFMT_SL1 14 -#define SFMT_SL2 3 -#define SFMT_SR1 7 -#define SFMT_SR2 3 -#define SFMT_MSK1 0xeffff7fbU -#define SFMT_MSK2 0xffffffefU -#define SFMT_MSK3 0xdfdfbfffU -#define SFMT_MSK4 0x7fffdbfdU -#define SFMT_PARITY1 0x00000001U -#define SFMT_PARITY2 0x00000000U -#define SFMT_PARITY3 0xe8148000U -#define SFMT_PARITY4 0xd0c7afa3U - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define SFMT_ALTI_SL1 \ - (vector unsigned int)(SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1) - #define SFMT_ALTI_SR1 \ - (vector unsigned int)(SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1) - #define SFMT_ALTI_MSK \ - (vector unsigned int)(SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4) - #define SFMT_ALTI_MSK64 \ - (vector unsigned int)(SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3) - #define SFMT_ALTI_SL2_PERM \ - (vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10) - #define SFMT_ALTI_SL2_PERM64 \ - (vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2) - #define SFMT_ALTI_SR2_PERM \ - (vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12) - #define SFMT_ALTI_SR2_PERM64 \ - (vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12) -#else /* For OTHER OSs(Linux?) */ - #define SFMT_ALTI_SL1 {SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1} - #define SFMT_ALTI_SR1 {SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1} - #define SFMT_ALTI_MSK {SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4} - #define SFMT_ALTI_MSK64 {SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3} - #define SFMT_ALTI_SL2_PERM {3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10} - #define SFMT_ALTI_SL2_PERM64 {3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2} - #define SFMT_ALTI_SR2_PERM {5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12} - #define SFMT_ALTI_SR2_PERM64 {13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12} -#endif /* For OSX */ -#define SFMT_IDSTR "SFMT-11213:68-14-3-7-3:effff7fb-ffffffef-dfdfbfff-7fffdbfd" - -#endif /* SFMT_PARAMS11213_H */ diff --git a/dep/SFMT/SFMT-params1279.h b/dep/SFMT/SFMT-params1279.h deleted file mode 100644 index 12dbc13267..0000000000 --- a/dep/SFMT/SFMT-params1279.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#ifndef SFMT_PARAMS1279_H -#define SFMT_PARAMS1279_H - -#define SFMT_POS1 7 -#define SFMT_SL1 14 -#define SFMT_SL2 3 -#define SFMT_SR1 5 -#define SFMT_SR2 1 -#define SFMT_MSK1 0xf7fefffdU -#define SFMT_MSK2 0x7fefcfffU -#define SFMT_MSK3 0xaff3ef3fU -#define SFMT_MSK4 0xb5ffff7fU -#define SFMT_PARITY1 0x00000001U -#define SFMT_PARITY2 0x00000000U -#define SFMT_PARITY3 0x00000000U -#define SFMT_PARITY4 0x20000000U - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define SFMT_ALTI_SL1 \ - (vector unsigned int)(SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1) - #define SFMT_ALTI_SR1 \ - (vector unsigned int)(SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1) - #define SFMT_ALTI_MSK \ - (vector unsigned int)(SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4) - #define SFMT_ALTI_MSK64 \ - (vector unsigned int)(SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3) - #define SFMT_ALTI_SL2_PERM \ - (vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10) - #define SFMT_ALTI_SL2_PERM64 \ - (vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2) - #define SFMT_ALTI_SR2_PERM \ - (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) - #define SFMT_ALTI_SR2_PERM64 \ - (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) -#else /* For OTHER OSs(Linux?) */ - #define SFMT_ALTI_SL1 {SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1} - #define SFMT_ALTI_SR1 {SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1} - #define SFMT_ALTI_MSK {SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4} - #define SFMT_ALTI_MSK64 {SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3} - #define SFMT_ALTI_SL2_PERM {3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10} - #define SFMT_ALTI_SL2_PERM64 {3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2} - #define SFMT_ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} - #define SFMT_ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} -#endif /* For OSX */ -#define SFMT_IDSTR "SFMT-1279:7-14-3-5-1:f7fefffd-7fefcfff-aff3ef3f-b5ffff7f" - -#endif /* SFMT_PARAMS1279_H */ diff --git a/dep/SFMT/SFMT-params132049.h b/dep/SFMT/SFMT-params132049.h deleted file mode 100644 index febc69f2f0..0000000000 --- a/dep/SFMT/SFMT-params132049.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#ifndef SFMT_PARAMS132049_H -#define SFMT_PARAMS132049_H - -#define SFMT_POS1 110 -#define SFMT_SL1 19 -#define SFMT_SL2 1 -#define SFMT_SR1 21 -#define SFMT_SR2 1 -#define SFMT_MSK1 0xffffbb5fU -#define SFMT_MSK2 0xfb6ebf95U -#define SFMT_MSK3 0xfffefffaU -#define SFMT_MSK4 0xcff77fffU -#define SFMT_PARITY1 0x00000001U -#define SFMT_PARITY2 0x00000000U -#define SFMT_PARITY3 0xcb520000U -#define SFMT_PARITY4 0xc7e91c7dU - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define SFMT_ALTI_SL1 \ - (vector unsigned int)(SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1) - #define SFMT_ALTI_SR1 \ - (vector unsigned int)(SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1) - #define SFMT_ALTI_MSK \ - (vector unsigned int)(SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4) - #define SFMT_ALTI_MSK64 \ - (vector unsigned int)(SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3) - #define SFMT_ALTI_SL2_PERM \ - (vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8) - #define SFMT_ALTI_SL2_PERM64 \ - (vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0) - #define SFMT_ALTI_SR2_PERM \ - (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) - #define SFMT_ALTI_SR2_PERM64 \ - (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) -#else /* For OTHER OSs(Linux?) */ - #define SFMT_ALTI_SL1 {SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1} - #define SFMT_ALTI_SR1 {SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1} - #define SFMT_ALTI_MSK {SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4} - #define SFMT_ALTI_MSK64 {SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3} - #define SFMT_ALTI_SL2_PERM {1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8} - #define SFMT_ALTI_SL2_PERM64 {1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0} - #define SFMT_ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} - #define SFMT_ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} -#endif /* For OSX */ -#define SFMT_IDSTR "SFMT-132049:110-19-1-21-1:ffffbb5f-fb6ebf95-fffefffa-cff77fff" - -#endif /* SFMT_PARAMS132049_H */ diff --git a/dep/SFMT/SFMT-params19937.h b/dep/SFMT/SFMT-params19937.h deleted file mode 100644 index fc49fa14e5..0000000000 --- a/dep/SFMT/SFMT-params19937.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#ifndef SFMT_PARAMS19937_H -#define SFMT_PARAMS19937_H - -#define SFMT_POS1 122 -#define SFMT_SL1 18 -#define SFMT_SL2 1 -#define SFMT_SR1 11 -#define SFMT_SR2 1 -#define SFMT_MSK1 0xdfffffefU -#define SFMT_MSK2 0xddfecb7fU -#define SFMT_MSK3 0xbffaffffU -#define SFMT_MSK4 0xbffffff6U -#define SFMT_PARITY1 0x00000001U -#define SFMT_PARITY2 0x00000000U -#define SFMT_PARITY3 0x00000000U -#define SFMT_PARITY4 0x13c9e684U - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define SFMT_ALTI_SL1 \ - (vector unsigned int)(SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1) - #define SFMT_ALTI_SR1 \ - (vector unsigned int)(SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1) - #define SFMT_ALTI_MSK \ - (vector unsigned int)(SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4) - #define SFMT_ALTI_MSK64 \ - (vector unsigned int)(SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3) - #define SFMT_ALTI_SL2_PERM \ - (vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8) - #define SFMT_ALTI_SL2_PERM64 \ - (vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0) - #define SFMT_ALTI_SR2_PERM \ - (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) - #define SFMT_ALTI_SR2_PERM64 \ - (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) -#else /* For OTHER OSs(Linux?) */ - #define SFMT_ALTI_SL1 {SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1} - #define SFMT_ALTI_SR1 {SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1} - #define SFMT_ALTI_MSK {SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4} - #define SFMT_ALTI_MSK64 {SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3} - #define SFMT_ALTI_SL2_PERM {1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8} - #define SFMT_ALTI_SL2_PERM64 {1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0} - #define SFMT_ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} - #define SFMT_ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} -#endif /* For OSX */ -#define SFMT_IDSTR "SFMT-19937:122-18-1-11-1:dfffffef-ddfecb7f-bffaffff-bffffff6" - -#endif /* SFMT_PARAMS19937_H */ diff --git a/dep/SFMT/SFMT-params216091.h b/dep/SFMT/SFMT-params216091.h deleted file mode 100644 index 60d58574b8..0000000000 --- a/dep/SFMT/SFMT-params216091.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#ifndef SFMT_PARAMS216091_H -#define SFMT_PARAMS216091_H - -#define SFMT_POS1 627 -#define SFMT_SL1 11 -#define SFMT_SL2 3 -#define SFMT_SR1 10 -#define SFMT_SR2 1 -#define SFMT_MSK1 0xbff7bff7U -#define SFMT_MSK2 0xbfffffffU -#define SFMT_MSK3 0xbffffa7fU -#define SFMT_MSK4 0xffddfbfbU -#define SFMT_PARITY1 0xf8000001U -#define SFMT_PARITY2 0x89e80709U -#define SFMT_PARITY3 0x3bd2b64bU -#define SFMT_PARITY4 0x0c64b1e4U - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define SFMT_ALTI_SL1 \ - (vector unsigned int)(SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1) - #define SFMT_ALTI_SR1 \ - (vector unsigned int)(SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1) - #define SFMT_ALTI_MSK \ - (vector unsigned int)(SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4) - #define SFMT_ALTI_MSK64 \ - (vector unsigned int)(SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3) - #define SFMT_ALTI_SL2_PERM \ - (vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10) - #define SFMT_ALTI_SL2_PERM64 \ - (vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2) - #define SFMT_ALTI_SR2_PERM \ - (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) - #define SFMT_ALTI_SR2_PERM64 \ - (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) -#else /* For OTHER OSs(Linux?) */ - #define SFMT_ALTI_SL1 {SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1} - #define SFMT_ALTI_SR1 {SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1} - #define SFMT_ALTI_MSK {SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4} - #define SFMT_ALTI_MSK64 {SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3} - #define SFMT_ALTI_SL2_PERM {3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10} - #define SFMT_ALTI_SL2_PERM64 {3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2} - #define SFMT_ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} - #define SFMT_ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} -#endif /* For OSX */ -#define SFMT_IDSTR "SFMT-216091:627-11-3-10-1:bff7bff7-bfffffff-bffffa7f-ffddfbfb" - -#endif /* SFMT_PARAMS216091_H */ diff --git a/dep/SFMT/SFMT-params2281.h b/dep/SFMT/SFMT-params2281.h deleted file mode 100644 index 05729515ce..0000000000 --- a/dep/SFMT/SFMT-params2281.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#ifndef SFMT_PARAMS2281_H -#define SFMT_PARAMS2281_H - -#define SFMT_POS1 12 -#define SFMT_SL1 19 -#define SFMT_SL2 1 -#define SFMT_SR1 5 -#define SFMT_SR2 1 -#define SFMT_MSK1 0xbff7ffbfU -#define SFMT_MSK2 0xfdfffffeU -#define SFMT_MSK3 0xf7ffef7fU -#define SFMT_MSK4 0xf2f7cbbfU -#define SFMT_PARITY1 0x00000001U -#define SFMT_PARITY2 0x00000000U -#define SFMT_PARITY3 0x00000000U -#define SFMT_PARITY4 0x41dfa600U - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define SFMT_ALTI_SL1 \ - (vector unsigned int)(SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1) - #define SFMT_ALTI_SR1 \ - (vector unsigned int)(SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1) - #define SFMT_ALTI_MSK \ - (vector unsigned int)(SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4) - #define SFMT_ALTI_MSK64 \ - (vector unsigned int)(SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3) - #define SFMT_ALTI_SL2_PERM \ - (vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8) - #define SFMT_ALTI_SL2_PERM64 \ - (vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0) - #define SFMT_ALTI_SR2_PERM \ - (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) - #define SFMT_ALTI_SR2_PERM64 \ - (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) -#else /* For OTHER OSs(Linux?) */ - #define SFMT_ALTI_SL1 {SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1} - #define SFMT_ALTI_SR1 {SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1} - #define SFMT_ALTI_MSK {SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4} - #define SFMT_ALTI_MSK64 {SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3} - #define SFMT_ALTI_SL2_PERM {1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8} - #define SFMT_ALTI_SL2_PERM64 {1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0} - #define SFMT_ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} - #define SFMT_ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} -#endif /* For OSX */ -#define SFMT_IDSTR "SFMT-2281:12-19-1-5-1:bff7ffbf-fdfffffe-f7ffef7f-f2f7cbbf" - -#endif /* SFMT_PARAMS2281_H */ diff --git a/dep/SFMT/SFMT-params4253.h b/dep/SFMT/SFMT-params4253.h deleted file mode 100644 index 2e7bfad1fe..0000000000 --- a/dep/SFMT/SFMT-params4253.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#ifndef SFMT_PARAMS4253_H -#define SFMT_PARAMS4253_H - -#define SFMT_POS1 17 -#define SFMT_SL1 20 -#define SFMT_SL2 1 -#define SFMT_SR1 7 -#define SFMT_SR2 1 -#define SFMT_MSK1 0x9f7bffffU -#define SFMT_MSK2 0x9fffff5fU -#define SFMT_MSK3 0x3efffffbU -#define SFMT_MSK4 0xfffff7bbU -#define SFMT_PARITY1 0xa8000001U -#define SFMT_PARITY2 0xaf5390a3U -#define SFMT_PARITY3 0xb740b3f8U -#define SFMT_PARITY4 0x6c11486dU - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define SFMT_ALTI_SL1 \ - (vector unsigned int)(SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1) - #define SFMT_ALTI_SR1 \ - (vector unsigned int)(SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1) - #define SFMT_ALTI_MSK \ - (vector unsigned int)(SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4) - #define SFMT_ALTI_MSK64 \ - (vector unsigned int)(SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3) - #define SFMT_ALTI_SL2_PERM \ - (vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8) - #define SFMT_ALTI_SL2_PERM64 \ - (vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0) - #define SFMT_ALTI_SR2_PERM \ - (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) - #define SFMT_ALTI_SR2_PERM64 \ - (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) -#else /* For OTHER OSs(Linux?) */ - #define SFMT_ALTI_SL1 {SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1} - #define SFMT_ALTI_SR1 {SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1} - #define SFMT_ALTI_MSK {SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4} - #define SFMT_ALTI_MSK64 {SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3} - #define SFMT_ALTI_SL2_PERM {1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8} - #define SFMT_ALTI_SL2_PERM64 {1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0} - #define SFMT_ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} - #define SFMT_ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} -#endif /* For OSX */ -#define SFMT_IDSTR "SFMT-4253:17-20-1-7-1:9f7bffff-9fffff5f-3efffffb-fffff7bb" - -#endif /* SFMT_PARAMS4253_H */ diff --git a/dep/SFMT/SFMT-params44497.h b/dep/SFMT/SFMT-params44497.h deleted file mode 100644 index f9829db0bb..0000000000 --- a/dep/SFMT/SFMT-params44497.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#ifndef SFMT_PARAMS44497_H -#define SFMT_PARAMS44497_H - -#define SFMT_POS1 330 -#define SFMT_SL1 5 -#define SFMT_SL2 3 -#define SFMT_SR1 9 -#define SFMT_SR2 3 -#define SFMT_MSK1 0xeffffffbU -#define SFMT_MSK2 0xdfbebfffU -#define SFMT_MSK3 0xbfbf7befU -#define SFMT_MSK4 0x9ffd7bffU -#define SFMT_PARITY1 0x00000001U -#define SFMT_PARITY2 0x00000000U -#define SFMT_PARITY3 0xa3ac4000U -#define SFMT_PARITY4 0xecc1327aU - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define SFMT_ALTI_SL1 \ - (vector unsigned int)(SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1) - #define SFMT_ALTI_SR1 \ - (vector unsigned int)(SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1) - #define SFMT_ALTI_MSK \ - (vector unsigned int)(SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4) - #define SFMT_ALTI_MSK64 \ - (vector unsigned int)(SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3) - #define SFMT_ALTI_SL2_PERM \ - (vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10) - #define SFMT_ALTI_SL2_PERM64 \ - (vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2) - #define SFMT_ALTI_SR2_PERM \ - (vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12) - #define SFMT_ALTI_SR2_PERM64 \ - (vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12) -#else /* For OTHER OSs(Linux?) */ - #define SFMT_ALTI_SL1 {SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1} - #define SFMT_ALTI_SR1 {SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1} - #define SFMT_ALTI_MSK {SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4} - #define SFMT_ALTI_MSK64 {SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3} - #define SFMT_ALTI_SL2_PERM {3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10} - #define SFMT_ALTI_SL2_PERM64 {3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2} - #define SFMT_ALTI_SR2_PERM {5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12} - #define SFMT_ALTI_SR2_PERM64 {13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12} -#endif /* For OSX */ -#define SFMT_IDSTR "SFMT-44497:330-5-3-9-3:effffffb-dfbebfff-bfbf7bef-9ffd7bff" - -#endif /* SFMT_PARAMS44497_H */ diff --git a/dep/SFMT/SFMT-params607.h b/dep/SFMT/SFMT-params607.h deleted file mode 100644 index 085367254a..0000000000 --- a/dep/SFMT/SFMT-params607.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#ifndef SFMT_PARAMS607_H -#define SFMT_PARAMS607_H - -#define SFMT_POS1 2 -#define SFMT_SL1 15 -#define SFMT_SL2 3 -#define SFMT_SR1 13 -#define SFMT_SR2 3 -#define SFMT_MSK1 0xfdff37ffU -#define SFMT_MSK2 0xef7f3f7dU -#define SFMT_MSK3 0xff777b7dU -#define SFMT_MSK4 0x7ff7fb2fU -#define SFMT_PARITY1 0x00000001U -#define SFMT_PARITY2 0x00000000U -#define SFMT_PARITY3 0x00000000U -#define SFMT_PARITY4 0x5986f054U - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define SFMT_ALTI_SL1 \ - (vector unsigned int)(SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1) - #define SFMT_ALTI_SR1 \ - (vector unsigned int)(SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1) - #define SFMT_ALTI_MSK \ - (vector unsigned int)(SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4) - #define SFMT_ALTI_MSK64 \ - (vector unsigned int)(SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3) - #define SFMT_ALTI_SL2_PERM \ - (vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10) - #define SFMT_ALTI_SL2_PERM64 \ - (vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2) - #define SFMT_ALTI_SR2_PERM \ - (vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12) - #define SFMT_ALTI_SR2_PERM64 \ - (vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12) -#else /* For OTHER OSs(Linux?) */ - #define SFMT_ALTI_SL1 {SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1} - #define SFMT_ALTI_SR1 {SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1} - #define SFMT_ALTI_MSK {SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4} - #define SFMT_ALTI_MSK64 {SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3} - #define SFMT_ALTI_SL2_PERM {3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10} - #define SFMT_ALTI_SL2_PERM64 {3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2} - #define SFMT_ALTI_SR2_PERM {5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12} - #define SFMT_ALTI_SR2_PERM64 {13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12} -#endif /* For OSX */ -#define SFMT_IDSTR "SFMT-607:2-15-3-13-3:fdff37ff-ef7f3f7d-ff777b7d-7ff7fb2f" - -#endif /* SFMT_PARAMS607_H */ diff --git a/dep/SFMT/SFMT-params86243.h b/dep/SFMT/SFMT-params86243.h deleted file mode 100644 index 89773b156a..0000000000 --- a/dep/SFMT/SFMT-params86243.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#ifndef SFMT_PARAMS86243_H -#define SFMT_PARAMS86243_H - -#define SFMT_POS1 366 -#define SFMT_SL1 6 -#define SFMT_SL2 7 -#define SFMT_SR1 19 -#define SFMT_SR2 1 -#define SFMT_MSK1 0xfdbffbffU -#define SFMT_MSK2 0xbff7ff3fU -#define SFMT_MSK3 0xfd77efffU -#define SFMT_MSK4 0xbf9ff3ffU -#define SFMT_PARITY1 0x00000001U -#define SFMT_PARITY2 0x00000000U -#define SFMT_PARITY3 0x00000000U -#define SFMT_PARITY4 0xe9528d85U - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define SFMT_ALTI_SL1 \ - (vector unsigned int)(SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1) - #define SFMT_ALTI_SR1 \ - (vector unsigned int)(SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1) - #define SFMT_ALTI_MSK \ - (vector unsigned int)(SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4) - #define SFMT_ALTI_MSK64 \ - (vector unsigned int)(SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3) - #define SFMT_ALTI_SL2_PERM \ - (vector unsigned char)(25,25,25,25,3,25,25,25,7,0,1,2,11,4,5,6) - #define SFMT_ALTI_SL2_PERM64 \ - (vector unsigned char)(7,25,25,25,25,25,25,25,15,0,1,2,3,4,5,6) - #define SFMT_ALTI_SR2_PERM \ - (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) - #define SFMT_ALTI_SR2_PERM64 \ - (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) -#else /* For OTHER OSs(Linux?) */ - #define SFMT_ALTI_SL1 {SFMT_SL1, SFMT_SL1, SFMT_SL1, SFMT_SL1} - #define SFMT_ALTI_SR1 {SFMT_SR1, SFMT_SR1, SFMT_SR1, SFMT_SR1} - #define SFMT_ALTI_MSK {SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4} - #define SFMT_ALTI_MSK64 {SFMT_MSK2, SFMT_MSK1, SFMT_MSK4, SFMT_MSK3} - #define SFMT_ALTI_SL2_PERM {25,25,25,25,3,25,25,25,7,0,1,2,11,4,5,6} - #define SFMT_ALTI_SL2_PERM64 {7,25,25,25,25,25,25,25,15,0,1,2,3,4,5,6} - #define SFMT_ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} - #define SFMT_ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} -#endif /* For OSX */ -#define SFMT_IDSTR "SFMT-86243:366-6-7-19-1:fdbffbff-bff7ff3f-fd77efff-bf9ff3ff" - -#endif /* SFMT_PARAMS86243_H */ diff --git a/dep/SFMT/SFMT-sse2-msc.h b/dep/SFMT/SFMT-sse2-msc.h deleted file mode 100644 index 9839df1a21..0000000000 --- a/dep/SFMT/SFMT-sse2-msc.h +++ /dev/null @@ -1,321 +0,0 @@ -#pragma once -/** - * @file SFMT-sse2-msc.h - * @brief SIMD oriented Fast Mersenne Twister(SFMT) for Intel SSE2 for MSC - * - * @author Mutsuo Saito (Hiroshima University) - * @author Makoto Matsumoto (Hiroshima University) - * - * @note We assume LITTLE ENDIAN in this file - * - * Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima - * University. All rights reserved. - * Copyright (C) 2013 Mutsuo Saito, Makoto Matsumoto and Hiroshima - * University. - * - * The new BSD License is applied to this software, see LICENSE.txt - */ - -#ifndef SFMT_SSE2_MSC_H -#define SFMT_SSE2_MSC_H - -/* This header file is included only when _MSC_VER is defined. */ -#if _MSC_VER > 1700 - -inline static __m128i __vectorcall mm_recursion(__m128i a, __m128i b, - __m128i c, __m128i d); - -/** - * This function represents the recursion formula. - * @param a a 128-bit part of the interal state array - * @param b a 128-bit part of the interal state array - * @param c a 128-bit part of the interal state array - * @param d a 128-bit part of the interal state array - * @return new value - */ -inline static __m128i __vectorcall mm_recursion(__m128i a, __m128i b, - __m128i c, __m128i d) -{ - __m128i v, x, y, z; - - y = _mm_srli_epi32(b, SFMT_SR1); - z = _mm_srli_si128(c, SFMT_SR2); - v = _mm_slli_epi32(d, SFMT_SL1); - z = _mm_xor_si128(z, a); - z = _mm_xor_si128(z, v); - x = _mm_slli_si128(a, SFMT_SL2); - y = _mm_and_si128(y, sse2_param_mask.si); - z = _mm_xor_si128(z, x); - return _mm_xor_si128(z, y); -} - -/** - * This function fills the internal state array with pseudorandom - * integers. - * @param sfmt SFMT internal state - */ -void sfmt_gen_rand_all(sfmt_t * sfmt) { - int i; - __m128i r1, r2; - w128_t * pstate = sfmt->state; - - r1 = pstate[SFMT_N - 2].si; - r2 = pstate[SFMT_N - 1].si; - for (i = 0; i < SFMT_N - SFMT_POS1; i++) { - pstate[i].si = mm_recursion(pstate[i].si, - pstate[i + SFMT_POS1].si, r1, r2); - r1 = r2; - r2 = pstate[i].si; - } - for (; i < SFMT_N; i++) { - pstate[i].si = mm_recursion(pstate[i].si, - pstate[i + SFMT_POS1 - SFMT_N].si, - r1, r2); - r1 = r2; - r2 = pstate[i].si; - } -} - -/** - * This function fills the user-specified array with pseudorandom - * integers. - * @param sfmt SFMT internal state. - * @param array an 128-bit array to be filled by pseudorandom numbers. - * @param size number of 128-bit pseudorandom numbers to be generated. - */ -static void gen_rand_array(sfmt_t * sfmt, w128_t * array, int size) -{ - int i, j; - __m128i r1, r2; - w128_t * pstate = sfmt->state; - - r1 = pstate[SFMT_N - 2].si; - r2 = pstate[SFMT_N - 1].si; - for (i = 0; i < SFMT_N - SFMT_POS1; i++) { - array[i].si = mm_recursion(pstate[i].si, - pstate[i + SFMT_POS1].si, r1, r2); - r1 = r2; - r2 = array[i].si; - } - for (; i < SFMT_N; i++) { - array[i].si = mm_recursion(pstate[i].si, - array[i + SFMT_POS1 - SFMT_N].si, r1, r2); - r1 = r2; - r2 = array[i].si; - } - for (; i < size - SFMT_N; i++) { - array[i].si = mm_recursion(array[i - SFMT_N].si, - array[i + SFMT_POS1 - SFMT_N].si, r1, r2); - r1 = r2; - r2 = array[i].si; - } - for (j = 0; j < 2 * SFMT_N - size; j++) { - pstate[j] = array[j + size - SFMT_N]; - } - for (; i < size; i++, j++) { - array[i].si = mm_recursion(array[i - SFMT_N].si, - array[i + SFMT_POS1 - SFMT_N].si, r1, r2); - r1 = r2; - r2 = array[i].si; - pstate[j] = array[i]; - } -} - -#elif defined(SFMT_USE_MACRO_FUNCTION_FOR_MSC) -/** - * This function represents the recursion formula. - * @param r an output - * @param a a 128-bit part of the interal state array - * @param b a 128-bit part of the interal state array - * @param c a 128-bit part of the interal state array - * @param d a 128-bit part of the interal state array - */ -#define mm_recursion(r, a, b, c, d) \ -do { \ - __m128i v, x, y, z; \ - \ - y = _mm_srli_epi32((b), SFMT_SR1); \ - z = _mm_srli_si128((c), SFMT_SR2); \ - v = _mm_slli_epi32((d), SFMT_SL1); \ - z = _mm_xor_si128(z, (a)); \ - z = _mm_xor_si128(z, v); \ - x = _mm_slli_si128((a), SFMT_SL2); \ - y = _mm_and_si128(y, sse2_param_mask.si); \ - z = _mm_xor_si128(z, x); \ - r = _mm_xor_si128(z, y); \ -} while (0) - -/** - * This function fills the internal state array with pseudorandom - * integers. - * @param sfmt SFMT internal state - */ -void sfmt_gen_rand_all(sfmt_t * sfmt) { - int i; - __m128i r1, r2; - w128_t * pstate = sfmt->state; - - r1 = pstate[SFMT_N - 2].si; - r2 = pstate[SFMT_N - 1].si; - for (i = 0; i < SFMT_N - SFMT_POS1; i++) { - mm_recursion(pstate[i].si, pstate[i].si, - pstate[i + SFMT_POS1].si, r1, r2); - r1 = r2; - r2 = pstate[i].si; - } - for (; i < SFMT_N; i++) { - mm_recursion(pstate[i].si, pstate[i].si, - pstate[i + SFMT_POS1 - SFMT_N].si, - r1, r2); - r1 = r2; - r2 = pstate[i].si; - } -} - -/** - * This function fills the user-specified array with pseudorandom - * integers. - * @param sfmt SFMT internal state. - * @param array an 128-bit array to be filled by pseudorandom numbers. - * @param size number of 128-bit pseudorandom numbers to be generated. - */ -static void gen_rand_array(sfmt_t * sfmt, w128_t * array, int size) -{ - int i, j; - __m128i r1, r2; - w128_t * pstate = sfmt->state; - - r1 = pstate[SFMT_N - 2].si; - r2 = pstate[SFMT_N - 1].si; - for (i = 0; i < SFMT_N - SFMT_POS1; i++) { - mm_recursion(array[i].si, pstate[i].si, - pstate[i + SFMT_POS1].si, r1, r2); - r1 = r2; - r2 = array[i].si; - } - for (; i < SFMT_N; i++) { - mm_recursion(array[i].si, pstate[i].si, - array[i + SFMT_POS1 - SFMT_N].si, r1, r2); - r1 = r2; - r2 = array[i].si; - } - for (; i < size - SFMT_N; i++) { - mm_recursion(array[i].si, array[i - SFMT_N].si, - array[i + SFMT_POS1 - SFMT_N].si, r1, r2); - r1 = r2; - r2 = array[i].si; - } - for (j = 0; j < 2 * SFMT_N - size; j++) { - pstate[j] = array[j + size - SFMT_N]; - } - for (; i < size; i++, j++) { - mm_recursion(array[i].si, array[i - SFMT_N].si, - array[i + SFMT_POS1 - SFMT_N].si, r1, r2); - r1 = r2; - r2 = array[i].si; - pstate[j] = array[i]; - } -} -#else -inline static void mm_recursion(__m128i * r, __m128i a, __m128i b, - __m128i c, __m128i * d); - -/** - * This function represents the recursion formula. - * @param r an output - * @param a a 128-bit part of the interal state array - * @param b a 128-bit part of the interal state array - * @param c a 128-bit part of the interal state array - * @param d a 128-bit part of the interal state array - */ -inline static void mm_recursion(__m128i * r, __m128i a, __m128i b, - __m128i c, __m128i * d) -{ - __m128i v, x, y, z; - - y = _mm_srli_epi32(b, SFMT_SR1); - z = _mm_srli_si128(c, SFMT_SR2); - v = _mm_slli_epi32(*d, SFMT_SL1); - z = _mm_xor_si128(z, a); - z = _mm_xor_si128(z, v); - x = _mm_slli_si128(a, SFMT_SL2); - y = _mm_and_si128(y, sse2_param_mask.si); - z = _mm_xor_si128(z, x); - z = _mm_xor_si128(z, y); - *r = z; -} - -/** - * This function fills the internal state array with pseudorandom - * integers. - * @param sfmt SFMT internal state - */ -void sfmt_gen_rand_all(sfmt_t * sfmt) { - int i; - __m128i r1, r2; - w128_t * pstate = sfmt->state; - - r1 = pstate[SFMT_N - 2].si; - r2 = pstate[SFMT_N - 1].si; - for (i = 0; i < SFMT_N - SFMT_POS1; i++) { - mm_recursion(&pstate[i].si, pstate[i].si, - pstate[i + SFMT_POS1].si, r1, &r2); - r1 = r2; - r2 = pstate[i].si; - } - for (; i < SFMT_N; i++) { - mm_recursion(&pstate[i].si, pstate[i].si, - pstate[i + SFMT_POS1 - SFMT_N].si, - r1, &r2); - r1 = r2; - r2 = pstate[i].si; - } -} - -/** - * This function fills the user-specified array with pseudorandom - * integers. - * @param sfmt SFMT internal state. - * @param array an 128-bit array to be filled by pseudorandom numbers. - * @param size number of 128-bit pseudorandom numbers to be generated. - */ -static void gen_rand_array(sfmt_t * sfmt, w128_t * array, int size) -{ - int i, j; - __m128i r1, r2; - w128_t * pstate = sfmt->state; - - r1 = pstate[SFMT_N - 2].si; - r2 = pstate[SFMT_N - 1].si; - for (i = 0; i < SFMT_N - SFMT_POS1; i++) { - mm_recursion(&array[i].si, pstate[i].si, - pstate[i + SFMT_POS1].si, r1, &r2); - r1 = r2; - r2 = array[i].si; - } - for (; i < SFMT_N; i++) { - mm_recursion(&array[i].si, pstate[i].si, - array[i + SFMT_POS1 - SFMT_N].si, r1, &r2); - r1 = r2; - r2 = array[i].si; - } - for (; i < size - SFMT_N; i++) { - mm_recursion(&array[i].si, array[i - SFMT_N].si, - array[i + SFMT_POS1 - SFMT_N].si, r1, &r2); - r1 = r2; - r2 = array[i].si; - } - for (j = 0; j < 2 * SFMT_N - size; j++) { - pstate[j] = array[j + size - SFMT_N]; - } - for (; i < size; i++, j++) { - mm_recursion(&array[i].si, array[i - SFMT_N].si, - array[i + SFMT_POS1 - SFMT_N].si, r1, &r2); - r1 = r2; - r2 = array[i].si; - pstate[j] = array[i]; - } -} -#endif - -#endif diff --git a/dep/SFMT/SFMT-sse2.h b/dep/SFMT/SFMT-sse2.h deleted file mode 100644 index 99a33ff1f8..0000000000 --- a/dep/SFMT/SFMT-sse2.h +++ /dev/null @@ -1,121 +0,0 @@ -#pragma once -/** - * @file SFMT-sse2.h - * @brief SIMD oriented Fast Mersenne Twister(SFMT) for Intel SSE2 - * - * @author Mutsuo Saito (Hiroshima University) - * @author Makoto Matsumoto (Hiroshima University) - * - * @note We assume LITTLE ENDIAN in this file - * - * Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima - * University. All rights reserved. - * - * The new BSD License is applied to this software, see LICENSE.txt - */ - -#ifndef SFMT_SSE2_H -#define SFMT_SSE2_H - -inline static void mm_recursion(__m128i * r, __m128i a, __m128i b, - __m128i c, __m128i d); - -/** - * This function represents the recursion formula. - * @param r an output - * @param a a 128-bit part of the interal state array - * @param b a 128-bit part of the interal state array - * @param c a 128-bit part of the interal state array - * @param d a 128-bit part of the interal state array - */ -inline static void mm_recursion(__m128i * r, __m128i a, __m128i b, - __m128i c, __m128i d) -{ - __m128i v, x, y, z; - - y = _mm_srli_epi32(b, SFMT_SR1); - z = _mm_srli_si128(c, SFMT_SR2); - v = _mm_slli_epi32(d, SFMT_SL1); - z = _mm_xor_si128(z, a); - z = _mm_xor_si128(z, v); - x = _mm_slli_si128(a, SFMT_SL2); - y = _mm_and_si128(y, sse2_param_mask.si); - z = _mm_xor_si128(z, x); - z = _mm_xor_si128(z, y); - *r = z; -} - -/** - * This function fills the internal state array with pseudorandom - * integers. - * @param sfmt SFMT internal state - */ -void sfmt_gen_rand_all(sfmt_t * sfmt) { - int i; - __m128i r1, r2; - w128_t * pstate = sfmt->state; - - r1 = pstate[SFMT_N - 2].si; - r2 = pstate[SFMT_N - 1].si; - for (i = 0; i < SFMT_N - SFMT_POS1; i++) { - mm_recursion(&pstate[i].si, pstate[i].si, - pstate[i + SFMT_POS1].si, r1, r2); - r1 = r2; - r2 = pstate[i].si; - } - for (; i < SFMT_N; i++) { - mm_recursion(&pstate[i].si, pstate[i].si, - pstate[i + SFMT_POS1 - SFMT_N].si, - r1, r2); - r1 = r2; - r2 = pstate[i].si; - } -} - -/** - * This function fills the user-specified array with pseudorandom - * integers. - * @param sfmt SFMT internal state. - * @param array an 128-bit array to be filled by pseudorandom numbers. - * @param size number of 128-bit pseudorandom numbers to be generated. - */ -static void gen_rand_array(sfmt_t * sfmt, w128_t * array, int size) -{ - int i, j; - __m128i r1, r2; - w128_t * pstate = sfmt->state; - - r1 = pstate[SFMT_N - 2].si; - r2 = pstate[SFMT_N - 1].si; - for (i = 0; i < SFMT_N - SFMT_POS1; i++) { - mm_recursion(&array[i].si, pstate[i].si, - pstate[i + SFMT_POS1].si, r1, r2); - r1 = r2; - r2 = array[i].si; - } - for (; i < SFMT_N; i++) { - mm_recursion(&array[i].si, pstate[i].si, - array[i + SFMT_POS1 - SFMT_N].si, r1, r2); - r1 = r2; - r2 = array[i].si; - } - for (; i < size - SFMT_N; i++) { - mm_recursion(&array[i].si, array[i - SFMT_N].si, - array[i + SFMT_POS1 - SFMT_N].si, r1, r2); - r1 = r2; - r2 = array[i].si; - } - for (j = 0; j < 2 * SFMT_N - size; j++) { - pstate[j] = array[j + size - SFMT_N]; - } - for (; i < size; i++, j++) { - mm_recursion(&array[i].si, array[i - SFMT_N].si, - array[i + SFMT_POS1 - SFMT_N].si, r1, r2); - r1 = r2; - r2 = array[i].si; - pstate[j] = array[i]; - } -} - - -#endif diff --git a/dep/SFMT/SFMT.c b/dep/SFMT/SFMT.c deleted file mode 100644 index b4ac9308bb..0000000000 --- a/dep/SFMT/SFMT.c +++ /dev/null @@ -1,437 +0,0 @@ -/** - * @file SFMT.c - * @brief SIMD oriented Fast Mersenne Twister(SFMT) - * - * @author Mutsuo Saito (Hiroshima University) - * @author Makoto Matsumoto (Hiroshima University) - * - * Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima - * University. - * Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, Hiroshima - * University and The University of Tokyo. - * Copyright (C) 2013 Mutsuo Saito, Makoto Matsumoto and Hiroshima - * University. - * All rights reserved. - * - * The 3-clause BSD License is applied to this software, see - * LICENSE.txt - */ - -#if defined(__cplusplus) -extern "C" { -#endif - -#include -#include -#include "SFMT.h" -#include "SFMT-params.h" -#include "SFMT-common.h" - -#if defined(__BIG_ENDIAN__) && !defined(__amd64) && !defined(BIG_ENDIAN64) -#define BIG_ENDIAN64 1 -#endif -#if defined(HAVE_ALTIVEC) && !defined(BIG_ENDIAN64) -#define BIG_ENDIAN64 1 -#endif -#if defined(ONLY64) && !defined(BIG_ENDIAN64) - #if defined(__GNUC__) - #error "-DONLY64 must be specified with -DBIG_ENDIAN64" - #endif -#undef ONLY64 -#endif - -/*---------------- - STATIC FUNCTIONS - ----------------*/ -inline static int idxof(int i); -inline static void gen_rand_array(sfmt_t * sfmt, w128_t *array, int size); -inline static uint32_t func1(uint32_t x); -inline static uint32_t func2(uint32_t x); -static void period_certification(sfmt_t * sfmt); -#if defined(BIG_ENDIAN64) && !defined(ONLY64) -inline static void swap(w128_t *array, int size); -#endif - -#if defined(HAVE_ALTIVEC) - #include "SFMT-alti.h" -#elif defined(HAVE_SSE2) -/** - * parameters used by sse2. - */ - static const w128_t sse2_param_mask = {{SFMT_MSK1, SFMT_MSK2, - SFMT_MSK3, SFMT_MSK4}}; - #if defined(_MSC_VER) - #include "SFMT-sse2-msc.h" - #else - #include "SFMT-sse2.h" - #endif -#elif defined(HAVE_NEON) - #include "SFMT-neon.h" -#endif - -/** - * This function simulate a 64-bit index of LITTLE ENDIAN - * in BIG ENDIAN machine. - */ -#ifdef ONLY64 -inline static int idxof(int i) { - return i ^ 1; -} -#else -inline static int idxof(int i) { - return i; -} -#endif - -#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2)) && (!defined(HAVE_NEON)) -/** - * This function fills the user-specified array with pseudorandom - * integers. - * - * @param sfmt SFMT internal state - * @param array an 128-bit array to be filled by pseudorandom numbers. - * @param size number of 128-bit pseudorandom numbers to be generated. - */ -inline static void gen_rand_array(sfmt_t * sfmt, w128_t *array, int size) { - int i, j; - w128_t *r1, *r2; - - r1 = &sfmt->state[SFMT_N - 2]; - r2 = &sfmt->state[SFMT_N - 1]; - for (i = 0; i < SFMT_N - SFMT_POS1; i++) { - do_recursion(&array[i], &sfmt->state[i], &sfmt->state[i + SFMT_POS1], r1, r2); - r1 = r2; - r2 = &array[i]; - } - for (; i < SFMT_N; i++) { - do_recursion(&array[i], &sfmt->state[i], - &array[i + SFMT_POS1 - SFMT_N], r1, r2); - r1 = r2; - r2 = &array[i]; - } - for (; i < size - SFMT_N; i++) { - do_recursion(&array[i], &array[i - SFMT_N], - &array[i + SFMT_POS1 - SFMT_N], r1, r2); - r1 = r2; - r2 = &array[i]; - } - for (j = 0; j < 2 * SFMT_N - size; j++) { - sfmt->state[j] = array[j + size - SFMT_N]; - } - for (; i < size; i++, j++) { - do_recursion(&array[i], &array[i - SFMT_N], - &array[i + SFMT_POS1 - SFMT_N], r1, r2); - r1 = r2; - r2 = &array[i]; - sfmt->state[j] = array[i]; - } -} -#endif - -#if defined(BIG_ENDIAN64) && !defined(ONLY64) && !defined(HAVE_ALTIVEC) -inline static void swap(w128_t *array, int size) { - int i; - uint32_t x, y; - - for (i = 0; i < size; i++) { - x = array[i].u[0]; - y = array[i].u[2]; - array[i].u[0] = array[i].u[1]; - array[i].u[2] = array[i].u[3]; - array[i].u[1] = x; - array[i].u[3] = y; - } -} -#endif -/** - * This function represents a function used in the initialization - * by init_by_array - * @param x 32-bit integer - * @return 32-bit integer - */ -static uint32_t func1(uint32_t x) { - return (x ^ (x >> 27)) * (uint32_t)1664525UL; -} - -/** - * This function represents a function used in the initialization - * by init_by_array - * @param x 32-bit integer - * @return 32-bit integer - */ -static uint32_t func2(uint32_t x) { - return (x ^ (x >> 27)) * (uint32_t)1566083941UL; -} - -/** - * This function certificate the period of 2^{MEXP} - * @param sfmt SFMT internal state - */ -static void period_certification(sfmt_t * sfmt) { - uint32_t inner = 0; - int i, j; - uint32_t work; - uint32_t *psfmt32 = &sfmt->state[0].u[0]; - const uint32_t parity[4] = {SFMT_PARITY1, SFMT_PARITY2, - SFMT_PARITY3, SFMT_PARITY4}; - - for (i = 0; i < 4; i++) { - inner ^= psfmt32[idxof(i)] & parity[i]; - } - for (i = 16; i > 0; i >>= 1) { - inner ^= inner >> i; - } - inner &= 1; - /* check OK */ - if (inner == 1) { - return; - } - /* check NG, and modification */ - for (i = 0; i < 4; i++) { - work = 1; - for (j = 0; j < 32; j++) { - if ((work & parity[i]) != 0) { - psfmt32[idxof(i)] ^= work; - return; - } - work = work << 1; - } - } -} - -/*---------------- - PUBLIC FUNCTIONS - ----------------*/ -#define UNUSED_VARIABLE(x) (void)(x) -/** - * This function returns the identification string. - * The string shows the word size, the Mersenne exponent, - * and all parameters of this generator. - * @param sfmt SFMT internal state - */ -const char *sfmt_get_idstring(sfmt_t * sfmt) { - UNUSED_VARIABLE(sfmt); - return SFMT_IDSTR; -} - -/** - * This function returns the minimum size of array used for \b - * fill_array32() function. - * @param sfmt SFMT internal state - * @return minimum size of array used for fill_array32() function. - */ -int sfmt_get_min_array_size32(sfmt_t * sfmt) { - UNUSED_VARIABLE(sfmt); - return SFMT_N32; -} - -/** - * This function returns the minimum size of array used for \b - * fill_array64() function. - * @param sfmt SFMT internal state - * @return minimum size of array used for fill_array64() function. - */ -int sfmt_get_min_array_size64(sfmt_t * sfmt) { - UNUSED_VARIABLE(sfmt); - return SFMT_N64; -} - -#if !defined(HAVE_SSE2) && !defined(HAVE_ALTIVEC) && !defined(HAVE_NEON) -/** - * This function fills the internal state array with pseudorandom - * integers. - * @param sfmt SFMT internal state - */ -void sfmt_gen_rand_all(sfmt_t * sfmt) { - int i; - w128_t *r1, *r2; - - r1 = &sfmt->state[SFMT_N - 2]; - r2 = &sfmt->state[SFMT_N - 1]; - for (i = 0; i < SFMT_N - SFMT_POS1; i++) { - do_recursion(&sfmt->state[i], &sfmt->state[i], - &sfmt->state[i + SFMT_POS1], r1, r2); - r1 = r2; - r2 = &sfmt->state[i]; - } - for (; i < SFMT_N; i++) { - do_recursion(&sfmt->state[i], &sfmt->state[i], - &sfmt->state[i + SFMT_POS1 - SFMT_N], r1, r2); - r1 = r2; - r2 = &sfmt->state[i]; - } -} -#endif - -#ifndef ONLY64 -/** - * This function generates pseudorandom 32-bit integers in the - * specified array[] by one call. The number of pseudorandom integers - * is specified by the argument size, which must be at least 624 and a - * multiple of four. The generation by this function is much faster - * than the following gen_rand function. - * - * For initialization, init_gen_rand or init_by_array must be called - * before the first call of this function. This function can not be - * used after calling gen_rand function, without initialization. - * - * @param sfmt SFMT internal state - * @param array an array where pseudorandom 32-bit integers are filled - * by this function. The pointer to the array must be \b "aligned" - * (namely, must be a multiple of 16) in the SIMD version, since it - * refers to the address of a 128-bit integer. In the standard C - * version, the pointer is arbitrary. - * - * @param size the number of 32-bit pseudorandom integers to be - * generated. size must be a multiple of 4, and greater than or equal - * to (MEXP / 128 + 1) * 4. - * - * @note \b memalign or \b posix_memalign is available to get aligned - * memory. Mac OSX doesn't have these functions, but \b malloc of OSX - * returns the pointer to the aligned memory block. - */ -void sfmt_fill_array32(sfmt_t * sfmt, uint32_t *array, int size) { - assert(sfmt->idx == SFMT_N32); - assert(size % 4 == 0); - assert(size >= SFMT_N32); - - gen_rand_array(sfmt, (w128_t *)array, size / 4); - sfmt->idx = SFMT_N32; -} -#endif - -/** - * This function generates pseudorandom 64-bit integers in the - * specified array[] by one call. The number of pseudorandom integers - * is specified by the argument size, which must be at least 312 and a - * multiple of two. The generation by this function is much faster - * than the following gen_rand function. - * - * @param sfmt SFMT internal state - * For initialization, init_gen_rand or init_by_array must be called - * before the first call of this function. This function can not be - * used after calling gen_rand function, without initialization. - * - * @param array an array where pseudorandom 64-bit integers are filled - * by this function. The pointer to the array must be "aligned" - * (namely, must be a multiple of 16) in the SIMD version, since it - * refers to the address of a 128-bit integer. In the standard C - * version, the pointer is arbitrary. - * - * @param size the number of 64-bit pseudorandom integers to be - * generated. size must be a multiple of 2, and greater than or equal - * to (MEXP / 128 + 1) * 2 - * - * @note \b memalign or \b posix_memalign is available to get aligned - * memory. Mac OSX doesn't have these functions, but \b malloc of OSX - * returns the pointer to the aligned memory block. - */ -void sfmt_fill_array64(sfmt_t * sfmt, uint64_t *array, int size) { - assert(sfmt->idx == SFMT_N32); - assert(size % 2 == 0); - assert(size >= SFMT_N64); - - gen_rand_array(sfmt, (w128_t *)array, size / 2); - sfmt->idx = SFMT_N32; - -#if defined(BIG_ENDIAN64) && !defined(ONLY64) - swap((w128_t *)array, size /2); -#endif -} - -/** - * This function initializes the internal state array with a 32-bit - * integer seed. - * - * @param sfmt SFMT internal state - * @param seed a 32-bit integer used as the seed. - */ -void sfmt_init_gen_rand(sfmt_t * sfmt, uint32_t seed) { - int i; - - uint32_t *psfmt32 = &sfmt->state[0].u[0]; - - psfmt32[idxof(0)] = seed; - for (i = 1; i < SFMT_N32; i++) { - psfmt32[idxof(i)] = 1812433253UL * (psfmt32[idxof(i - 1)] - ^ (psfmt32[idxof(i - 1)] >> 30)) - + i; - } - sfmt->idx = SFMT_N32; - period_certification(sfmt); -} - -/** - * This function initializes the internal state array, - * with an array of 32-bit integers used as the seeds - * @param sfmt SFMT internal state - * @param init_key the array of 32-bit integers, used as a seed. - * @param key_length the length of init_key. - */ -void sfmt_init_by_array(sfmt_t * sfmt, uint32_t *init_key, int key_length) { - int i, j, count; - uint32_t r; - int lag; - int mid; - int size = SFMT_N * 4; - uint32_t *psfmt32 = &sfmt->state[0].u[0]; - - if (size >= 623) { - lag = 11; - } else if (size >= 68) { - lag = 7; - } else if (size >= 39) { - lag = 5; - } else { - lag = 3; - } - mid = (size - lag) / 2; - - memset(sfmt, 0x8b, sizeof(sfmt_t)); - if (key_length + 1 > SFMT_N32) { - count = key_length + 1; - } else { - count = SFMT_N32; - } - r = func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid)] - ^ psfmt32[idxof(SFMT_N32 - 1)]); - psfmt32[idxof(mid)] += r; - r += key_length; - psfmt32[idxof(mid + lag)] += r; - psfmt32[idxof(0)] = r; - - count--; - for (i = 1, j = 0; (j < count) && (j < key_length); j++) { - r = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % SFMT_N32)] - ^ psfmt32[idxof((i + SFMT_N32 - 1) % SFMT_N32)]); - psfmt32[idxof((i + mid) % SFMT_N32)] += r; - r += init_key[j] + i; - psfmt32[idxof((i + mid + lag) % SFMT_N32)] += r; - psfmt32[idxof(i)] = r; - i = (i + 1) % SFMT_N32; - } - for (; j < count; j++) { - r = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % SFMT_N32)] - ^ psfmt32[idxof((i + SFMT_N32 - 1) % SFMT_N32)]); - psfmt32[idxof((i + mid) % SFMT_N32)] += r; - r += i; - psfmt32[idxof((i + mid + lag) % SFMT_N32)] += r; - psfmt32[idxof(i)] = r; - i = (i + 1) % SFMT_N32; - } - for (j = 0; j < SFMT_N32; j++) { - r = func2(psfmt32[idxof(i)] + psfmt32[idxof((i + mid) % SFMT_N32)] - + psfmt32[idxof((i + SFMT_N32 - 1) % SFMT_N32)]); - psfmt32[idxof((i + mid) % SFMT_N32)] ^= r; - r -= i; - psfmt32[idxof((i + mid + lag) % SFMT_N32)] ^= r; - psfmt32[idxof(i)] = r; - i = (i + 1) % SFMT_N32; - } - - sfmt->idx = SFMT_N32; - period_certification(sfmt); -} -#if defined(__cplusplus) -} -#endif diff --git a/dep/SFMT/SFMT.h b/dep/SFMT/SFMT.h deleted file mode 100644 index 79e012d633..0000000000 --- a/dep/SFMT/SFMT.h +++ /dev/null @@ -1,304 +0,0 @@ -#pragma once -/** - * @file SFMT.h - * - * @brief SIMD oriented Fast Mersenne Twister(SFMT) pseudorandom - * number generator using C structure. - * - * @author Mutsuo Saito (Hiroshima University) - * @author Makoto Matsumoto (The University of Tokyo) - * - * Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima - * University. - * Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, Hiroshima - * University and The University of Tokyo. - * All rights reserved. - * - * The 3-clause BSD License is applied to this software, see - * LICENSE.txt - * - * @note We assume that your system has inttypes.h. If your system - * doesn't have inttypes.h, you have to typedef uint32_t and uint64_t, - * and you have to define PRIu64 and PRIx64 in this file as follows: - * @verbatim - typedef unsigned int uint32_t - typedef unsigned long long uint64_t - #define PRIu64 "llu" - #define PRIx64 "llx" -@endverbatim - * uint32_t must be exactly 32-bit unsigned integer type (no more, no - * less), and uint64_t must be exactly 64-bit unsigned integer type. - * PRIu64 and PRIx64 are used for printf function to print 64-bit - * unsigned int and 64-bit unsigned int in hexadecimal format. - */ - -#ifndef SFMTST_H -#define SFMTST_H -#if defined(__cplusplus) -extern "C" { -#endif - -#include -#include - -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - #include -#elif defined(_MSC_VER) || defined(__BORLANDC__) - typedef unsigned int uint32_t; - typedef unsigned __int64 uint64_t; - #define inline __inline -#else - #include - #if defined(__GNUC__) - #define inline __inline__ - #endif -#endif - -#ifndef PRIu64 - #if defined(_MSC_VER) || defined(__BORLANDC__) - #define PRIu64 "I64u" - #define PRIx64 "I64x" - #else - #define PRIu64 "llu" - #define PRIx64 "llx" - #endif -#endif - -#include "SFMT-params.h" - -/*------------------------------------------ - 128-bit SIMD like data type for standard C - ------------------------------------------*/ -#if defined(HAVE_ALTIVEC) - #if !defined(__APPLE__) - #include - #endif -/** 128-bit data structure */ -union W128_T { - vector unsigned int s; - uint32_t u[4]; - uint64_t u64[2]; -}; -#elif defined(HAVE_NEON) - #include - -/** 128-bit data structure */ -union W128_T { - uint32_t u[4]; - uint64_t u64[2]; - uint32x4_t si; -}; -#elif defined(HAVE_SSE2) - #include - -/** 128-bit data structure */ -union W128_T { - uint32_t u[4]; - uint64_t u64[2]; - __m128i si; -}; -#else -/** 128-bit data structure */ -union W128_T { - uint32_t u[4]; - uint64_t u64[2]; -}; -#endif - -/** 128-bit data type */ -typedef union W128_T w128_t; - -/** - * SFMT internal state - */ -struct SFMT_T { - /** the 128-bit internal state array */ - w128_t state[SFMT_N]; - /** index counter to the 32-bit internal state array */ - int idx; -}; - -typedef struct SFMT_T sfmt_t; - -void sfmt_fill_array32(sfmt_t * sfmt, uint32_t * array, int size); -void sfmt_fill_array64(sfmt_t * sfmt, uint64_t * array, int size); -void sfmt_init_gen_rand(sfmt_t * sfmt, uint32_t seed); -void sfmt_init_by_array(sfmt_t * sfmt, uint32_t * init_key, int key_length); -const char * sfmt_get_idstring(sfmt_t * sfmt); -int sfmt_get_min_array_size32(sfmt_t * sfmt); -int sfmt_get_min_array_size64(sfmt_t * sfmt); -void sfmt_gen_rand_all(sfmt_t * sfmt); - -#ifndef ONLY64 -/** - * This function generates and returns 32-bit pseudorandom number. - * init_gen_rand or init_by_array must be called before this function. - * @param sfmt SFMT internal state - * @return 32-bit pseudorandom number - */ -inline static uint32_t sfmt_genrand_uint32(sfmt_t * sfmt) { - uint32_t r; - uint32_t * psfmt32 = &sfmt->state[0].u[0]; - - if (sfmt->idx >= SFMT_N32) { - sfmt_gen_rand_all(sfmt); - sfmt->idx = 0; - } - r = psfmt32[sfmt->idx++]; - return r; -} -#endif -/** - * This function generates and returns 64-bit pseudorandom number. - * init_gen_rand or init_by_array must be called before this function. - * The function gen_rand64 should not be called after gen_rand32, - * unless an initialization is again executed. - * @param sfmt SFMT internal state - * @return 64-bit pseudorandom number - */ -inline static uint64_t sfmt_genrand_uint64(sfmt_t * sfmt) { -#if defined(BIG_ENDIAN64) && !defined(ONLY64) - uint32_t * psfmt32 = &sfmt->state[0].u[0]; - uint32_t r1, r2; -#else - uint64_t r; -#endif - uint64_t * psfmt64 = &sfmt->state[0].u64[0]; - assert(sfmt->idx % 2 == 0); - - if (sfmt->idx >= SFMT_N32) { - sfmt_gen_rand_all(sfmt); - sfmt->idx = 0; - } -#if defined(BIG_ENDIAN64) && !defined(ONLY64) - r1 = psfmt32[sfmt->idx]; - r2 = psfmt32[sfmt->idx + 1]; - sfmt->idx += 2; - return ((uint64_t)r2 << 32) | r1; -#else - r = psfmt64[sfmt->idx / 2]; - sfmt->idx += 2; - return r; -#endif -} - -/* ================================================= - The following real versions are due to Isaku Wada - ================================================= */ -/** - * converts an unsigned 32-bit number to a double on [0,1]-real-interval. - * @param v 32-bit unsigned integer - * @return double on [0,1]-real-interval - */ -inline static double sfmt_to_real1(uint32_t v) -{ - return v * (1.0/4294967295.0); - /* divided by 2^32-1 */ -} - -/** - * generates a random number on [0,1]-real-interval - * @param sfmt SFMT internal state - * @return double on [0,1]-real-interval - */ -inline static double sfmt_genrand_real1(sfmt_t * sfmt) -{ - return sfmt_to_real1(sfmt_genrand_uint32(sfmt)); -} - -/** - * converts an unsigned 32-bit integer to a double on [0,1)-real-interval. - * @param v 32-bit unsigned integer - * @return double on [0,1)-real-interval - */ -inline static double sfmt_to_real2(uint32_t v) -{ - return v * (1.0/4294967296.0); - /* divided by 2^32 */ -} - -/** - * generates a random number on [0,1)-real-interval - * @param sfmt SFMT internal state - * @return double on [0,1)-real-interval - */ -inline static double sfmt_genrand_real2(sfmt_t * sfmt) -{ - return sfmt_to_real2(sfmt_genrand_uint32(sfmt)); -} - -/** - * converts an unsigned 32-bit integer to a double on (0,1)-real-interval. - * @param v 32-bit unsigned integer - * @return double on (0,1)-real-interval - */ -inline static double sfmt_to_real3(uint32_t v) -{ - return (((double)v) + 0.5)*(1.0/4294967296.0); - /* divided by 2^32 */ -} - -/** - * generates a random number on (0,1)-real-interval - * @param sfmt SFMT internal state - * @return double on (0,1)-real-interval - */ -inline static double sfmt_genrand_real3(sfmt_t * sfmt) -{ - return sfmt_to_real3(sfmt_genrand_uint32(sfmt)); -} - -/** - * converts an unsigned 32-bit integer to double on [0,1) - * with 53-bit resolution. - * @param v 32-bit unsigned integer - * @return double on [0,1)-real-interval with 53-bit resolution. - */ -inline static double sfmt_to_res53(uint64_t v) -{ - return (v >> 11) * (1.0/9007199254740992.0); -} - -/** - * generates a random number on [0,1) with 53-bit resolution - * @param sfmt SFMT internal state - * @return double on [0,1) with 53-bit resolution - */ -inline static double sfmt_genrand_res53(sfmt_t * sfmt) -{ - return sfmt_to_res53(sfmt_genrand_uint64(sfmt)); -} - - -/* ================================================= - The following function are added by Saito. - ================================================= */ -/** - * generates a random number on [0,1) with 53-bit resolution from two - * 32 bit integers - */ -inline static double sfmt_to_res53_mix(uint32_t x, uint32_t y) -{ - return sfmt_to_res53(x | ((uint64_t)y << 32)); -} - -/** - * generates a random number on [0,1) with 53-bit resolution - * using two 32bit integers. - * @param sfmt SFMT internal state - * @return double on [0,1) with 53-bit resolution - */ -inline static double sfmt_genrand_res53_mix(sfmt_t * sfmt) -{ - uint32_t x, y; - - x = sfmt_genrand_uint32(sfmt); - y = sfmt_genrand_uint32(sfmt); - return sfmt_to_res53_mix(x, y); -} - -#if defined(__cplusplus) -} -#endif - -#endif diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 4c4e9266ac..b447294951 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -66,7 +66,7 @@ target_link_libraries(common fmt g3dlib Detour - sfmt + pcg utf8cpp openssl valgrind diff --git a/src/common/Utilities/SFMTRand.cpp b/src/common/Utilities/PCGRand.cpp similarity index 58% rename from src/common/Utilities/SFMTRand.cpp rename to src/common/Utilities/PCGRand.cpp index 2c472f2364..8d2d94b261 100644 --- a/src/common/Utilities/SFMTRand.cpp +++ b/src/common/Utilities/PCGRand.cpp @@ -15,7 +15,7 @@ * with this program. If not, see . */ -#include "SFMTRand.h" +#include "PCGRand.h" #include #include #include @@ -23,61 +23,57 @@ #include #include -SFMTRand::SFMTRand() +PCGRand::PCGRand() { std::random_device dev; if (dev.entropy() > 0) - { - std::array seed; - std::generate(seed.begin(), seed.end(), std::ref(dev)); - - sfmt_init_by_array(&_state, seed.data(), seed.size()); - } + _state.seed(pcg_extras::seed_seq_from()); else - sfmt_init_gen_rand(&_state, uint32(time(nullptr))); + _state.seed(uint64(time(nullptr))); } -uint32 SFMTRand::RandomUInt32() // Output random bits +uint32 PCGRand::RandomUInt32() // Output random bits { - return sfmt_genrand_uint32(&_state); + std::uniform_int_distribution dist; + return dist(_state); } -void* SFMTRand::operator new(size_t size, std::nothrow_t const&) +void* PCGRand::operator new(size_t size, std::nothrow_t const&) { return _mm_malloc(size, 16); } -void SFMTRand::operator delete(void* ptr, std::nothrow_t const&) +void PCGRand::operator delete(void* ptr, std::nothrow_t const&) { _mm_free(ptr); } -void* SFMTRand::operator new(size_t size) +void* PCGRand::operator new(size_t size) { return _mm_malloc(size, 16); } -void SFMTRand::operator delete(void* ptr) +void PCGRand::operator delete(void* ptr) { _mm_free(ptr); } -void* SFMTRand::operator new[](size_t size, std::nothrow_t const&) +void* PCGRand::operator new[](size_t size, std::nothrow_t const&) { return _mm_malloc(size, 16); } -void SFMTRand::operator delete[](void* ptr, std::nothrow_t const&) +void PCGRand::operator delete[](void* ptr, std::nothrow_t const&) { _mm_free(ptr); } -void* SFMTRand::operator new[](size_t size) +void* PCGRand::operator new[](size_t size) { return _mm_malloc(size, 16); } -void SFMTRand::operator delete[](void* ptr) +void PCGRand::operator delete[](void* ptr) { _mm_free(ptr); } diff --git a/src/common/Utilities/SFMTRand.h b/src/common/Utilities/PCGRand.h similarity index 87% rename from src/common/Utilities/SFMTRand.h rename to src/common/Utilities/PCGRand.h index 7d9a820c48..6298762a51 100644 --- a/src/common/Utilities/SFMTRand.h +++ b/src/common/Utilities/PCGRand.h @@ -15,19 +15,20 @@ * with this program. If not, see . */ -#ifndef SFMTRand_h__ -#define SFMTRand_h__ +#ifndef PCGRand_h__ +#define PCGRand_h__ #include "Define.h" -#include +#include "pcg_random.hpp" #include -/* - * C++ Wrapper for SFMT - */ -class SFMTRand { + /* + * C++ Wrapper for PCG + */ +class PCGRand +{ public: - SFMTRand(); + PCGRand(); uint32 RandomUInt32(); // Output random bits void* operator new(size_t size, std::nothrow_t const&); void operator delete(void* ptr, std::nothrow_t const&); @@ -38,7 +39,8 @@ public: void* operator new[](size_t size); void operator delete[](void* ptr); private: - sfmt_t _state; + + pcg32 _state; }; -#endif // SFMTRand_h__ +#endif // PCGRand_h__ diff --git a/src/common/Utilities/Random.cpp b/src/common/Utilities/Random.cpp index 7da7a43256..1f5fe231a3 100644 --- a/src/common/Utilities/Random.cpp +++ b/src/common/Utilities/Random.cpp @@ -17,19 +17,19 @@ #include "Random.h" #include "Errors.h" -#include "SFMTRand.h" +#include "PCGRand.h" #include #include -static thread_local std::unique_ptr sfmtRand; +static thread_local std::unique_ptr pcgRand; static RandomEngine engine; -static SFMTRand* GetRng() +static PCGRand* GetRng() { - if (!sfmtRand) - sfmtRand = std::make_unique(); + if (!pcgRand) + pcgRand = std::make_unique(); - return sfmtRand.get(); + return pcgRand.get(); } int32 irand(int32 min, int32 max)