LCOV - code coverage report
Current view: top level - src/utils/common - RandHelper.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 32 33 97.0 %
Date: 2024-05-02 15:31:40 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
       4             : // This program and the accompanying materials are made available under the
       5             : // terms of the Eclipse Public License 2.0 which is available at
       6             : // https://www.eclipse.org/legal/epl-2.0/
       7             : // This Source Code may also be made available under the following Secondary
       8             : // Licenses when the conditions for such availability set forth in the Eclipse
       9             : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10             : // or later which is available at
      11             : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12             : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13             : /****************************************************************************/
      14             : /// @file    RandHelper.cpp
      15             : /// @author  Daniel Krajzewicz
      16             : /// @author  Michael Behrisch
      17             : /// @date    Tue, 29.05.2005
      18             : ///
      19             : //
      20             : /****************************************************************************/
      21             : #include <config.h>
      22             : 
      23             : #include <ctime>
      24             : #include <utils/options/OptionsCont.h>
      25             : #include <utils/common/SysUtils.h>
      26             : #include "StdDefs.h"
      27             : #include "RandHelper.h"
      28             : 
      29             : 
      30             : // debug vehicle movement randomness (dawdling in finalizeSpeed)
      31             : //#define DEBUG_FLAG1
      32             : //#define DEBUG_RANDCALLS
      33             : //#define DEBUG_RANDCALLS_PARALLEL
      34             : 
      35             : 
      36             : // ===========================================================================
      37             : // static member variables
      38             : // ===========================================================================
      39             : SumoRNG RandHelper::myRandomNumberGenerator("default");
      40             : 
      41             : #ifdef DEBUG_RANDCALLS
      42             : unsigned long long int myDebugIndex(7);
      43             : std::string myDebugId("");
      44             : #endif
      45             : 
      46             : #ifdef DEBUG_RANDCALLS_PARALLEL
      47             : #include <thread>
      48             : #include <utils/iodevices/OutputDevice.h>
      49             : std::map<std::thread::id, int> threadIndices;
      50             : std::map<std::string, int> lastThreadIndex; // by rng
      51             : #endif
      52             : 
      53             : 
      54             : // ===========================================================================
      55             : // member method definitions
      56             : // ===========================================================================
      57             : 
      58             : void
      59       44511 : RandHelper::insertRandOptions(OptionsCont& oc) {
      60             :     // registers random number options
      61       44511 :     oc.addOptionSubTopic("Random Number");
      62             : 
      63       44511 :     oc.doRegister("random", new Option_Bool(false));
      64       89022 :     oc.addSynonyme("random", "abs-rand", true);
      65       89022 :     oc.addDescription("random", "Random Number", TL("Initialises the random number generator with the current system time"));
      66             : 
      67       44511 :     oc.doRegister("seed", new Option_Integer(23423));
      68       89022 :     oc.addSynonyme("seed", "srand", true);
      69       89022 :     oc.addDescription("seed", "Random Number", TL("Initialises the random number generator with the given value"));
      70       44511 : }
      71             : 
      72             : 
      73             : void
      74     2525607 : RandHelper::initRand(SumoRNG* which, const bool random, const int seed) {
      75     2525607 :     if (which == nullptr) {
      76             :         which = &myRandomNumberGenerator;
      77             :     }
      78     2525607 :     if (random) {
      79           0 :         which->seed((unsigned long)time(nullptr));
      80             :     } else {
      81     2525607 :         which->seed(seed);
      82             :     }
      83     2525607 : }
      84             : 
      85             : 
      86             : void
      87      255783 : RandHelper::initRandGlobal(SumoRNG* which) {
      88      255783 :     OptionsCont& oc = OptionsCont::getOptions();
      89      511566 :     initRand(which, oc.getBool("random"), oc.getInt("seed"));
      90      255783 : }
      91             : 
      92             : 
      93             : double
      94   881286186 : RandHelper::rand(SumoRNG* rng) {
      95   881286186 :     if (rng == nullptr) {
      96             :         rng = &myRandomNumberGenerator;
      97             :     }
      98   881286186 :     const double res = double((*rng)() / 4294967296.0);
      99   881286186 :     rng->count++;
     100             : #ifdef DEBUG_RANDCALLS
     101             :     if (rng->count == myDebugIndex
     102             :             && (myDebugId == "" || rng->id == myDebugId)) {
     103             :         std::cout << "DEBUG\n"; // for setting breakpoint
     104             :     }
     105             :     std::stringstream stream; // to reduce output interleaving from different threads
     106             : #ifdef DEBUG_RANDCALLS_PARALLEL
     107             :     auto threadID = std::this_thread::get_id();
     108             :     if (threadIndices.count(threadID) == 0) {
     109             :         const int tmp = threadIndices.size();
     110             :         threadIndices[threadID] = tmp;
     111             :     }
     112             :     int threadIndex = threadIndices[threadID];
     113             :     auto it = lastThreadIndex.find(rng->id);
     114             :     if ((it == lastThreadIndex.end() || it->second != threadIndex)
     115             :             && (myDebugId == "" || rng->id == myDebugId)) {
     116             :         std::cout << "DEBUG rng " << rng->id << " change thread old=" << (it == lastThreadIndex.end() ? -1 : it->second) << " new=" << threadIndex << " (" << std::this_thread::get_id() << ")\n"; // for setting breakpoint
     117             :     }
     118             :     lastThreadIndex[rng->id] = threadIndex;
     119             :     stream << "rng " << rng->id << " call=" << rng->count << " thread=" << threadIndex << " val=" << res << "\n";
     120             :     OutputDevice::getDevice(rng->id) << stream.str();
     121             : #else
     122             :     stream << "rng " << rng->id << " call=" << rng->count << " val=" << res << "\n";
     123             :     std::cout << stream.str();
     124             : #endif
     125             : #endif
     126             : #ifdef DEBUG_FLAG1
     127             :     if (gDebugFlag1) {
     128             :         std::stringstream stream; // to reduce output interleaving from different threads
     129             :         stream << "rng " << rng->id << " call=" << rng->count << " val=" << res << "\n";
     130             :         std::cout << stream.str();
     131             :     }
     132             : #endif
     133   881286186 :     return res;
     134             : }
     135             : 
     136             : double
     137    37942166 : RandHelper::randNorm(double mean, double variance, SumoRNG* rng) {
     138             :     // Polar method to avoid cosine
     139             :     double u, q;
     140             :     do {
     141    48352779 :         u = rand(2.0, rng) - 1;
     142    48352779 :         const double v = rand(2.0, rng) - 1;
     143    48352779 :         q = u * u + v * v;
     144    48352779 :     } while (q == 0.0 || q >= 1.0);
     145    37942166 :     const double logRounded = ceil(log(q) * 1e14) / 1e14;
     146    37942166 :     return mean + variance * u * sqrt(-2 * logRounded / q);
     147             : }
     148             : 
     149             : double
     150      334902 : RandHelper::randExp(double rate, SumoRNG* rng) {
     151      334902 :     return -log(rand(rng)) / rate;
     152             : }
     153             : 
     154             : // template<class T>
     155             : // void RandHelper::shuffle(const std::vector<T>& v) {
     156             : //     std::shuffle(v.begin(), v.end(), rng);
     157             : // }
     158             : 
     159             : /****************************************************************************/

Generated by: LCOV version 1.14