Stefan Scholz / ETL
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers random.cpp Source File

random.cpp

Go to the documentation of this file.
00001 ///\file
00002 
00003 /******************************************************************************
00004 The MIT License(MIT)
00005 
00006 Embedded Template Library.
00007 https://github.com/ETLCPP/etl
00008 http://www.etlcpp.com
00009 
00010 Copyright(c) 2017 jwellbelove
00011 
00012 Permission is hereby granted, free of charge, to any person obtaining a copy
00013 of this software and associated documentation files(the "Software"), to deal
00014 in the Software without restriction, including without limitation the rights
00015 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
00016 copies of the Software, and to permit persons to whom the Software is
00017 furnished to do so, subject to the following conditions :
00018 
00019 The above copyright notice and this permission notice shall be included in all
00020 copies or substantial portions of the Software.
00021 
00022 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00023 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00024 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
00025 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00026 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00027 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00028 SOFTWARE.
00029 ******************************************************************************/
00030 
00031 #include "platform.h "
00032 #include "random.h "
00033 
00034 namespace etl
00035 {
00036   //***************************************************************************
00037   // XOR Shift
00038   //***************************************************************************
00039 
00040   //***************************************************************************
00041   /// Default constructor.
00042   /// Attempts to come up with a unique non-zero seed.
00043   //***************************************************************************
00044   random_xorshift::random_xorshift()
00045   {
00046     // An attempt to come up with a unique non-zero seed,
00047     // based on the address of the instance.
00048     uintptr_t n    = reinterpret_cast<uintptr_t>(this);
00049     uint32_t  seed = static_cast<uint32_t>(n);
00050     initialise(seed);
00051   }
00052 
00053   //***************************************************************************
00054   /// Constructor with seed value.
00055   ///\param seed The new seed value.
00056   //***************************************************************************
00057   random_xorshift::random_xorshift(uint32_t seed)
00058   {
00059     initialise(seed);
00060   }
00061 
00062   //***************************************************************************
00063   /// Initialises the sequence with a new seed value.
00064   ///\param seed The new seed value.
00065   //***************************************************************************
00066   void random_xorshift::initialise(uint32_t seed)
00067   {
00068     // Add the first four primes to ensure that the seed isn't zero.
00069     state[0] = seed + 3;
00070     state[1] = seed + 5;
00071     state[2] = seed + 7;
00072     state[3] = seed + 11;
00073   }
00074 
00075   //***************************************************************************
00076   /// Get the next random_xorshift number.
00077   //***************************************************************************
00078   uint32_t random_xorshift::operator()()
00079   {
00080     uint32_t n = state[3];
00081     n ^= n << 11;
00082     n ^= n >> 8;
00083     state[3] = state[2];
00084     state[2] = state[1];
00085     state[1] = state[0];
00086     n ^= state[0];
00087     n ^= state[0] >> 19;
00088     state[0] = n;
00089 
00090     return n;
00091   }
00092 
00093   //***************************************************************************
00094   /// Get the next random_xorshift number in a specified inclusive range.
00095   //***************************************************************************
00096   uint32_t random_xorshift::range(uint32_t low, uint32_t high)
00097   {
00098     uint32_t r = high - low + 1;
00099     uint32_t n = operator()();
00100     n %= r;
00101     n += low;
00102 
00103     return n;
00104   }
00105 
00106   //***************************************************************************
00107   // Linear Congruential Generator
00108   //***************************************************************************
00109 
00110   //***************************************************************************
00111   /// Default constructor.
00112   /// Attempts to come up with a unique non-zero seed.
00113   //***************************************************************************
00114   random_lcg::random_lcg()
00115   {
00116     // An attempt to come up with a unique non-zero seed,
00117     // based on the address of the instance.
00118     uintptr_t n    = reinterpret_cast<uintptr_t>(this);
00119     uint32_t  seed = static_cast<uint32_t>(n);
00120     initialise(seed);
00121   }
00122 
00123   //***************************************************************************
00124   /// Constructor with seed value.
00125   ///\param seed The new seed value.
00126   //***************************************************************************
00127   random_lcg::random_lcg(uint32_t seed)
00128   {
00129     initialise(seed);
00130   }
00131 
00132   //***************************************************************************
00133   /// Initialises the sequence with a new seed value.
00134   ///\param seed The new seed value.
00135   //***************************************************************************
00136   void random_lcg::initialise(uint32_t seed)
00137   {
00138     seed = (seed == 0) ? 1 : seed;
00139     value = (seed > m) ? m : seed;
00140   }
00141 
00142   //***************************************************************************
00143   /// Get the next random_clcg number.
00144   //***************************************************************************
00145   uint32_t random_lcg::operator()()
00146   {
00147     value = (a * value) % m;
00148 
00149     return value;
00150   }
00151 
00152   //***************************************************************************
00153   /// Get the next random_clcg number in a specified inclusive range.
00154   //***************************************************************************
00155   uint32_t random_lcg::range(uint32_t low, uint32_t high)
00156   {
00157     uint32_t r = high - low + 1;
00158     uint32_t n = operator()();
00159     n %= r;
00160     n += low;
00161 
00162     return n;
00163   }
00164 
00165   //***************************************************************************
00166   // Combined Linear Congruential Generator
00167   //***************************************************************************
00168 
00169   //***************************************************************************
00170   /// Default constructor.
00171   /// Attempts to come up with a unique non-zero seed.
00172   //***************************************************************************
00173   random_clcg::random_clcg()
00174   {
00175     // An attempt to come up with a unique non-zero seed,
00176     // based on the address of the instance.
00177     uintptr_t n = reinterpret_cast<uintptr_t>(this);
00178     uint32_t  seed = static_cast<uint32_t>(n);
00179     initialise(seed);
00180   }
00181 
00182   //***************************************************************************
00183   /// Constructor with seed value.
00184   ///\param seed The new seed value.
00185   //***************************************************************************
00186   random_clcg::random_clcg(uint32_t seed)
00187   {
00188     initialise(seed);
00189   }
00190 
00191   //***************************************************************************
00192   /// Initialises the sequence with a new seed value.
00193   ///\param seed The new seed value.
00194   //***************************************************************************
00195   void random_clcg::initialise(uint32_t seed)
00196   {
00197     seed = (seed == 0) ? 1 : seed;
00198     value1 = (seed > m1) ? m1 : seed;
00199     value2 = (seed > m1) ? m1 : seed;
00200   }
00201 
00202   //***************************************************************************
00203   /// Get the next random_clcg number.
00204   //***************************************************************************
00205   uint32_t random_clcg::operator()()
00206   {
00207     static const uint32_t m = ((m1 > m2) ? m1 : m2);
00208 
00209     value1 = (a1 * value1) % m1;
00210     value2 = (a2 * value2) % m2;
00211 
00212     return (value1 + value2) % m;
00213   }
00214 
00215   //***************************************************************************
00216   /// Get the next random_clcg number in a specified inclusive range.
00217   //***************************************************************************
00218   uint32_t random_clcg::range(uint32_t low, uint32_t high)
00219   {
00220     uint32_t r = high - low + 1;
00221     uint32_t n = operator()();
00222     n %= r;
00223     n += low;
00224 
00225     return n;
00226   }
00227 
00228   //***************************************************************************
00229   // Linear Shift Feedback Register
00230   //***************************************************************************
00231 
00232   //***************************************************************************
00233   /// Default constructor.
00234   /// Attempts to come up with a unique non-zero seed.
00235   //***************************************************************************
00236   random_lsfr::random_lsfr()
00237   {
00238     // An attempt to come up with a unique non-zero seed,
00239     // based on the address of the instance.
00240     uintptr_t n    = reinterpret_cast<uintptr_t>(this);
00241     uint32_t  seed = static_cast<uint32_t>(n);
00242     initialise(seed);
00243   }
00244 
00245   //***************************************************************************
00246   /// Constructor with seed value.
00247   ///\param seed The new seed value.
00248   //***************************************************************************
00249   random_lsfr::random_lsfr(uint32_t seed)
00250   {
00251     initialise(seed);
00252   }
00253 
00254   //***************************************************************************
00255   /// Initialises the sequence with a new seed value.
00256   ///\param seed The new seed value.
00257   //***************************************************************************
00258   void random_lsfr::initialise(uint32_t seed)
00259   {
00260     value = seed;
00261   }
00262 
00263   //***************************************************************************
00264   /// Get the next random_lsfr number.
00265   //***************************************************************************
00266   uint32_t random_lsfr::operator()()
00267   {
00268     static const uint32_t polynomial = 0x80200003;
00269 
00270     value >>= 1;
00271 
00272     if ((value & 1) == 1)
00273     {
00274       value ^= polynomial;
00275     }
00276 
00277     return value;
00278   }
00279 
00280   //***************************************************************************
00281   /// Get the next random_lsfr number in a specified inclusive range.
00282   //***************************************************************************
00283   uint32_t random_lsfr::range(uint32_t low, uint32_t high)
00284   {
00285     uint32_t r = high - low + 1;
00286     uint32_t n = operator()();
00287     n %= r;
00288     n += low;
00289 
00290     return n;
00291   }
00292 
00293   //***************************************************************************
00294   // Multiply with carry random number generator.
00295   //***************************************************************************
00296 
00297   //***************************************************************************
00298   /// Default constructor.
00299   /// Attempts to come up with a unique non-zero seed.
00300   //***************************************************************************
00301   random_mwc::random_mwc()
00302   {
00303     // An attempt to come up with a unique non-zero seed,
00304     // based on the address of the instance.
00305     uintptr_t n = reinterpret_cast<uintptr_t>(this);
00306     uint32_t  seed = static_cast<uint32_t>(n);
00307     initialise(seed);
00308   }
00309 
00310   //***************************************************************************
00311   /// Constructor with seed value.
00312   ///\param seed The new seed value.
00313   //***************************************************************************
00314   random_mwc::random_mwc(uint32_t seed)
00315   {
00316     initialise(seed);
00317   }
00318 
00319   //***************************************************************************
00320   /// Initialises the sequence with a new seed value.
00321   ///\param seed The new seed value.
00322   //***************************************************************************
00323   void random_mwc::initialise(uint32_t seed)
00324   {
00325     value1 = seed;
00326     value2 = seed;
00327   }
00328 
00329   //***************************************************************************
00330   /// Get the next random_lsfr number.
00331   //***************************************************************************
00332   uint32_t random_mwc::operator()()
00333   {
00334     value1 = 36969 * (value1 & 0xFFFF) + (value1 >> 16);
00335     value2 = 18000 * (value2 & 0xFFFF) + (value2 >> 16);
00336 
00337     return (value1 << 16) + value2;
00338   }
00339 
00340   //***************************************************************************
00341   /// Get the next random_lsfr number in a specified inclusive range.
00342   //***************************************************************************
00343   uint32_t random_mwc::range(uint32_t low, uint32_t high)
00344   {
00345     uint32_t r = high - low + 1;
00346     uint32_t n = operator()();
00347     n %= r;
00348     n += low;
00349 
00350     return n;
00351   }
00352 }
00353