--- deliantra/server/include/rng.h 2010/07/06 20:00:46 1.2 +++ deliantra/server/include/rng.h 2012/05/17 02:20:45 1.10 @@ -1,7 +1,7 @@ /* * This file is part of Deliantra, the Roguelike Realtime MMORPG. * - * Copyright (©) 2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * Copyright (©) 2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team * * Deliantra is free software: you can redistribute it and/or modify it under * the terms of the Affero GNU General Public License as published by the @@ -25,10 +25,12 @@ #include +typedef uint32_t seed_t; // overkill + // P. L'Ecuyer, “Maximally Equidistributed Combined Tausworthe Generators”, Mathematics of Computation, 65, 213 (1996), 203–213. // http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps // http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps -struct tausworthe_random_generator +struct tausworthe_rng { uint32_t state [4]; @@ -41,13 +43,13 @@ // this one is about 40% faster than the tausworthe one above (i.e. not much), // despite the inlining, and has the issue of only creating 2**32-1 numbers. // see also http://www.iro.umontreal.ca/~lecuyer/myftp/papers/xorshift.pdf -struct xorshift_random_generator +struct xorshift_rng { uint32_t x, y; void seed (uint32_t seed) { - x = seed | 1; + x = seed ? seed : 0xdeadbeef; y = x * 69069U; } @@ -60,8 +62,30 @@ } }; +template +struct lc_rng +{ + uint32_t x; + + void seed (uint32_t seed) + { + x = seed; + } + + uint32_t next () + { + x = x * A + B; + return x; + } +}; + +typedef lc_rng<3039177861U, 0U> borosh_niederreiter_rng; +typedef lc_rng<2147001325U, 715136305U> bcpl_rng; +typedef lc_rng< 1664525U, 1U> lavaux_janssens_rng; +typedef lc_rng< 1664525U, 1013904223U> numerical_recipes_rng; + template -struct gfsr_random_generator +struct gfsr_rng { int i; T x[N]; @@ -87,9 +111,9 @@ } // actually should subclass to gfsr32... :) - void seed (uint32_t seed) + void seed (seed_t seed) { - xorshift_random_generator rng; + xorshift_rng rng; rng.seed (seed); this->seed_rng (rng); @@ -112,24 +136,27 @@ // these are about 2-3 times faster than tausworthe, non-inlined, // and likely of higher quality. -typedef gfsr_random_generator r250_random_generator; -typedef gfsr_random_generator r521_random_generator; +typedef gfsr_rng r250_rng; +typedef gfsr_rng r521_rng; // freeciv uses this one, so it's good enough for us :) -typedef gfsr_random_generator freeciv_random_generator; +// (also known as mitchell moore generator +typedef gfsr_rng freeciv_rng; // this one should be high quality, but is slightly slower than tausworthe -struct r250521_random_generator +struct r250521_rng { - r250_random_generator r250; - r521_random_generator r521; + r250_rng r250; + r521_rng r521; void seed (uint32_t seed); uint32_t next (); }; -// this is actually an adaptor that provides different types -// of random numbers. +///////////////////////////////////////////////////////////////////////////// + +// this is actually an adaptor that provides different +// distributions of random numbers. template struct random_number_generator : generator { @@ -137,7 +164,7 @@ { } - random_number_generator (uint32_t seed) + random_number_generator (seed_t seed) { this->seed (seed); } @@ -158,14 +185,18 @@ : get_range (r_min, r_max); } + uint32_t get_u32 (); + uint64_t get_u64 (); + float get_float (); + double get_double (); + // return a number within the half-open interval [0..1[ - double operator ()() + double operator () () { - return this->next () / (double)0x100000000ULL; + return get_double (); } - uint32_t get_u32 (); - uint64_t get_u64 (); + uint32_t poisson (double mean); protected: uint32_t get_range (uint32_t r_max); @@ -173,10 +204,10 @@ }; // the default rng used in the game -typedef random_number_generator rand_gen; +typedef random_number_generator rand_gen; // used when we often seed -typedef random_number_generator seedable_rand_gen; +typedef random_number_generator seedable_rand_gen; extern rand_gen rndm, rmg_rndm;