lemon/random.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 24 Mar 2009 00:18:25 +0100
changeset 596 8c3112a66878
parent 492 b9b3473327e3
parent 498 afd134142111
child 550 c5fd2d996909
permissions -rw-r--r--
Use XTI implementation instead of ATI in NetworkSimplex (#234)

XTI (eXtended Threaded Index) is an imporved version of the widely
known ATI (Augmented Threaded Index) method for storing and updating
the spanning tree structure in Network Simplex algorithms.

In the ATI data structure three indices are stored for each node:
predecessor, thread and depth. In the XTI data structure depth is
replaced by the number of successors and the last successor
(according to the thread index).
alpar@209
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
alpar@10
     2
 *
alpar@209
     3
 * This file is a part of LEMON, a generic C++ optimization library.
alpar@10
     4
 *
alpar@440
     5
 * Copyright (C) 2003-2009
alpar@10
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@10
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@10
     8
 *
alpar@10
     9
 * Permission to use, modify and distribute this software is granted
alpar@10
    10
 * provided that this copyright notice appears in all copies. For
alpar@10
    11
 * precise terms see the accompanying LICENSE file.
alpar@10
    12
 *
alpar@10
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@10
    14
 * express or implied, and with no claim as to its suitability for any
alpar@10
    15
 * purpose.
alpar@10
    16
 *
alpar@10
    17
 */
alpar@10
    18
alpar@10
    19
/*
alpar@10
    20
 * This file contains the reimplemented version of the Mersenne Twister
alpar@10
    21
 * Generator of Matsumoto and Nishimura.
alpar@10
    22
 *
alpar@10
    23
 * See the appropriate copyright notice below.
alpar@209
    24
 *
alpar@10
    25
 * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
alpar@209
    26
 * All rights reserved.
alpar@10
    27
 *
alpar@10
    28
 * Redistribution and use in source and binary forms, with or without
alpar@10
    29
 * modification, are permitted provided that the following conditions
alpar@10
    30
 * are met:
alpar@10
    31
 *
alpar@10
    32
 * 1. Redistributions of source code must retain the above copyright
alpar@10
    33
 *    notice, this list of conditions and the following disclaimer.
alpar@10
    34
 *
alpar@10
    35
 * 2. Redistributions in binary form must reproduce the above copyright
alpar@10
    36
 *    notice, this list of conditions and the following disclaimer in the
alpar@10
    37
 *    documentation and/or other materials provided with the distribution.
alpar@10
    38
 *
alpar@209
    39
 * 3. The names of its contributors may not be used to endorse or promote
alpar@209
    40
 *    products derived from this software without specific prior written
alpar@10
    41
 *    permission.
alpar@10
    42
 *
alpar@10
    43
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
alpar@10
    44
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
alpar@10
    45
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
alpar@10
    46
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
alpar@10
    47
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
alpar@10
    48
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
alpar@10
    49
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
alpar@10
    50
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
alpar@10
    51
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
alpar@10
    52
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
alpar@10
    53
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
alpar@10
    54
 * OF THE POSSIBILITY OF SUCH DAMAGE.
alpar@10
    55
 *
alpar@10
    56
 *
alpar@10
    57
 * Any feedback is very welcome.
alpar@10
    58
 * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
alpar@10
    59
 * email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
alpar@10
    60
 */
alpar@10
    61
alpar@10
    62
#ifndef LEMON_RANDOM_H
alpar@10
    63
#define LEMON_RANDOM_H
alpar@10
    64
alpar@10
    65
#include <algorithm>
alpar@10
    66
#include <iterator>
alpar@10
    67
#include <vector>
deba@110
    68
#include <limits>
deba@177
    69
#include <fstream>
alpar@10
    70
alpar@68
    71
#include <lemon/math.h>
alpar@10
    72
#include <lemon/dim2.h>
alpar@68
    73
deba@177
    74
#ifndef WIN32
deba@177
    75
#include <sys/time.h>
deba@177
    76
#include <ctime>
deba@177
    77
#include <sys/types.h>
deba@177
    78
#include <unistd.h>
deba@177
    79
#else
alpar@491
    80
#include <lemon/bits/windows.h>
deba@177
    81
#endif
deba@177
    82
alpar@10
    83
///\ingroup misc
alpar@10
    84
///\file
alpar@10
    85
///\brief Mersenne Twister random number generator
alpar@10
    86
alpar@10
    87
namespace lemon {
alpar@10
    88
alpar@10
    89
  namespace _random_bits {
alpar@209
    90
alpar@10
    91
    template <typename _Word, int _bits = std::numeric_limits<_Word>::digits>
alpar@10
    92
    struct RandomTraits {};
alpar@10
    93
alpar@10
    94
    template <typename _Word>
alpar@10
    95
    struct RandomTraits<_Word, 32> {
alpar@10
    96
alpar@10
    97
      typedef _Word Word;
alpar@10
    98
      static const int bits = 32;
alpar@10
    99
alpar@10
   100
      static const int length = 624;
alpar@10
   101
      static const int shift = 397;
alpar@209
   102
alpar@10
   103
      static const Word mul = 0x6c078965u;
alpar@10
   104
      static const Word arrayInit = 0x012BD6AAu;
alpar@10
   105
      static const Word arrayMul1 = 0x0019660Du;
alpar@10
   106
      static const Word arrayMul2 = 0x5D588B65u;
alpar@10
   107
alpar@10
   108
      static const Word mask = 0x9908B0DFu;
alpar@10
   109
      static const Word loMask = (1u << 31) - 1;
alpar@10
   110
      static const Word hiMask = ~loMask;
alpar@10
   111
alpar@10
   112
alpar@10
   113
      static Word tempering(Word rnd) {
alpar@10
   114
        rnd ^= (rnd >> 11);
alpar@10
   115
        rnd ^= (rnd << 7) & 0x9D2C5680u;
alpar@10
   116
        rnd ^= (rnd << 15) & 0xEFC60000u;
alpar@10
   117
        rnd ^= (rnd >> 18);
alpar@10
   118
        return rnd;
alpar@10
   119
      }
alpar@10
   120
alpar@10
   121
    };
alpar@10
   122
alpar@10
   123
    template <typename _Word>
alpar@10
   124
    struct RandomTraits<_Word, 64> {
alpar@10
   125
alpar@10
   126
      typedef _Word Word;
alpar@10
   127
      static const int bits = 64;
alpar@10
   128
alpar@10
   129
      static const int length = 312;
alpar@10
   130
      static const int shift = 156;
alpar@10
   131
alpar@10
   132
      static const Word mul = Word(0x5851F42Du) << 32 | Word(0x4C957F2Du);
alpar@10
   133
      static const Word arrayInit = Word(0x00000000u) << 32 |Word(0x012BD6AAu);
alpar@10
   134
      static const Word arrayMul1 = Word(0x369DEA0Fu) << 32 |Word(0x31A53F85u);
alpar@10
   135
      static const Word arrayMul2 = Word(0x27BB2EE6u) << 32 |Word(0x87B0B0FDu);
alpar@10
   136
alpar@10
   137
      static const Word mask = Word(0xB5026F5Au) << 32 | Word(0xA96619E9u);
alpar@10
   138
      static const Word loMask = (Word(1u) << 31) - 1;
alpar@10
   139
      static const Word hiMask = ~loMask;
alpar@10
   140
alpar@10
   141
      static Word tempering(Word rnd) {
alpar@10
   142
        rnd ^= (rnd >> 29) & (Word(0x55555555u) << 32 | Word(0x55555555u));
alpar@10
   143
        rnd ^= (rnd << 17) & (Word(0x71D67FFFu) << 32 | Word(0xEDA60000u));
alpar@10
   144
        rnd ^= (rnd << 37) & (Word(0xFFF7EEE0u) << 32 | Word(0x00000000u));
alpar@10
   145
        rnd ^= (rnd >> 43);
alpar@10
   146
        return rnd;
alpar@10
   147
      }
alpar@10
   148
alpar@10
   149
    };
alpar@10
   150
alpar@10
   151
    template <typename _Word>
alpar@10
   152
    class RandomCore {
alpar@10
   153
    public:
alpar@10
   154
alpar@10
   155
      typedef _Word Word;
alpar@10
   156
alpar@10
   157
    private:
alpar@10
   158
alpar@10
   159
      static const int bits = RandomTraits<Word>::bits;
alpar@10
   160
alpar@10
   161
      static const int length = RandomTraits<Word>::length;
alpar@10
   162
      static const int shift = RandomTraits<Word>::shift;
alpar@10
   163
alpar@10
   164
    public:
alpar@10
   165
alpar@10
   166
      void initState() {
alpar@10
   167
        static const Word seedArray[4] = {
alpar@10
   168
          0x12345u, 0x23456u, 0x34567u, 0x45678u
alpar@10
   169
        };
alpar@209
   170
alpar@10
   171
        initState(seedArray, seedArray + 4);
alpar@10
   172
      }
alpar@10
   173
alpar@10
   174
      void initState(Word seed) {
alpar@10
   175
alpar@10
   176
        static const Word mul = RandomTraits<Word>::mul;
alpar@10
   177
alpar@209
   178
        current = state;
alpar@10
   179
alpar@10
   180
        Word *curr = state + length - 1;
alpar@10
   181
        curr[0] = seed; --curr;
alpar@10
   182
        for (int i = 1; i < length; ++i) {
alpar@10
   183
          curr[0] = (mul * ( curr[1] ^ (curr[1] >> (bits - 2)) ) + i);
alpar@10
   184
          --curr;
alpar@10
   185
        }
alpar@10
   186
      }
alpar@10
   187
alpar@10
   188
      template <typename Iterator>
alpar@10
   189
      void initState(Iterator begin, Iterator end) {
alpar@10
   190
alpar@10
   191
        static const Word init = RandomTraits<Word>::arrayInit;
alpar@10
   192
        static const Word mul1 = RandomTraits<Word>::arrayMul1;
alpar@10
   193
        static const Word mul2 = RandomTraits<Word>::arrayMul2;
alpar@10
   194
alpar@10
   195
alpar@10
   196
        Word *curr = state + length - 1; --curr;
alpar@10
   197
        Iterator it = begin; int cnt = 0;
alpar@10
   198
        int num;
alpar@10
   199
alpar@10
   200
        initState(init);
alpar@10
   201
alpar@10
   202
        num = length > end - begin ? length : end - begin;
alpar@10
   203
        while (num--) {
alpar@209
   204
          curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul1))
alpar@10
   205
            + *it + cnt;
alpar@10
   206
          ++it; ++cnt;
alpar@10
   207
          if (it == end) {
alpar@10
   208
            it = begin; cnt = 0;
alpar@10
   209
          }
alpar@10
   210
          if (curr == state) {
alpar@10
   211
            curr = state + length - 1; curr[0] = state[0];
alpar@10
   212
          }
alpar@10
   213
          --curr;
alpar@10
   214
        }
alpar@10
   215
alpar@10
   216
        num = length - 1; cnt = length - (curr - state) - 1;
alpar@10
   217
        while (num--) {
alpar@10
   218
          curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul2))
alpar@10
   219
            - cnt;
alpar@10
   220
          --curr; ++cnt;
alpar@10
   221
          if (curr == state) {
alpar@10
   222
            curr = state + length - 1; curr[0] = state[0]; --curr;
alpar@10
   223
            cnt = 1;
alpar@10
   224
          }
alpar@10
   225
        }
alpar@209
   226
alpar@10
   227
        state[length - 1] = Word(1) << (bits - 1);
alpar@10
   228
      }
alpar@209
   229
alpar@10
   230
      void copyState(const RandomCore& other) {
alpar@10
   231
        std::copy(other.state, other.state + length, state);
alpar@10
   232
        current = state + (other.current - other.state);
alpar@10
   233
      }
alpar@10
   234
alpar@10
   235
      Word operator()() {
alpar@10
   236
        if (current == state) fillState();
alpar@10
   237
        --current;
alpar@10
   238
        Word rnd = *current;
alpar@10
   239
        return RandomTraits<Word>::tempering(rnd);
alpar@10
   240
      }
alpar@10
   241
alpar@10
   242
    private:
alpar@10
   243
alpar@209
   244
alpar@10
   245
      void fillState() {
alpar@10
   246
        static const Word mask[2] = { 0x0ul, RandomTraits<Word>::mask };
alpar@10
   247
        static const Word loMask = RandomTraits<Word>::loMask;
alpar@10
   248
        static const Word hiMask = RandomTraits<Word>::hiMask;
alpar@10
   249
alpar@209
   250
        current = state + length;
alpar@10
   251
alpar@10
   252
        register Word *curr = state + length - 1;
alpar@10
   253
        register long num;
alpar@209
   254
alpar@10
   255
        num = length - shift;
alpar@10
   256
        while (num--) {
alpar@10
   257
          curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^
alpar@10
   258
            curr[- shift] ^ mask[curr[-1] & 1ul];
alpar@10
   259
          --curr;
alpar@10
   260
        }
alpar@10
   261
        num = shift - 1;
alpar@10
   262
        while (num--) {
alpar@10
   263
          curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^
alpar@10
   264
            curr[length - shift] ^ mask[curr[-1] & 1ul];
alpar@10
   265
          --curr;
alpar@10
   266
        }
deba@62
   267
        state[0] = (((state[0] & hiMask) | (curr[length - 1] & loMask)) >> 1) ^
alpar@10
   268
          curr[length - shift] ^ mask[curr[length - 1] & 1ul];
alpar@10
   269
alpar@10
   270
      }
alpar@10
   271
alpar@209
   272
alpar@10
   273
      Word *current;
alpar@10
   274
      Word state[length];
alpar@209
   275
alpar@10
   276
    };
alpar@10
   277
alpar@10
   278
alpar@209
   279
    template <typename Result,
alpar@10
   280
              int shift = (std::numeric_limits<Result>::digits + 1) / 2>
alpar@10
   281
    struct Masker {
alpar@10
   282
      static Result mask(const Result& result) {
alpar@10
   283
        return Masker<Result, (shift + 1) / 2>::
alpar@10
   284
          mask(static_cast<Result>(result | (result >> shift)));
alpar@10
   285
      }
alpar@10
   286
    };
alpar@209
   287
alpar@10
   288
    template <typename Result>
alpar@10
   289
    struct Masker<Result, 1> {
alpar@10
   290
      static Result mask(const Result& result) {
alpar@10
   291
        return static_cast<Result>(result | (result >> 1));
alpar@10
   292
      }
alpar@10
   293
    };
alpar@10
   294
alpar@209
   295
    template <typename Result, typename Word,
alpar@209
   296
              int rest = std::numeric_limits<Result>::digits, int shift = 0,
alpar@10
   297
              bool last = rest <= std::numeric_limits<Word>::digits>
alpar@10
   298
    struct IntConversion {
alpar@10
   299
      static const int bits = std::numeric_limits<Word>::digits;
alpar@209
   300
alpar@10
   301
      static Result convert(RandomCore<Word>& rnd) {
alpar@10
   302
        return static_cast<Result>(rnd() >> (bits - rest)) << shift;
alpar@10
   303
      }
alpar@10
   304
alpar@209
   305
    };
alpar@209
   306
alpar@209
   307
    template <typename Result, typename Word, int rest, int shift>
alpar@10
   308
    struct IntConversion<Result, Word, rest, shift, false> {
alpar@10
   309
      static const int bits = std::numeric_limits<Word>::digits;
alpar@10
   310
alpar@10
   311
      static Result convert(RandomCore<Word>& rnd) {
alpar@209
   312
        return (static_cast<Result>(rnd()) << shift) |
alpar@10
   313
          IntConversion<Result, Word, rest - bits, shift + bits>::convert(rnd);
alpar@10
   314
      }
alpar@10
   315
    };
alpar@10
   316
alpar@10
   317
alpar@10
   318
    template <typename Result, typename Word,
alpar@209
   319
              bool one_word = (std::numeric_limits<Word>::digits <
alpar@209
   320
                               std::numeric_limits<Result>::digits) >
alpar@10
   321
    struct Mapping {
alpar@10
   322
      static Result map(RandomCore<Word>& rnd, const Result& bound) {
alpar@10
   323
        Word max = Word(bound - 1);
alpar@10
   324
        Result mask = Masker<Result>::mask(bound - 1);
alpar@10
   325
        Result num;
alpar@10
   326
        do {
alpar@209
   327
          num = IntConversion<Result, Word>::convert(rnd) & mask;
alpar@10
   328
        } while (num > max);
alpar@10
   329
        return num;
alpar@10
   330
      }
alpar@10
   331
    };
alpar@10
   332
alpar@10
   333
    template <typename Result, typename Word>
alpar@10
   334
    struct Mapping<Result, Word, false> {
alpar@10
   335
      static Result map(RandomCore<Word>& rnd, const Result& bound) {
alpar@10
   336
        Word max = Word(bound - 1);
alpar@10
   337
        Word mask = Masker<Word, (std::numeric_limits<Result>::digits + 1) / 2>
alpar@10
   338
          ::mask(max);
alpar@10
   339
        Word num;
alpar@10
   340
        do {
alpar@10
   341
          num = rnd() & mask;
alpar@10
   342
        } while (num > max);
alpar@10
   343
        return num;
alpar@10
   344
      }
alpar@10
   345
    };
alpar@10
   346
kpeter@498
   347
    template <typename Result, int exp>
alpar@10
   348
    struct ShiftMultiplier {
alpar@10
   349
      static const Result multiplier() {
alpar@10
   350
        Result res = ShiftMultiplier<Result, exp / 2>::multiplier();
alpar@10
   351
        res *= res;
alpar@10
   352
        if ((exp & 1) == 1) res *= static_cast<Result>(0.5);
alpar@209
   353
        return res;
alpar@10
   354
      }
alpar@10
   355
    };
alpar@10
   356
alpar@10
   357
    template <typename Result>
kpeter@498
   358
    struct ShiftMultiplier<Result, 0> {
alpar@10
   359
      static const Result multiplier() {
alpar@209
   360
        return static_cast<Result>(1.0);
alpar@10
   361
      }
alpar@10
   362
    };
alpar@10
   363
alpar@10
   364
    template <typename Result>
kpeter@498
   365
    struct ShiftMultiplier<Result, 20> {
alpar@10
   366
      static const Result multiplier() {
alpar@209
   367
        return static_cast<Result>(1.0/1048576.0);
alpar@10
   368
      }
alpar@10
   369
    };
alpar@209
   370
alpar@10
   371
    template <typename Result>
kpeter@498
   372
    struct ShiftMultiplier<Result, 32> {
alpar@10
   373
      static const Result multiplier() {
kpeter@498
   374
        return static_cast<Result>(1.0/4294967296.0);
alpar@10
   375
      }
alpar@10
   376
    };
alpar@10
   377
alpar@10
   378
    template <typename Result>
kpeter@498
   379
    struct ShiftMultiplier<Result, 53> {
alpar@10
   380
      static const Result multiplier() {
alpar@209
   381
        return static_cast<Result>(1.0/9007199254740992.0);
alpar@10
   382
      }
alpar@10
   383
    };
alpar@10
   384
alpar@10
   385
    template <typename Result>
kpeter@498
   386
    struct ShiftMultiplier<Result, 64> {
alpar@10
   387
      static const Result multiplier() {
alpar@209
   388
        return static_cast<Result>(1.0/18446744073709551616.0);
alpar@10
   389
      }
alpar@10
   390
    };
alpar@10
   391
alpar@10
   392
    template <typename Result, int exp>
alpar@10
   393
    struct Shifting {
alpar@10
   394
      static Result shift(const Result& result) {
alpar@10
   395
        return result * ShiftMultiplier<Result, exp>::multiplier();
alpar@10
   396
      }
alpar@10
   397
    };
alpar@10
   398
alpar@10
   399
    template <typename Result, typename Word,
alpar@209
   400
              int rest = std::numeric_limits<Result>::digits, int shift = 0,
alpar@10
   401
              bool last = rest <= std::numeric_limits<Word>::digits>
alpar@209
   402
    struct RealConversion{
alpar@10
   403
      static const int bits = std::numeric_limits<Word>::digits;
alpar@10
   404
alpar@10
   405
      static Result convert(RandomCore<Word>& rnd) {
kpeter@498
   406
        return Shifting<Result, shift + rest>::
alpar@10
   407
          shift(static_cast<Result>(rnd() >> (bits - rest)));
alpar@10
   408
      }
alpar@10
   409
    };
alpar@10
   410
alpar@10
   411
    template <typename Result, typename Word, int rest, int shift>
alpar@209
   412
    struct RealConversion<Result, Word, rest, shift, false> {
alpar@10
   413
      static const int bits = std::numeric_limits<Word>::digits;
alpar@10
   414
alpar@10
   415
      static Result convert(RandomCore<Word>& rnd) {
kpeter@498
   416
        return Shifting<Result, shift + bits>::
alpar@10
   417
          shift(static_cast<Result>(rnd())) +
alpar@10
   418
          RealConversion<Result, Word, rest-bits, shift + bits>::
alpar@10
   419
          convert(rnd);
alpar@10
   420
      }
alpar@10
   421
    };
alpar@10
   422
alpar@10
   423
    template <typename Result, typename Word>
alpar@10
   424
    struct Initializer {
alpar@10
   425
alpar@10
   426
      template <typename Iterator>
alpar@10
   427
      static void init(RandomCore<Word>& rnd, Iterator begin, Iterator end) {
alpar@10
   428
        std::vector<Word> ws;
alpar@10
   429
        for (Iterator it = begin; it != end; ++it) {
alpar@10
   430
          ws.push_back(Word(*it));
alpar@10
   431
        }
alpar@10
   432
        rnd.initState(ws.begin(), ws.end());
alpar@10
   433
      }
alpar@10
   434
alpar@10
   435
      static void init(RandomCore<Word>& rnd, Result seed) {
alpar@10
   436
        rnd.initState(seed);
alpar@10
   437
      }
alpar@10
   438
    };
alpar@10
   439
alpar@10
   440
    template <typename Word>
alpar@10
   441
    struct BoolConversion {
alpar@10
   442
      static bool convert(RandomCore<Word>& rnd) {
alpar@10
   443
        return (rnd() & 1) == 1;
alpar@10
   444
      }
alpar@10
   445
    };
alpar@10
   446
alpar@10
   447
    template <typename Word>
alpar@10
   448
    struct BoolProducer {
alpar@10
   449
      Word buffer;
alpar@10
   450
      int num;
alpar@209
   451
alpar@10
   452
      BoolProducer() : num(0) {}
alpar@10
   453
alpar@10
   454
      bool convert(RandomCore<Word>& rnd) {
alpar@10
   455
        if (num == 0) {
alpar@10
   456
          buffer = rnd();
alpar@10
   457
          num = RandomTraits<Word>::bits;
alpar@10
   458
        }
alpar@10
   459
        bool r = (buffer & 1);
alpar@10
   460
        buffer >>= 1;
alpar@10
   461
        --num;
alpar@10
   462
        return r;
alpar@10
   463
      }
alpar@10
   464
    };
alpar@10
   465
alpar@10
   466
  }
alpar@10
   467
alpar@10
   468
  /// \ingroup misc
alpar@10
   469
  ///
alpar@10
   470
  /// \brief Mersenne Twister random number generator
alpar@10
   471
  ///
alpar@10
   472
  /// The Mersenne Twister is a twisted generalized feedback
alpar@10
   473
  /// shift-register generator of Matsumoto and Nishimura. The period
alpar@10
   474
  /// of this generator is \f$ 2^{19937} - 1 \f$ and it is
alpar@10
   475
  /// equi-distributed in 623 dimensions for 32-bit numbers. The time
alpar@10
   476
  /// performance of this generator is comparable to the commonly used
alpar@10
   477
  /// generators.
alpar@10
   478
  ///
alpar@10
   479
  /// This implementation is specialized for both 32-bit and 64-bit
alpar@10
   480
  /// architectures. The generators differ sligthly in the
alpar@10
   481
  /// initialization and generation phase so they produce two
alpar@10
   482
  /// completly different sequences.
alpar@10
   483
  ///
alpar@10
   484
  /// The generator gives back random numbers of serveral types. To
alpar@10
   485
  /// get a random number from a range of a floating point type you
alpar@10
   486
  /// can use one form of the \c operator() or the \c real() member
alpar@10
   487
  /// function. If you want to get random number from the {0, 1, ...,
alpar@10
   488
  /// n-1} integer range use the \c operator[] or the \c integer()
alpar@10
   489
  /// method. And to get random number from the whole range of an
alpar@10
   490
  /// integer type you can use the argumentless \c integer() or \c
alpar@10
   491
  /// uinteger() functions. After all you can get random bool with
alpar@10
   492
  /// equal chance of true and false or given probability of true
alpar@10
   493
  /// result with the \c boolean() member functions.
alpar@10
   494
  ///
alpar@10
   495
  ///\code
alpar@10
   496
  /// // The commented code is identical to the other
alpar@10
   497
  /// double a = rnd();                     // [0.0, 1.0)
alpar@10
   498
  /// // double a = rnd.real();             // [0.0, 1.0)
alpar@10
   499
  /// double b = rnd(100.0);                // [0.0, 100.0)
alpar@10
   500
  /// // double b = rnd.real(100.0);        // [0.0, 100.0)
alpar@10
   501
  /// double c = rnd(1.0, 2.0);             // [1.0, 2.0)
alpar@10
   502
  /// // double c = rnd.real(1.0, 2.0);     // [1.0, 2.0)
alpar@10
   503
  /// int d = rnd[100000];                  // 0..99999
alpar@10
   504
  /// // int d = rnd.integer(100000);       // 0..99999
alpar@10
   505
  /// int e = rnd[6] + 1;                   // 1..6
alpar@10
   506
  /// // int e = rnd.integer(1, 1 + 6);     // 1..6
alpar@10
   507
  /// int b = rnd.uinteger<int>();          // 0 .. 2^31 - 1
alpar@10
   508
  /// int c = rnd.integer<int>();           // - 2^31 .. 2^31 - 1
alpar@10
   509
  /// bool g = rnd.boolean();               // P(g = true) = 0.5
alpar@10
   510
  /// bool h = rnd.boolean(0.8);            // P(h = true) = 0.8
alpar@10
   511
  ///\endcode
alpar@10
   512
  ///
kpeter@49
   513
  /// LEMON provides a global instance of the random number
alpar@10
   514
  /// generator which name is \ref lemon::rnd "rnd". Usually it is a
alpar@10
   515
  /// good programming convenience to use this global generator to get
alpar@10
   516
  /// random numbers.
alpar@10
   517
  class Random {
alpar@10
   518
  private:
alpar@10
   519
kpeter@16
   520
    // Architecture word
alpar@10
   521
    typedef unsigned long Word;
alpar@209
   522
alpar@10
   523
    _random_bits::RandomCore<Word> core;
alpar@10
   524
    _random_bits::BoolProducer<Word> bool_producer;
alpar@209
   525
alpar@10
   526
alpar@10
   527
  public:
alpar@10
   528
deba@177
   529
    ///\name Initialization
deba@177
   530
    ///
deba@177
   531
    /// @{
deba@177
   532
kpeter@49
   533
    /// \brief Default constructor
alpar@10
   534
    ///
alpar@10
   535
    /// Constructor with constant seeding.
alpar@10
   536
    Random() { core.initState(); }
alpar@10
   537
kpeter@49
   538
    /// \brief Constructor with seed
alpar@10
   539
    ///
alpar@10
   540
    /// Constructor with seed. The current number type will be converted
alpar@10
   541
    /// to the architecture word type.
alpar@10
   542
    template <typename Number>
alpar@209
   543
    Random(Number seed) {
alpar@10
   544
      _random_bits::Initializer<Number, Word>::init(core, seed);
alpar@10
   545
    }
alpar@10
   546
kpeter@49
   547
    /// \brief Constructor with array seeding
alpar@10
   548
    ///
alpar@10
   549
    /// Constructor with array seeding. The given range should contain
alpar@10
   550
    /// any number type and the numbers will be converted to the
alpar@10
   551
    /// architecture word type.
alpar@10
   552
    template <typename Iterator>
alpar@209
   553
    Random(Iterator begin, Iterator end) {
alpar@10
   554
      typedef typename std::iterator_traits<Iterator>::value_type Number;
alpar@10
   555
      _random_bits::Initializer<Number, Word>::init(core, begin, end);
alpar@10
   556
    }
alpar@10
   557
alpar@10
   558
    /// \brief Copy constructor
alpar@10
   559
    ///
alpar@10
   560
    /// Copy constructor. The generated sequence will be identical to
alpar@10
   561
    /// the other sequence. It can be used to save the current state
alpar@10
   562
    /// of the generator and later use it to generate the same
alpar@10
   563
    /// sequence.
alpar@10
   564
    Random(const Random& other) {
alpar@10
   565
      core.copyState(other.core);
alpar@10
   566
    }
alpar@10
   567
alpar@10
   568
    /// \brief Assign operator
alpar@10
   569
    ///
alpar@10
   570
    /// Assign operator. The generated sequence will be identical to
alpar@10
   571
    /// the other sequence. It can be used to save the current state
alpar@10
   572
    /// of the generator and later use it to generate the same
alpar@10
   573
    /// sequence.
alpar@10
   574
    Random& operator=(const Random& other) {
alpar@10
   575
      if (&other != this) {
alpar@10
   576
        core.copyState(other.core);
alpar@10
   577
      }
alpar@10
   578
      return *this;
alpar@10
   579
    }
alpar@10
   580
deba@102
   581
    /// \brief Seeding random sequence
deba@102
   582
    ///
deba@102
   583
    /// Seeding the random sequence. The current number type will be
deba@102
   584
    /// converted to the architecture word type.
deba@102
   585
    template <typename Number>
alpar@209
   586
    void seed(Number seed) {
deba@102
   587
      _random_bits::Initializer<Number, Word>::init(core, seed);
deba@102
   588
    }
deba@102
   589
deba@102
   590
    /// \brief Seeding random sequence
deba@102
   591
    ///
deba@102
   592
    /// Seeding the random sequence. The given range should contain
deba@102
   593
    /// any number type and the numbers will be converted to the
deba@102
   594
    /// architecture word type.
deba@102
   595
    template <typename Iterator>
alpar@209
   596
    void seed(Iterator begin, Iterator end) {
deba@102
   597
      typedef typename std::iterator_traits<Iterator>::value_type Number;
deba@102
   598
      _random_bits::Initializer<Number, Word>::init(core, begin, end);
deba@102
   599
    }
deba@102
   600
deba@177
   601
    /// \brief Seeding from file or from process id and time
deba@177
   602
    ///
deba@177
   603
    /// By default, this function calls the \c seedFromFile() member
alpar@178
   604
    /// function with the <tt>/dev/urandom</tt> file. If it does not success,
deba@177
   605
    /// it uses the \c seedFromTime().
deba@177
   606
    /// \return Currently always true.
deba@177
   607
    bool seed() {
deba@177
   608
#ifndef WIN32
deba@177
   609
      if (seedFromFile("/dev/urandom", 0)) return true;
deba@177
   610
#endif
deba@177
   611
      if (seedFromTime()) return true;
deba@177
   612
      return false;
deba@177
   613
    }
alpar@209
   614
deba@177
   615
    /// \brief Seeding from file
deba@177
   616
    ///
deba@177
   617
    /// Seeding the random sequence from file. The linux kernel has two
deba@177
   618
    /// devices, <tt>/dev/random</tt> and <tt>/dev/urandom</tt> which
deba@177
   619
    /// could give good seed values for pseudo random generators (The
deba@177
   620
    /// difference between two devices is that the <tt>random</tt> may
deba@177
   621
    /// block the reading operation while the kernel can give good
deba@177
   622
    /// source of randomness, while the <tt>urandom</tt> does not
deba@177
   623
    /// block the input, but it could give back bytes with worse
deba@177
   624
    /// entropy).
deba@177
   625
    /// \param file The source file
deba@177
   626
    /// \param offset The offset, from the file read.
alpar@178
   627
    /// \return True when the seeding successes.
deba@177
   628
#ifndef WIN32
alpar@209
   629
    bool seedFromFile(const std::string& file = "/dev/urandom", int offset = 0)
deba@177
   630
#else
alpar@209
   631
    bool seedFromFile(const std::string& file = "", int offset = 0)
deba@177
   632
#endif
deba@177
   633
    {
deba@177
   634
      std::ifstream rs(file.c_str());
deba@177
   635
      const int size = 4;
deba@177
   636
      Word buf[size];
deba@177
   637
      if (offset != 0 && !rs.seekg(offset)) return false;
deba@177
   638
      if (!rs.read(reinterpret_cast<char*>(buf), sizeof(buf))) return false;
deba@177
   639
      seed(buf, buf + size);
deba@177
   640
      return true;
deba@177
   641
    }
deba@177
   642
deba@177
   643
    /// \brief Seding from process id and time
deba@177
   644
    ///
deba@177
   645
    /// Seding from process id and time. This function uses the
deba@177
   646
    /// current process id and the current time for initialize the
deba@177
   647
    /// random sequence.
deba@177
   648
    /// \return Currently always true.
alpar@209
   649
    bool seedFromTime() {
deba@177
   650
#ifndef WIN32
deba@177
   651
      timeval tv;
deba@177
   652
      gettimeofday(&tv, 0);
deba@177
   653
      seed(getpid() + tv.tv_sec + tv.tv_usec);
deba@177
   654
#else
alpar@491
   655
      seed(bits::getWinRndSeed());
deba@177
   656
#endif
deba@177
   657
      return true;
deba@177
   658
    }
deba@177
   659
deba@177
   660
    /// @}
deba@177
   661
deba@177
   662
    ///\name Uniform distributions
deba@177
   663
    ///
deba@177
   664
    /// @{
deba@177
   665
alpar@10
   666
    /// \brief Returns a random real number from the range [0, 1)
alpar@10
   667
    ///
alpar@10
   668
    /// It returns a random real number from the range [0, 1). The
kpeter@49
   669
    /// default Number type is \c double.
alpar@10
   670
    template <typename Number>
alpar@10
   671
    Number real() {
alpar@10
   672
      return _random_bits::RealConversion<Number, Word>::convert(core);
alpar@10
   673
    }
alpar@10
   674
alpar@10
   675
    double real() {
alpar@10
   676
      return real<double>();
alpar@10
   677
    }
alpar@10
   678
alpar@10
   679
    /// \brief Returns a random real number from the range [0, 1)
alpar@10
   680
    ///
alpar@10
   681
    /// It returns a random double from the range [0, 1).
alpar@10
   682
    double operator()() {
alpar@10
   683
      return real<double>();
alpar@10
   684
    }
alpar@10
   685
alpar@10
   686
    /// \brief Returns a random real number from the range [0, b)
alpar@10
   687
    ///
alpar@10
   688
    /// It returns a random real number from the range [0, b).
alpar@377
   689
    double operator()(double b) {
alpar@377
   690
      return real<double>() * b;
alpar@10
   691
    }
alpar@10
   692
alpar@10
   693
    /// \brief Returns a random real number from the range [a, b)
alpar@10
   694
    ///
alpar@10
   695
    /// It returns a random real number from the range [a, b).
alpar@377
   696
    double operator()(double a, double b) {
alpar@377
   697
      return real<double>() * (b - a) + a;
alpar@10
   698
    }
alpar@10
   699
alpar@10
   700
    /// \brief Returns a random integer from a range
alpar@10
   701
    ///
alpar@10
   702
    /// It returns a random integer from the range {0, 1, ..., b - 1}.
alpar@10
   703
    template <typename Number>
alpar@10
   704
    Number integer(Number b) {
alpar@10
   705
      return _random_bits::Mapping<Number, Word>::map(core, b);
alpar@10
   706
    }
alpar@10
   707
alpar@10
   708
    /// \brief Returns a random integer from a range
alpar@10
   709
    ///
alpar@10
   710
    /// It returns a random integer from the range {a, a + 1, ..., b - 1}.
alpar@10
   711
    template <typename Number>
alpar@10
   712
    Number integer(Number a, Number b) {
alpar@10
   713
      return _random_bits::Mapping<Number, Word>::map(core, b - a) + a;
alpar@10
   714
    }
alpar@10
   715
alpar@10
   716
    /// \brief Returns a random integer from a range
alpar@10
   717
    ///
alpar@10
   718
    /// It returns a random integer from the range {0, 1, ..., b - 1}.
alpar@10
   719
    template <typename Number>
alpar@10
   720
    Number operator[](Number b) {
alpar@10
   721
      return _random_bits::Mapping<Number, Word>::map(core, b);
alpar@10
   722
    }
alpar@10
   723
alpar@10
   724
    /// \brief Returns a random non-negative integer
alpar@10
   725
    ///
alpar@10
   726
    /// It returns a random non-negative integer uniformly from the
kpeter@49
   727
    /// whole range of the current \c Number type. The default result
kpeter@49
   728
    /// type of this function is <tt>unsigned int</tt>.
alpar@10
   729
    template <typename Number>
alpar@10
   730
    Number uinteger() {
alpar@10
   731
      return _random_bits::IntConversion<Number, Word>::convert(core);
alpar@10
   732
    }
alpar@10
   733
alpar@10
   734
    unsigned int uinteger() {
alpar@10
   735
      return uinteger<unsigned int>();
alpar@10
   736
    }
alpar@10
   737
alpar@10
   738
    /// \brief Returns a random integer
alpar@10
   739
    ///
alpar@10
   740
    /// It returns a random integer uniformly from the whole range of
alpar@10
   741
    /// the current \c Number type. The default result type of this
kpeter@49
   742
    /// function is \c int.
alpar@10
   743
    template <typename Number>
alpar@10
   744
    Number integer() {
alpar@209
   745
      static const int nb = std::numeric_limits<Number>::digits +
alpar@10
   746
        (std::numeric_limits<Number>::is_signed ? 1 : 0);
alpar@10
   747
      return _random_bits::IntConversion<Number, Word, nb>::convert(core);
alpar@10
   748
    }
alpar@10
   749
alpar@10
   750
    int integer() {
alpar@10
   751
      return integer<int>();
alpar@10
   752
    }
alpar@209
   753
alpar@10
   754
    /// \brief Returns a random bool
alpar@10
   755
    ///
alpar@10
   756
    /// It returns a random bool. The generator holds a buffer for
alpar@10
   757
    /// random bits. Every time when it become empty the generator makes
alpar@10
   758
    /// a new random word and fill the buffer up.
alpar@10
   759
    bool boolean() {
alpar@10
   760
      return bool_producer.convert(core);
alpar@10
   761
    }
alpar@10
   762
deba@177
   763
    /// @}
deba@177
   764
kpeter@49
   765
    ///\name Non-uniform distributions
alpar@10
   766
    ///
alpar@10
   767
    ///@{
alpar@209
   768
kpeter@340
   769
    /// \brief Returns a random bool with given probability of true result.
alpar@10
   770
    ///
kpeter@23
   771
    /// It returns a random bool with given probability of true result.
alpar@10
   772
    bool boolean(double p) {
alpar@10
   773
      return operator()() < p;
alpar@10
   774
    }
alpar@10
   775
kpeter@340
   776
    /// Standard normal (Gauss) distribution
alpar@10
   777
kpeter@340
   778
    /// Standard normal (Gauss) distribution.
alpar@10
   779
    /// \note The Cartesian form of the Box-Muller
alpar@10
   780
    /// transformation is used to generate a random normal distribution.
alpar@209
   781
    double gauss()
alpar@10
   782
    {
alpar@10
   783
      double V1,V2,S;
alpar@10
   784
      do {
alpar@209
   785
        V1=2*real<double>()-1;
alpar@209
   786
        V2=2*real<double>()-1;
alpar@209
   787
        S=V1*V1+V2*V2;
alpar@10
   788
      } while(S>=1);
alpar@10
   789
      return std::sqrt(-2*std::log(S)/S)*V1;
alpar@10
   790
    }
kpeter@340
   791
    /// Normal (Gauss) distribution with given mean and standard deviation
alpar@10
   792
kpeter@340
   793
    /// Normal (Gauss) distribution with given mean and standard deviation.
alpar@10
   794
    /// \sa gauss()
alpar@10
   795
    double gauss(double mean,double std_dev)
alpar@10
   796
    {
alpar@10
   797
      return gauss()*std_dev+mean;
alpar@10
   798
    }
alpar@10
   799
alpar@339
   800
    /// Lognormal distribution
alpar@339
   801
alpar@339
   802
    /// Lognormal distribution. The parameters are the mean and the standard
alpar@339
   803
    /// deviation of <tt>exp(X)</tt>.
alpar@339
   804
    ///
alpar@339
   805
    double lognormal(double n_mean,double n_std_dev)
alpar@339
   806
    {
alpar@339
   807
      return std::exp(gauss(n_mean,n_std_dev));
alpar@339
   808
    }
alpar@339
   809
    /// Lognormal distribution
alpar@339
   810
alpar@339
   811
    /// Lognormal distribution. The parameter is an <tt>std::pair</tt> of
alpar@339
   812
    /// the mean and the standard deviation of <tt>exp(X)</tt>.
alpar@339
   813
    ///
alpar@339
   814
    double lognormal(const std::pair<double,double> &params)
alpar@339
   815
    {
alpar@339
   816
      return std::exp(gauss(params.first,params.second));
alpar@339
   817
    }
alpar@339
   818
    /// Compute the lognormal parameters from mean and standard deviation
alpar@339
   819
alpar@339
   820
    /// This function computes the lognormal parameters from mean and
alpar@339
   821
    /// standard deviation. The return value can direcly be passed to
alpar@339
   822
    /// lognormal().
alpar@339
   823
    std::pair<double,double> lognormalParamsFromMD(double mean,
kpeter@340
   824
                                                   double std_dev)
alpar@339
   825
    {
alpar@339
   826
      double fr=std_dev/mean;
alpar@339
   827
      fr*=fr;
alpar@339
   828
      double lg=std::log(1+fr);
alpar@339
   829
      return std::pair<double,double>(std::log(mean)-lg/2.0,std::sqrt(lg));
alpar@339
   830
    }
alpar@339
   831
    /// Lognormal distribution with given mean and standard deviation
kpeter@340
   832
alpar@339
   833
    /// Lognormal distribution with given mean and standard deviation.
alpar@339
   834
    ///
alpar@339
   835
    double lognormalMD(double mean,double std_dev)
alpar@339
   836
    {
alpar@339
   837
      return lognormal(lognormalParamsFromMD(mean,std_dev));
alpar@339
   838
    }
kpeter@340
   839
alpar@10
   840
    /// Exponential distribution with given mean
alpar@10
   841
alpar@10
   842
    /// This function generates an exponential distribution random number
alpar@10
   843
    /// with mean <tt>1/lambda</tt>.
alpar@10
   844
    ///
alpar@10
   845
    double exponential(double lambda=1.0)
alpar@10
   846
    {
alpar@11
   847
      return -std::log(1.0-real<double>())/lambda;
alpar@10
   848
    }
alpar@10
   849
alpar@10
   850
    /// Gamma distribution with given integer shape
alpar@10
   851
alpar@10
   852
    /// This function generates a gamma distribution random number.
alpar@209
   853
    ///
alpar@10
   854
    ///\param k shape parameter (<tt>k>0</tt> integer)
alpar@209
   855
    double gamma(int k)
alpar@10
   856
    {
alpar@10
   857
      double s = 0;
alpar@10
   858
      for(int i=0;i<k;i++) s-=std::log(1.0-real<double>());
alpar@10
   859
      return s;
alpar@10
   860
    }
alpar@209
   861
alpar@10
   862
    /// Gamma distribution with given shape and scale parameter
alpar@10
   863
alpar@10
   864
    /// This function generates a gamma distribution random number.
alpar@209
   865
    ///
alpar@10
   866
    ///\param k shape parameter (<tt>k>0</tt>)
alpar@10
   867
    ///\param theta scale parameter
alpar@10
   868
    ///
alpar@10
   869
    double gamma(double k,double theta=1.0)
alpar@10
   870
    {
alpar@10
   871
      double xi,nu;
alpar@10
   872
      const double delta = k-std::floor(k);
alpar@68
   873
      const double v0=E/(E-delta);
alpar@10
   874
      do {
alpar@209
   875
        double V0=1.0-real<double>();
alpar@209
   876
        double V1=1.0-real<double>();
alpar@209
   877
        double V2=1.0-real<double>();
alpar@209
   878
        if(V2<=v0)
alpar@209
   879
          {
alpar@209
   880
            xi=std::pow(V1,1.0/delta);
alpar@209
   881
            nu=V0*std::pow(xi,delta-1.0);
alpar@209
   882
          }
alpar@209
   883
        else
alpar@209
   884
          {
alpar@209
   885
            xi=1.0-std::log(V1);
alpar@209
   886
            nu=V0*std::exp(-xi);
alpar@209
   887
          }
alpar@10
   888
      } while(nu>std::pow(xi,delta-1.0)*std::exp(-xi));
alpar@116
   889
      return theta*(xi+gamma(int(std::floor(k))));
alpar@10
   890
    }
alpar@209
   891
alpar@11
   892
    /// Weibull distribution
alpar@11
   893
alpar@11
   894
    /// This function generates a Weibull distribution random number.
alpar@209
   895
    ///
alpar@11
   896
    ///\param k shape parameter (<tt>k>0</tt>)
alpar@11
   897
    ///\param lambda scale parameter (<tt>lambda>0</tt>)
alpar@11
   898
    ///
alpar@11
   899
    double weibull(double k,double lambda)
alpar@11
   900
    {
alpar@11
   901
      return lambda*pow(-std::log(1.0-real<double>()),1.0/k);
alpar@209
   902
    }
alpar@209
   903
alpar@11
   904
    /// Pareto distribution
alpar@11
   905
alpar@11
   906
    /// This function generates a Pareto distribution random number.
alpar@209
   907
    ///
alpar@12
   908
    ///\param k shape parameter (<tt>k>0</tt>)
alpar@11
   909
    ///\param x_min location parameter (<tt>x_min>0</tt>)
alpar@11
   910
    ///
alpar@12
   911
    double pareto(double k,double x_min)
alpar@11
   912
    {
alpar@116
   913
      return exponential(gamma(k,1.0/x_min))+x_min;
alpar@209
   914
    }
alpar@209
   915
alpar@92
   916
    /// Poisson distribution
alpar@92
   917
alpar@92
   918
    /// This function generates a Poisson distribution random number with
alpar@92
   919
    /// parameter \c lambda.
alpar@209
   920
    ///
alpar@92
   921
    /// The probability mass function of this distribusion is
alpar@92
   922
    /// \f[ \frac{e^{-\lambda}\lambda^k}{k!} \f]
alpar@92
   923
    /// \note The algorithm is taken from the book of Donald E. Knuth titled
alpar@92
   924
    /// ''Seminumerical Algorithms'' (1969). Its running time is linear in the
alpar@92
   925
    /// return value.
alpar@209
   926
alpar@92
   927
    int poisson(double lambda)
alpar@92
   928
    {
alpar@92
   929
      const double l = std::exp(-lambda);
alpar@92
   930
      int k=0;
alpar@92
   931
      double p = 1.0;
alpar@92
   932
      do {
alpar@209
   933
        k++;
alpar@209
   934
        p*=real<double>();
alpar@92
   935
      } while (p>=l);
alpar@92
   936
      return k-1;
alpar@209
   937
    }
alpar@209
   938
alpar@10
   939
    ///@}
alpar@209
   940
alpar@10
   941
    ///\name Two dimensional distributions
alpar@10
   942
    ///
alpar@10
   943
    ///@{
alpar@209
   944
kpeter@23
   945
    /// Uniform distribution on the full unit circle
kpeter@16
   946
kpeter@16
   947
    /// Uniform distribution on the full unit circle.
kpeter@16
   948
    ///
alpar@209
   949
    dim2::Point<double> disc()
alpar@10
   950
    {
alpar@10
   951
      double V1,V2;
alpar@10
   952
      do {
alpar@209
   953
        V1=2*real<double>()-1;
alpar@209
   954
        V2=2*real<double>()-1;
alpar@209
   955
alpar@10
   956
      } while(V1*V1+V2*V2>=1);
alpar@10
   957
      return dim2::Point<double>(V1,V2);
alpar@10
   958
    }
kpeter@340
   959
    /// A kind of two dimensional normal (Gauss) distribution
alpar@10
   960
alpar@10
   961
    /// This function provides a turning symmetric two-dimensional distribution.
alpar@10
   962
    /// Both coordinates are of standard normal distribution, but they are not
alpar@10
   963
    /// independent.
alpar@10
   964
    ///
alpar@10
   965
    /// \note The coordinates are the two random variables provided by
alpar@10
   966
    /// the Box-Muller method.
alpar@10
   967
    dim2::Point<double> gauss2()
alpar@10
   968
    {
alpar@10
   969
      double V1,V2,S;
alpar@10
   970
      do {
alpar@209
   971
        V1=2*real<double>()-1;
alpar@209
   972
        V2=2*real<double>()-1;
alpar@209
   973
        S=V1*V1+V2*V2;
alpar@10
   974
      } while(S>=1);
alpar@10
   975
      double W=std::sqrt(-2*std::log(S)/S);
alpar@10
   976
      return dim2::Point<double>(W*V1,W*V2);
alpar@10
   977
    }
alpar@10
   978
    /// A kind of two dimensional exponential distribution
alpar@10
   979
alpar@10
   980
    /// This function provides a turning symmetric two-dimensional distribution.
alpar@10
   981
    /// The x-coordinate is of conditionally exponential distribution
alpar@209
   982
    /// with the condition that x is positive and y=0. If x is negative and
alpar@10
   983
    /// y=0 then, -x is of exponential distribution. The same is true for the
alpar@10
   984
    /// y-coordinate.
alpar@209
   985
    dim2::Point<double> exponential2()
alpar@10
   986
    {
alpar@10
   987
      double V1,V2,S;
alpar@10
   988
      do {
alpar@209
   989
        V1=2*real<double>()-1;
alpar@209
   990
        V2=2*real<double>()-1;
alpar@209
   991
        S=V1*V1+V2*V2;
alpar@10
   992
      } while(S>=1);
alpar@10
   993
      double W=-std::log(S)/S;
alpar@10
   994
      return dim2::Point<double>(W*V1,W*V2);
alpar@10
   995
    }
alpar@10
   996
alpar@209
   997
    ///@}
alpar@10
   998
  };
alpar@10
   999
alpar@10
  1000
alpar@10
  1001
  extern Random rnd;
alpar@10
  1002
alpar@10
  1003
}
alpar@10
  1004
alpar@10
  1005
#endif