Program Listing for File RandomGenerators.h

↰ Return to documentation for file (ADS/numeric/RandomGenerators.h)

/*--------------------------------------------------------------------------*/
/*------------------------ File RandomGenerators.h -------------------------*/
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/*----------------------------- DEFINITIONS --------------------------------*/
/*--------------------------------------------------------------------------*/

#ifndef __ADS_RandomGenerators
 #define __ADS_RandomGenerators
                      /* self-identification: #endif constant */

/*--------------------------------------------------------------------------*/
/*------------------------------ INCLUDES ----------------------------------*/
/*--------------------------------------------------------------------------*/

#include "ADS/Contract.h"
#include "ADS/dictionary/RandomHashing.h"
#include "ADS/numeric/NumberTheory.h"

#include <array>
#include <bit>
#include <cmath>
#include <concepts>
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <limits>
#include <utility>
#include <vector>

/*--------------------------------------------------------------------------*/
/*--------------------------- NAMESPACE ------------------------------------*/
/*--------------------------------------------------------------------------*/

#if defined( __GNUC__ ) || defined( __clang__ )
 #define ADS_RNG_INLINE inline __attribute__(( always_inline ))
#elif defined( _MSC_VER )
 #define ADS_RNG_INLINE __forceinline
#else
 #define ADS_RNG_INLINE inline
#endif

namespace ADS {

template< class G >
concept FullWordGenerator =
 std::uniform_random_bit_generator< std::remove_reference_t< G > > &&
 std::same_as< typename std::remove_reference_t< G >::result_type ,
               std::uint64_t > &&
 ( std::remove_reference_t< G >::min() == 0 ) &&
 ( std::remove_reference_t< G >::max() ==
   std::numeric_limits< std::uint64_t >::max() );

/*--------------------------------------------------------------------------*/
/*--------------------------- CLASS Xoshiro256 -----------------------------*/
/*--------------------------------------------------------------------------*/

template< bool StarStar >
class Xoshiro256T {
 public:
 using result_type = std::uint64_t;

 explicit constexpr Xoshiro256T( std::uint64_t seed = 1 );

 constexpr std::uint64_t operator()( void );

 constexpr void jump( void );

 static constexpr std::uint64_t min( void ) { return( 0 ); }
 static constexpr std::uint64_t max( void ) {
  return( std::numeric_limits< std::uint64_t >::max() );
  }

 bool operator==( const Xoshiro256T & ) const = default;

 private:
 std::uint64_t f_s[ 4 ];
 };  // end( class Xoshiro256T )

using Xoshiro256 = Xoshiro256T< false >;
using Xoshiro256StarStar = Xoshiro256T< true >;

/*--------------------------------------------------------------------------*/
/*----------------------------- CLASS WyRand -------------------------------*/
/*--------------------------------------------------------------------------*/

class WyRand {
 public:
 using result_type = std::uint64_t;

 explicit constexpr WyRand( std::uint64_t seed = 1 ) : f_s( seed ) {}

 constexpr std::uint64_t operator()( void );

 static constexpr std::uint64_t min( void ) { return( 0 ); }
 static constexpr std::uint64_t max( void ) {
  return( std::numeric_limits< std::uint64_t >::max() );
  }

 bool operator==( const WyRand & ) const = default;

 private:
 std::uint64_t f_s;
 };  // end( class WyRand )

/*--------------------------------------------------------------------------*/
/*----------------------------- CLASS PhiloxT ------------------------------*/
/*--------------------------------------------------------------------------*/

template< class W >
class PhiloxT {
 static_assert( std::same_as< W , std::uint32_t > ||
                std::same_as< W , std::uint64_t > ,
                "words of 32 or 64 bits" );
 public:
 using result_type = W;
 using Block = std::array< W , 4 >;
 using Key = std::array< W , 2 >;

 static constexpr W default_seed = 20111115u;

 explicit constexpr PhiloxT( W seed = default_seed );

 constexpr W operator()( void );

 constexpr void discard( unsigned long long z );

 constexpr void setCounter( const Block & c );

 static constexpr Block block( Block c , Key k );

 static constexpr W min( void ) { return( 0 ); }
 static constexpr W max( void ) { return( std::numeric_limits< W >::max() ); }

 bool operator==( const PhiloxT & ) const = default;

 private:
 static constexpr unsigned lanes = 2;

 constexpr void refill( void );

 Key f_key;
 Block f_ctr{};
 W f_buf[ 4 * lanes ] = {};
 unsigned f_at = 4 * lanes;
 };  // end( class PhiloxT )

using Philox4x32 = PhiloxT< std::uint32_t >;
using Philox4x64 = PhiloxT< std::uint64_t >;

/*--------------------------------------------------------------------------*/
/*--------------------------- CLASS AliasTable -----------------------------*/
/*--------------------------------------------------------------------------*/

class AliasTable {
 public:
 explicit AliasTable( const std::vector< double > & w );

 [[nodiscard]] std::size_t size( void ) const { return( f_T.size() ); }

 template< FullWordGenerator G >
 std::size_t operator()( G && g ) const;

 [[nodiscard]] double probability( std::size_t i ) const;

 private:
 struct Entry {
  std::uint64_t keep;
  std::uint32_t alias;
  };
 std::vector< Entry > f_T;
 };  // end( class AliasTable )

/*--------------------------------------------------------------------------*/
/*------------------------------ FUNCTIONS ---------------------------------*/
/*--------------------------------------------------------------------------*/

template< FullWordGenerator G >
std::uint64_t uniformBelow( G && g , std::uint64_t s );

template< FullWordGenerator G >
double uniformReal( G && g );

template< FullWordGenerator G >
ADS_RNG_INLINE double normalZiggurat( G && g );

template< FullWordGenerator G >
ADS_RNG_INLINE double exponentialZiggurat( G && g );

template< std::random_access_iterator I , FullWordGenerator G >
void shuffleFast( I first , I last , G && g );

/*--------------------------------------------------------------------------*/

}  // end( namespace ADS )

/*--------------------------------------------------------------------------*/
/*-------------------------- IMPLEMENTATION --------------------------------*/
/*--------------------------------------------------------------------------*/

#include "ADS/numeric/impl/RandomGenerators.tpp"

/*--------------------------------------------------------------------------*/

#endif  /* RandomGenerators.h included */

/*--------------------------------------------------------------------------*/
/*----------------------- End File RandomGenerators.h ----------------------*/
/*--------------------------------------------------------------------------*/