gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Minor doc improvements
0 1 0
default
1 file changed with 9 insertions and 23 deletions:
↑ Collapse diff ↑
Ignore white space 3072 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2008
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
/*
20 20
 * This file contains the reimplemented version of the Mersenne Twister
21 21
 * Generator of Matsumoto and Nishimura.
22 22
 *
23 23
 * See the appropriate copyright notice below.
24 24
 *
25 25
 * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
26 26
 * All rights reserved.
27 27
 *
28 28
 * Redistribution and use in source and binary forms, with or without
29 29
 * modification, are permitted provided that the following conditions
30 30
 * are met:
31 31
 *
32 32
 * 1. Redistributions of source code must retain the above copyright
33 33
 *    notice, this list of conditions and the following disclaimer.
34 34
 *
35 35
 * 2. Redistributions in binary form must reproduce the above copyright
36 36
 *    notice, this list of conditions and the following disclaimer in the
37 37
 *    documentation and/or other materials provided with the distribution.
38 38
 *
39 39
 * 3. The names of its contributors may not be used to endorse or promote
40 40
 *    products derived from this software without specific prior written
41 41
 *    permission.
42 42
 *
43 43
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 44
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 45
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
46 46
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
47 47
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
48 48
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
49 49
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
50 50
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 51
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
52 52
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53 53
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
54 54
 * OF THE POSSIBILITY OF SUCH DAMAGE.
55 55
 *
56 56
 *
57 57
 * Any feedback is very welcome.
58 58
 * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
59 59
 * email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
60 60
 */
61 61

	
62 62
#ifndef LEMON_RANDOM_H
63 63
#define LEMON_RANDOM_H
64 64

	
65 65
#include <algorithm>
66 66
#include <iterator>
67 67
#include <vector>
68 68
#include <limits>
69 69
#include <fstream>
70 70

	
71 71
#include <lemon/math.h>
72 72
#include <lemon/dim2.h>
73 73

	
74 74
#ifndef WIN32
75 75
#include <sys/time.h>
76 76
#include <ctime>
77 77
#include <sys/types.h>
78 78
#include <unistd.h>
79 79
#else
80 80
#include <windows.h>
81 81
#endif
82 82

	
83 83
///\ingroup misc
84 84
///\file
85 85
///\brief Mersenne Twister random number generator
86 86

	
87 87
namespace lemon {
88 88

	
89 89
  namespace _random_bits {
90 90

	
91 91
    template <typename _Word, int _bits = std::numeric_limits<_Word>::digits>
92 92
    struct RandomTraits {};
93 93

	
94 94
    template <typename _Word>
95 95
    struct RandomTraits<_Word, 32> {
96 96

	
97 97
      typedef _Word Word;
98 98
      static const int bits = 32;
99 99

	
100 100
      static const int length = 624;
101 101
      static const int shift = 397;
102 102

	
103 103
      static const Word mul = 0x6c078965u;
104 104
      static const Word arrayInit = 0x012BD6AAu;
105 105
      static const Word arrayMul1 = 0x0019660Du;
106 106
      static const Word arrayMul2 = 0x5D588B65u;
107 107

	
108 108
      static const Word mask = 0x9908B0DFu;
109 109
      static const Word loMask = (1u << 31) - 1;
110 110
      static const Word hiMask = ~loMask;
111 111

	
112 112

	
113 113
      static Word tempering(Word rnd) {
114 114
        rnd ^= (rnd >> 11);
115 115
        rnd ^= (rnd << 7) & 0x9D2C5680u;
116 116
        rnd ^= (rnd << 15) & 0xEFC60000u;
117 117
        rnd ^= (rnd >> 18);
118 118
        return rnd;
119 119
      }
120 120

	
121 121
    };
122 122

	
123 123
    template <typename _Word>
124 124
    struct RandomTraits<_Word, 64> {
125 125

	
126 126
      typedef _Word Word;
127 127
      static const int bits = 64;
128 128

	
129 129
      static const int length = 312;
130 130
      static const int shift = 156;
131 131

	
132 132
      static const Word mul = Word(0x5851F42Du) << 32 | Word(0x4C957F2Du);
133 133
      static const Word arrayInit = Word(0x00000000u) << 32 |Word(0x012BD6AAu);
134 134
      static const Word arrayMul1 = Word(0x369DEA0Fu) << 32 |Word(0x31A53F85u);
135 135
      static const Word arrayMul2 = Word(0x27BB2EE6u) << 32 |Word(0x87B0B0FDu);
136 136

	
137 137
      static const Word mask = Word(0xB5026F5Au) << 32 | Word(0xA96619E9u);
138 138
      static const Word loMask = (Word(1u) << 31) - 1;
139 139
      static const Word hiMask = ~loMask;
140 140

	
141 141
      static Word tempering(Word rnd) {
142 142
        rnd ^= (rnd >> 29) & (Word(0x55555555u) << 32 | Word(0x55555555u));
143 143
        rnd ^= (rnd << 17) & (Word(0x71D67FFFu) << 32 | Word(0xEDA60000u));
144 144
        rnd ^= (rnd << 37) & (Word(0xFFF7EEE0u) << 32 | Word(0x00000000u));
145 145
        rnd ^= (rnd >> 43);
146 146
        return rnd;
147 147
      }
148 148

	
149 149
    };
150 150

	
151 151
    template <typename _Word>
152 152
    class RandomCore {
153 153
    public:
154 154

	
155 155
      typedef _Word Word;
156 156

	
157 157
    private:
158 158

	
159 159
      static const int bits = RandomTraits<Word>::bits;
160 160

	
161 161
      static const int length = RandomTraits<Word>::length;
162 162
      static const int shift = RandomTraits<Word>::shift;
163 163

	
164 164
    public:
165 165

	
166 166
      void initState() {
167 167
        static const Word seedArray[4] = {
168 168
          0x12345u, 0x23456u, 0x34567u, 0x45678u
169 169
        };
170 170

	
171 171
        initState(seedArray, seedArray + 4);
172 172
      }
173 173

	
174 174
      void initState(Word seed) {
175 175

	
176 176
        static const Word mul = RandomTraits<Word>::mul;
177 177

	
178 178
        current = state;
179 179

	
180 180
        Word *curr = state + length - 1;
181 181
        curr[0] = seed; --curr;
182 182
        for (int i = 1; i < length; ++i) {
183 183
          curr[0] = (mul * ( curr[1] ^ (curr[1] >> (bits - 2)) ) + i);
184 184
          --curr;
185 185
        }
186 186
      }
187 187

	
188 188
      template <typename Iterator>
189 189
      void initState(Iterator begin, Iterator end) {
190 190

	
191 191
        static const Word init = RandomTraits<Word>::arrayInit;
192 192
        static const Word mul1 = RandomTraits<Word>::arrayMul1;
193 193
        static const Word mul2 = RandomTraits<Word>::arrayMul2;
194 194

	
195 195

	
196 196
        Word *curr = state + length - 1; --curr;
197 197
        Iterator it = begin; int cnt = 0;
198 198
        int num;
199 199

	
200 200
        initState(init);
201 201

	
202 202
        num = length > end - begin ? length : end - begin;
203 203
        while (num--) {
204 204
          curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul1))
205 205
            + *it + cnt;
206 206
          ++it; ++cnt;
207 207
          if (it == end) {
208 208
            it = begin; cnt = 0;
209 209
          }
210 210
          if (curr == state) {
211 211
            curr = state + length - 1; curr[0] = state[0];
212 212
          }
213 213
          --curr;
214 214
        }
215 215

	
216 216
        num = length - 1; cnt = length - (curr - state) - 1;
217 217
        while (num--) {
218 218
          curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul2))
219 219
            - cnt;
220 220
          --curr; ++cnt;
221 221
          if (curr == state) {
222 222
            curr = state + length - 1; curr[0] = state[0]; --curr;
223 223
            cnt = 1;
224 224
          }
225 225
        }
226 226

	
227 227
        state[length - 1] = Word(1) << (bits - 1);
228 228
      }
229 229

	
230 230
      void copyState(const RandomCore& other) {
231 231
        std::copy(other.state, other.state + length, state);
232 232
        current = state + (other.current - other.state);
233 233
      }
234 234

	
235 235
      Word operator()() {
236 236
        if (current == state) fillState();
237 237
        --current;
238 238
        Word rnd = *current;
239 239
        return RandomTraits<Word>::tempering(rnd);
240 240
      }
241 241

	
242 242
    private:
243 243

	
244 244

	
245 245
      void fillState() {
246 246
        static const Word mask[2] = { 0x0ul, RandomTraits<Word>::mask };
247 247
        static const Word loMask = RandomTraits<Word>::loMask;
248 248
        static const Word hiMask = RandomTraits<Word>::hiMask;
249 249

	
250 250
        current = state + length;
251 251

	
252 252
        register Word *curr = state + length - 1;
253 253
        register long num;
254 254

	
255 255
        num = length - shift;
256 256
        while (num--) {
257 257
          curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^
258 258
            curr[- shift] ^ mask[curr[-1] & 1ul];
259 259
          --curr;
260 260
        }
261 261
        num = shift - 1;
262 262
        while (num--) {
263 263
          curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^
264 264
            curr[length - shift] ^ mask[curr[-1] & 1ul];
265 265
          --curr;
266 266
        }
267 267
        state[0] = (((state[0] & hiMask) | (curr[length - 1] & loMask)) >> 1) ^
268 268
          curr[length - shift] ^ mask[curr[length - 1] & 1ul];
269 269

	
270 270
      }
271 271

	
272 272

	
273 273
      Word *current;
274 274
      Word state[length];
275 275

	
276 276
    };
277 277

	
278 278

	
279 279
    template <typename Result,
280 280
              int shift = (std::numeric_limits<Result>::digits + 1) / 2>
281 281
    struct Masker {
282 282
      static Result mask(const Result& result) {
283 283
        return Masker<Result, (shift + 1) / 2>::
284 284
          mask(static_cast<Result>(result | (result >> shift)));
285 285
      }
286 286
    };
287 287

	
288 288
    template <typename Result>
289 289
    struct Masker<Result, 1> {
290 290
      static Result mask(const Result& result) {
291 291
        return static_cast<Result>(result | (result >> 1));
292 292
      }
293 293
    };
294 294

	
295 295
    template <typename Result, typename Word,
296 296
              int rest = std::numeric_limits<Result>::digits, int shift = 0,
297 297
              bool last = rest <= std::numeric_limits<Word>::digits>
298 298
    struct IntConversion {
299 299
      static const int bits = std::numeric_limits<Word>::digits;
300 300

	
301 301
      static Result convert(RandomCore<Word>& rnd) {
302 302
        return static_cast<Result>(rnd() >> (bits - rest)) << shift;
303 303
      }
304 304

	
305 305
    };
306 306

	
307 307
    template <typename Result, typename Word, int rest, int shift>
308 308
    struct IntConversion<Result, Word, rest, shift, false> {
309 309
      static const int bits = std::numeric_limits<Word>::digits;
310 310

	
311 311
      static Result convert(RandomCore<Word>& rnd) {
312 312
        return (static_cast<Result>(rnd()) << shift) |
313 313
          IntConversion<Result, Word, rest - bits, shift + bits>::convert(rnd);
314 314
      }
315 315
    };
316 316

	
317 317

	
318 318
    template <typename Result, typename Word,
319 319
              bool one_word = (std::numeric_limits<Word>::digits <
320 320
                               std::numeric_limits<Result>::digits) >
321 321
    struct Mapping {
322 322
      static Result map(RandomCore<Word>& rnd, const Result& bound) {
323 323
        Word max = Word(bound - 1);
324 324
        Result mask = Masker<Result>::mask(bound - 1);
325 325
        Result num;
326 326
        do {
327 327
          num = IntConversion<Result, Word>::convert(rnd) & mask;
328 328
        } while (num > max);
329 329
        return num;
330 330
      }
331 331
    };
332 332

	
333 333
    template <typename Result, typename Word>
334 334
    struct Mapping<Result, Word, false> {
335 335
      static Result map(RandomCore<Word>& rnd, const Result& bound) {
336 336
        Word max = Word(bound - 1);
337 337
        Word mask = Masker<Word, (std::numeric_limits<Result>::digits + 1) / 2>
338 338
          ::mask(max);
339 339
        Word num;
340 340
        do {
341 341
          num = rnd() & mask;
342 342
        } while (num > max);
343 343
        return num;
344 344
      }
345 345
    };
346 346

	
347 347
    template <typename Result, int exp, bool pos = (exp >= 0)>
348 348
    struct ShiftMultiplier {
349 349
      static const Result multiplier() {
350 350
        Result res = ShiftMultiplier<Result, exp / 2>::multiplier();
351 351
        res *= res;
352 352
        if ((exp & 1) == 1) res *= static_cast<Result>(2.0);
353 353
        return res;
354 354
      }
355 355
    };
356 356

	
357 357
    template <typename Result, int exp>
358 358
    struct ShiftMultiplier<Result, exp, false> {
359 359
      static const Result multiplier() {
360 360
        Result res = ShiftMultiplier<Result, exp / 2>::multiplier();
361 361
        res *= res;
362 362
        if ((exp & 1) == 1) res *= static_cast<Result>(0.5);
363 363
        return res;
364 364
      }
365 365
    };
366 366

	
367 367
    template <typename Result>
368 368
    struct ShiftMultiplier<Result, 0, true> {
369 369
      static const Result multiplier() {
370 370
        return static_cast<Result>(1.0);
371 371
      }
372 372
    };
373 373

	
374 374
    template <typename Result>
375 375
    struct ShiftMultiplier<Result, -20, true> {
376 376
      static const Result multiplier() {
377 377
        return static_cast<Result>(1.0/1048576.0);
378 378
      }
379 379
    };
380 380

	
381 381
    template <typename Result>
382 382
    struct ShiftMultiplier<Result, -32, true> {
383 383
      static const Result multiplier() {
384 384
        return static_cast<Result>(1.0/424967296.0);
385 385
      }
386 386
    };
387 387

	
388 388
    template <typename Result>
389 389
    struct ShiftMultiplier<Result, -53, true> {
390 390
      static const Result multiplier() {
391 391
        return static_cast<Result>(1.0/9007199254740992.0);
392 392
      }
393 393
    };
394 394

	
395 395
    template <typename Result>
396 396
    struct ShiftMultiplier<Result, -64, true> {
397 397
      static const Result multiplier() {
398 398
        return static_cast<Result>(1.0/18446744073709551616.0);
399 399
      }
400 400
    };
401 401

	
402 402
    template <typename Result, int exp>
403 403
    struct Shifting {
404 404
      static Result shift(const Result& result) {
405 405
        return result * ShiftMultiplier<Result, exp>::multiplier();
406 406
      }
407 407
    };
408 408

	
409 409
    template <typename Result, typename Word,
410 410
              int rest = std::numeric_limits<Result>::digits, int shift = 0,
411 411
              bool last = rest <= std::numeric_limits<Word>::digits>
412 412
    struct RealConversion{
413 413
      static const int bits = std::numeric_limits<Word>::digits;
414 414

	
415 415
      static Result convert(RandomCore<Word>& rnd) {
416 416
        return Shifting<Result, - shift - rest>::
417 417
          shift(static_cast<Result>(rnd() >> (bits - rest)));
418 418
      }
419 419
    };
420 420

	
421 421
    template <typename Result, typename Word, int rest, int shift>
422 422
    struct RealConversion<Result, Word, rest, shift, false> {
423 423
      static const int bits = std::numeric_limits<Word>::digits;
424 424

	
425 425
      static Result convert(RandomCore<Word>& rnd) {
426 426
        return Shifting<Result, - shift - bits>::
427 427
          shift(static_cast<Result>(rnd())) +
428 428
          RealConversion<Result, Word, rest-bits, shift + bits>::
429 429
          convert(rnd);
430 430
      }
431 431
    };
432 432

	
433 433
    template <typename Result, typename Word>
434 434
    struct Initializer {
435 435

	
436 436
      template <typename Iterator>
437 437
      static void init(RandomCore<Word>& rnd, Iterator begin, Iterator end) {
438 438
        std::vector<Word> ws;
439 439
        for (Iterator it = begin; it != end; ++it) {
440 440
          ws.push_back(Word(*it));
441 441
        }
442 442
        rnd.initState(ws.begin(), ws.end());
443 443
      }
444 444

	
445 445
      static void init(RandomCore<Word>& rnd, Result seed) {
446 446
        rnd.initState(seed);
447 447
      }
448 448
    };
449 449

	
450 450
    template <typename Word>
451 451
    struct BoolConversion {
452 452
      static bool convert(RandomCore<Word>& rnd) {
453 453
        return (rnd() & 1) == 1;
454 454
      }
455 455
    };
456 456

	
457 457
    template <typename Word>
458 458
    struct BoolProducer {
459 459
      Word buffer;
460 460
      int num;
461 461

	
462 462
      BoolProducer() : num(0) {}
463 463

	
464 464
      bool convert(RandomCore<Word>& rnd) {
465 465
        if (num == 0) {
466 466
          buffer = rnd();
467 467
          num = RandomTraits<Word>::bits;
468 468
        }
469 469
        bool r = (buffer & 1);
470 470
        buffer >>= 1;
471 471
        --num;
472 472
        return r;
473 473
      }
474 474
    };
475 475

	
476 476
  }
477 477

	
478 478
  /// \ingroup misc
479 479
  ///
480 480
  /// \brief Mersenne Twister random number generator
481 481
  ///
482 482
  /// The Mersenne Twister is a twisted generalized feedback
483 483
  /// shift-register generator of Matsumoto and Nishimura. The period
484 484
  /// of this generator is \f$ 2^{19937} - 1 \f$ and it is
485 485
  /// equi-distributed in 623 dimensions for 32-bit numbers. The time
486 486
  /// performance of this generator is comparable to the commonly used
487 487
  /// generators.
488 488
  ///
489 489
  /// This implementation is specialized for both 32-bit and 64-bit
490 490
  /// architectures. The generators differ sligthly in the
491 491
  /// initialization and generation phase so they produce two
492 492
  /// completly different sequences.
493 493
  ///
494 494
  /// The generator gives back random numbers of serveral types. To
495 495
  /// get a random number from a range of a floating point type you
496 496
  /// can use one form of the \c operator() or the \c real() member
497 497
  /// function. If you want to get random number from the {0, 1, ...,
498 498
  /// n-1} integer range use the \c operator[] or the \c integer()
499 499
  /// method. And to get random number from the whole range of an
500 500
  /// integer type you can use the argumentless \c integer() or \c
501 501
  /// uinteger() functions. After all you can get random bool with
502 502
  /// equal chance of true and false or given probability of true
503 503
  /// result with the \c boolean() member functions.
504 504
  ///
505 505
  ///\code
506 506
  /// // The commented code is identical to the other
507 507
  /// double a = rnd();                     // [0.0, 1.0)
508 508
  /// // double a = rnd.real();             // [0.0, 1.0)
509 509
  /// double b = rnd(100.0);                // [0.0, 100.0)
510 510
  /// // double b = rnd.real(100.0);        // [0.0, 100.0)
511 511
  /// double c = rnd(1.0, 2.0);             // [1.0, 2.0)
512 512
  /// // double c = rnd.real(1.0, 2.0);     // [1.0, 2.0)
513 513
  /// int d = rnd[100000];                  // 0..99999
514 514
  /// // int d = rnd.integer(100000);       // 0..99999
515 515
  /// int e = rnd[6] + 1;                   // 1..6
516 516
  /// // int e = rnd.integer(1, 1 + 6);     // 1..6
517 517
  /// int b = rnd.uinteger<int>();          // 0 .. 2^31 - 1
518 518
  /// int c = rnd.integer<int>();           // - 2^31 .. 2^31 - 1
519 519
  /// bool g = rnd.boolean();               // P(g = true) = 0.5
520 520
  /// bool h = rnd.boolean(0.8);            // P(h = true) = 0.8
521 521
  ///\endcode
522 522
  ///
523 523
  /// LEMON provides a global instance of the random number
524 524
  /// generator which name is \ref lemon::rnd "rnd". Usually it is a
525 525
  /// good programming convenience to use this global generator to get
526 526
  /// random numbers.
527 527
  class Random {
528 528
  private:
529 529

	
530 530
    // Architecture word
531 531
    typedef unsigned long Word;
532 532

	
533 533
    _random_bits::RandomCore<Word> core;
534 534
    _random_bits::BoolProducer<Word> bool_producer;
535 535

	
536 536

	
537 537
  public:
538 538

	
539 539
    ///\name Initialization
540 540
    ///
541 541
    /// @{
542 542

	
543
    ///\name Initialization
544
    ///
545
    /// @{
546

	
547 543
    /// \brief Default constructor
548 544
    ///
549 545
    /// Constructor with constant seeding.
550 546
    Random() { core.initState(); }
551 547

	
552 548
    /// \brief Constructor with seed
553 549
    ///
554 550
    /// Constructor with seed. The current number type will be converted
555 551
    /// to the architecture word type.
556 552
    template <typename Number>
557 553
    Random(Number seed) {
558 554
      _random_bits::Initializer<Number, Word>::init(core, seed);
559 555
    }
560 556

	
561 557
    /// \brief Constructor with array seeding
562 558
    ///
563 559
    /// Constructor with array seeding. The given range should contain
564 560
    /// any number type and the numbers will be converted to the
565 561
    /// architecture word type.
566 562
    template <typename Iterator>
567 563
    Random(Iterator begin, Iterator end) {
568 564
      typedef typename std::iterator_traits<Iterator>::value_type Number;
569 565
      _random_bits::Initializer<Number, Word>::init(core, begin, end);
570 566
    }
571 567

	
572 568
    /// \brief Copy constructor
573 569
    ///
574 570
    /// Copy constructor. The generated sequence will be identical to
575 571
    /// the other sequence. It can be used to save the current state
576 572
    /// of the generator and later use it to generate the same
577 573
    /// sequence.
578 574
    Random(const Random& other) {
579 575
      core.copyState(other.core);
580 576
    }
581 577

	
582 578
    /// \brief Assign operator
583 579
    ///
584 580
    /// Assign operator. The generated sequence will be identical to
585 581
    /// the other sequence. It can be used to save the current state
586 582
    /// of the generator and later use it to generate the same
587 583
    /// sequence.
588 584
    Random& operator=(const Random& other) {
589 585
      if (&other != this) {
590 586
        core.copyState(other.core);
591 587
      }
592 588
      return *this;
593 589
    }
594 590

	
595 591
    /// \brief Seeding random sequence
596 592
    ///
597 593
    /// Seeding the random sequence. The current number type will be
598 594
    /// converted to the architecture word type.
599 595
    template <typename Number>
600 596
    void seed(Number seed) {
601 597
      _random_bits::Initializer<Number, Word>::init(core, seed);
602 598
    }
603 599

	
604 600
    /// \brief Seeding random sequence
605 601
    ///
606 602
    /// Seeding the random sequence. The given range should contain
607 603
    /// any number type and the numbers will be converted to the
608 604
    /// architecture word type.
609 605
    template <typename Iterator>
610 606
    void seed(Iterator begin, Iterator end) {
611 607
      typedef typename std::iterator_traits<Iterator>::value_type Number;
612 608
      _random_bits::Initializer<Number, Word>::init(core, begin, end);
613 609
    }
614 610

	
615 611
    /// \brief Seeding from file or from process id and time
616 612
    ///
617 613
    /// By default, this function calls the \c seedFromFile() member
618 614
    /// function with the <tt>/dev/urandom</tt> file. If it does not success,
619 615
    /// it uses the \c seedFromTime().
620 616
    /// \return Currently always true.
621 617
    bool seed() {
622 618
#ifndef WIN32
623 619
      if (seedFromFile("/dev/urandom", 0)) return true;
624 620
#endif
625 621
      if (seedFromTime()) return true;
626 622
      return false;
627 623
    }
628 624

	
629 625
    /// \brief Seeding from file
630 626
    ///
631 627
    /// Seeding the random sequence from file. The linux kernel has two
632 628
    /// devices, <tt>/dev/random</tt> and <tt>/dev/urandom</tt> which
633 629
    /// could give good seed values for pseudo random generators (The
634 630
    /// difference between two devices is that the <tt>random</tt> may
635 631
    /// block the reading operation while the kernel can give good
636 632
    /// source of randomness, while the <tt>urandom</tt> does not
637 633
    /// block the input, but it could give back bytes with worse
638 634
    /// entropy).
639 635
    /// \param file The source file
640 636
    /// \param offset The offset, from the file read.
641 637
    /// \return True when the seeding successes.
642 638
#ifndef WIN32
643 639
    bool seedFromFile(const std::string& file = "/dev/urandom", int offset = 0)
644 640
#else
645 641
    bool seedFromFile(const std::string& file = "", int offset = 0)
646 642
#endif
647 643
    {
648 644
      std::ifstream rs(file.c_str());
649 645
      const int size = 4;
650 646
      Word buf[size];
651 647
      if (offset != 0 && !rs.seekg(offset)) return false;
652 648
      if (!rs.read(reinterpret_cast<char*>(buf), sizeof(buf))) return false;
653 649
      seed(buf, buf + size);
654 650
      return true;
655 651
    }
656 652

	
657 653
    /// \brief Seding from process id and time
658 654
    ///
659 655
    /// Seding from process id and time. This function uses the
660 656
    /// current process id and the current time for initialize the
661 657
    /// random sequence.
662 658
    /// \return Currently always true.
663 659
    bool seedFromTime() {
664 660
#ifndef WIN32
665 661
      timeval tv;
666 662
      gettimeofday(&tv, 0);
667 663
      seed(getpid() + tv.tv_sec + tv.tv_usec);
668 664
#else
669 665
      FILETIME time;
670 666
      GetSystemTimeAsFileTime(&time);
671 667
      seed(GetCurrentProcessId() + time.dwHighDateTime + time.dwLowDateTime);
672 668
#endif
673 669
      return true;
674 670
    }
675 671

	
676 672
    /// @}
677 673

	
678 674
    ///\name Uniform distributions
679 675
    ///
680 676
    /// @{
681 677

	
682 678
    /// \brief Returns a random real number from the range [0, 1)
683 679
    ///
684 680
    /// It returns a random real number from the range [0, 1). The
685 681
    /// default Number type is \c double.
686 682
    template <typename Number>
687 683
    Number real() {
688 684
      return _random_bits::RealConversion<Number, Word>::convert(core);
689 685
    }
690 686

	
691 687
    double real() {
692 688
      return real<double>();
693 689
    }
694 690

	
695 691
    /// \brief Returns a random real number the range [0, b)
696 692
    ///
697 693
    /// It returns a random real number from the range [0, b).
698 694
    template <typename Number>
699 695
    Number real(Number b) {
700 696
      return real<Number>() * b;
701 697
    }
702 698

	
703 699
    /// \brief Returns a random real number from the range [a, b)
704 700
    ///
705 701
    /// It returns a random real number from the range [a, b).
706 702
    template <typename Number>
707 703
    Number real(Number a, Number b) {
708 704
      return real<Number>() * (b - a) + a;
709 705
    }
710 706

	
711
    /// @}
712

	
713
    ///\name Uniform distributions
714
    ///
715
    /// @{
716

	
717 707
    /// \brief Returns a random real number from the range [0, 1)
718 708
    ///
719 709
    /// It returns a random double from the range [0, 1).
720 710
    double operator()() {
721 711
      return real<double>();
722 712
    }
723 713

	
724 714
    /// \brief Returns a random real number from the range [0, b)
725 715
    ///
726 716
    /// It returns a random real number from the range [0, b).
727 717
    template <typename Number>
728 718
    Number operator()(Number b) {
729 719
      return real<Number>() * b;
730 720
    }
731 721

	
732 722
    /// \brief Returns a random real number from the range [a, b)
733 723
    ///
734 724
    /// It returns a random real number from the range [a, b).
735 725
    template <typename Number>
736 726
    Number operator()(Number a, Number b) {
737 727
      return real<Number>() * (b - a) + a;
738 728
    }
739 729

	
740 730
    /// \brief Returns a random integer from a range
741 731
    ///
742 732
    /// It returns a random integer from the range {0, 1, ..., b - 1}.
743 733
    template <typename Number>
744 734
    Number integer(Number b) {
745 735
      return _random_bits::Mapping<Number, Word>::map(core, b);
746 736
    }
747 737

	
748 738
    /// \brief Returns a random integer from a range
749 739
    ///
750 740
    /// It returns a random integer from the range {a, a + 1, ..., b - 1}.
751 741
    template <typename Number>
752 742
    Number integer(Number a, Number b) {
753 743
      return _random_bits::Mapping<Number, Word>::map(core, b - a) + a;
754 744
    }
755 745

	
756 746
    /// \brief Returns a random integer from a range
757 747
    ///
758 748
    /// It returns a random integer from the range {0, 1, ..., b - 1}.
759 749
    template <typename Number>
760 750
    Number operator[](Number b) {
761 751
      return _random_bits::Mapping<Number, Word>::map(core, b);
762 752
    }
763 753

	
764 754
    /// \brief Returns a random non-negative integer
765 755
    ///
766 756
    /// It returns a random non-negative integer uniformly from the
767 757
    /// whole range of the current \c Number type. The default result
768 758
    /// type of this function is <tt>unsigned int</tt>.
769 759
    template <typename Number>
770 760
    Number uinteger() {
771 761
      return _random_bits::IntConversion<Number, Word>::convert(core);
772 762
    }
773 763

	
774
    /// @}
775

	
776 764
    unsigned int uinteger() {
777 765
      return uinteger<unsigned int>();
778 766
    }
779 767

	
780 768
    /// \brief Returns a random integer
781 769
    ///
782 770
    /// It returns a random integer uniformly from the whole range of
783 771
    /// the current \c Number type. The default result type of this
784 772
    /// function is \c int.
785 773
    template <typename Number>
786 774
    Number integer() {
787 775
      static const int nb = std::numeric_limits<Number>::digits +
788 776
        (std::numeric_limits<Number>::is_signed ? 1 : 0);
789 777
      return _random_bits::IntConversion<Number, Word, nb>::convert(core);
790 778
    }
791 779

	
792 780
    int integer() {
793 781
      return integer<int>();
794 782
    }
795 783

	
796 784
    /// \brief Returns a random bool
797 785
    ///
798 786
    /// It returns a random bool. The generator holds a buffer for
799 787
    /// random bits. Every time when it become empty the generator makes
800 788
    /// a new random word and fill the buffer up.
801 789
    bool boolean() {
802 790
      return bool_producer.convert(core);
803 791
    }
804 792

	
805 793
    /// @}
806 794

	
807 795
    ///\name Non-uniform distributions
808 796
    ///
809

	
810 797
    ///@{
811 798

	
812
    /// \brief Returns a random bool
799
    /// \brief Returns a random bool with given probability of true result.
813 800
    ///
814 801
    /// It returns a random bool with given probability of true result.
815 802
    bool boolean(double p) {
816 803
      return operator()() < p;
817 804
    }
818 805

	
819
    /// Standard Gauss distribution
806
    /// Standard normal (Gauss) distribution
820 807

	
821
    /// Standard Gauss distribution.
808
    /// Standard normal (Gauss) distribution.
822 809
    /// \note The Cartesian form of the Box-Muller
823 810
    /// transformation is used to generate a random normal distribution.
824 811
    double gauss()
825 812
    {
826 813
      double V1,V2,S;
827 814
      do {
828 815
        V1=2*real<double>()-1;
829 816
        V2=2*real<double>()-1;
830 817
        S=V1*V1+V2*V2;
831 818
      } while(S>=1);
832 819
      return std::sqrt(-2*std::log(S)/S)*V1;
833 820
    }
834
    /// Gauss distribution with given mean and standard deviation
821
    /// Normal (Gauss) distribution with given mean and standard deviation
835 822

	
836
    /// Gauss distribution with given mean and standard deviation.
823
    /// Normal (Gauss) distribution with given mean and standard deviation.
837 824
    /// \sa gauss()
838 825
    double gauss(double mean,double std_dev)
839 826
    {
840 827
      return gauss()*std_dev+mean;
841 828
    }
842 829

	
843 830
    /// Lognormal distribution
844 831

	
845 832
    /// Lognormal distribution. The parameters are the mean and the standard
846 833
    /// deviation of <tt>exp(X)</tt>.
847 834
    ///
848 835
    double lognormal(double n_mean,double n_std_dev)
849 836
    {
850 837
      return std::exp(gauss(n_mean,n_std_dev));
851 838
    }
852 839
    /// Lognormal distribution
853 840

	
854 841
    /// Lognormal distribution. The parameter is an <tt>std::pair</tt> of
855 842
    /// the mean and the standard deviation of <tt>exp(X)</tt>.
856 843
    ///
857 844
    double lognormal(const std::pair<double,double> &params)
858 845
    {
859 846
      return std::exp(gauss(params.first,params.second));
860 847
    }
861 848
    /// Compute the lognormal parameters from mean and standard deviation
862 849

	
863 850
    /// This function computes the lognormal parameters from mean and
864 851
    /// standard deviation. The return value can direcly be passed to
865 852
    /// lognormal().
866 853
    std::pair<double,double> lognormalParamsFromMD(double mean,
867
						   double std_dev)
854
                                                   double std_dev)
868 855
    {
869 856
      double fr=std_dev/mean;
870 857
      fr*=fr;
871 858
      double lg=std::log(1+fr);
872 859
      return std::pair<double,double>(std::log(mean)-lg/2.0,std::sqrt(lg));
873 860
    }
874 861
    /// Lognormal distribution with given mean and standard deviation
875
    
862

	
876 863
    /// Lognormal distribution with given mean and standard deviation.
877 864
    ///
878 865
    double lognormalMD(double mean,double std_dev)
879 866
    {
880 867
      return lognormal(lognormalParamsFromMD(mean,std_dev));
881 868
    }
882
    
869

	
883 870
    /// Exponential distribution with given mean
884 871

	
885 872
    /// This function generates an exponential distribution random number
886 873
    /// with mean <tt>1/lambda</tt>.
887 874
    ///
888 875
    double exponential(double lambda=1.0)
889 876
    {
890 877
      return -std::log(1.0-real<double>())/lambda;
891 878
    }
892 879

	
893 880
    /// Gamma distribution with given integer shape
894 881

	
895 882
    /// This function generates a gamma distribution random number.
896 883
    ///
897 884
    ///\param k shape parameter (<tt>k>0</tt> integer)
898 885
    double gamma(int k)
899 886
    {
900 887
      double s = 0;
901 888
      for(int i=0;i<k;i++) s-=std::log(1.0-real<double>());
902 889
      return s;
903 890
    }
904 891

	
905 892
    /// Gamma distribution with given shape and scale parameter
906 893

	
907 894
    /// This function generates a gamma distribution random number.
908 895
    ///
909 896
    ///\param k shape parameter (<tt>k>0</tt>)
910 897
    ///\param theta scale parameter
911 898
    ///
912 899
    double gamma(double k,double theta=1.0)
913 900
    {
914 901
      double xi,nu;
915 902
      const double delta = k-std::floor(k);
916 903
      const double v0=E/(E-delta);
917 904
      do {
918 905
        double V0=1.0-real<double>();
919 906
        double V1=1.0-real<double>();
920 907
        double V2=1.0-real<double>();
921 908
        if(V2<=v0)
922 909
          {
923 910
            xi=std::pow(V1,1.0/delta);
924 911
            nu=V0*std::pow(xi,delta-1.0);
925 912
          }
926 913
        else
927 914
          {
928 915
            xi=1.0-std::log(V1);
929 916
            nu=V0*std::exp(-xi);
930 917
          }
931 918
      } while(nu>std::pow(xi,delta-1.0)*std::exp(-xi));
932 919
      return theta*(xi+gamma(int(std::floor(k))));
933 920
    }
934 921

	
935 922
    /// Weibull distribution
936 923

	
937 924
    /// This function generates a Weibull distribution random number.
938 925
    ///
939 926
    ///\param k shape parameter (<tt>k>0</tt>)
940 927
    ///\param lambda scale parameter (<tt>lambda>0</tt>)
941 928
    ///
942 929
    double weibull(double k,double lambda)
943 930
    {
944 931
      return lambda*pow(-std::log(1.0-real<double>()),1.0/k);
945 932
    }
946 933

	
947 934
    /// Pareto distribution
948 935

	
949 936
    /// This function generates a Pareto distribution random number.
950 937
    ///
951 938
    ///\param k shape parameter (<tt>k>0</tt>)
952 939
    ///\param x_min location parameter (<tt>x_min>0</tt>)
953 940
    ///
954 941
    double pareto(double k,double x_min)
955 942
    {
956 943
      return exponential(gamma(k,1.0/x_min))+x_min;
957 944
    }
958 945

	
959 946
    /// Poisson distribution
960 947

	
961 948
    /// This function generates a Poisson distribution random number with
962 949
    /// parameter \c lambda.
963 950
    ///
964 951
    /// The probability mass function of this distribusion is
965 952
    /// \f[ \frac{e^{-\lambda}\lambda^k}{k!} \f]
966 953
    /// \note The algorithm is taken from the book of Donald E. Knuth titled
967 954
    /// ''Seminumerical Algorithms'' (1969). Its running time is linear in the
968 955
    /// return value.
969 956

	
970 957
    int poisson(double lambda)
971 958
    {
972 959
      const double l = std::exp(-lambda);
973 960
      int k=0;
974 961
      double p = 1.0;
975 962
      do {
976 963
        k++;
977 964
        p*=real<double>();
978 965
      } while (p>=l);
979 966
      return k-1;
980 967
    }
981 968

	
982 969
    ///@}
983 970

	
984 971
    ///\name Two dimensional distributions
985 972
    ///
986

	
987 973
    ///@{
988 974

	
989 975
    /// Uniform distribution on the full unit circle
990 976

	
991 977
    /// Uniform distribution on the full unit circle.
992 978
    ///
993 979
    dim2::Point<double> disc()
994 980
    {
995 981
      double V1,V2;
996 982
      do {
997 983
        V1=2*real<double>()-1;
998 984
        V2=2*real<double>()-1;
999 985

	
1000 986
      } while(V1*V1+V2*V2>=1);
1001 987
      return dim2::Point<double>(V1,V2);
1002 988
    }
1003
    /// A kind of two dimensional Gauss distribution
989
    /// A kind of two dimensional normal (Gauss) distribution
1004 990

	
1005 991
    /// This function provides a turning symmetric two-dimensional distribution.
1006 992
    /// Both coordinates are of standard normal distribution, but they are not
1007 993
    /// independent.
1008 994
    ///
1009 995
    /// \note The coordinates are the two random variables provided by
1010 996
    /// the Box-Muller method.
1011 997
    dim2::Point<double> gauss2()
1012 998
    {
1013 999
      double V1,V2,S;
1014 1000
      do {
1015 1001
        V1=2*real<double>()-1;
1016 1002
        V2=2*real<double>()-1;
1017 1003
        S=V1*V1+V2*V2;
1018 1004
      } while(S>=1);
1019 1005
      double W=std::sqrt(-2*std::log(S)/S);
1020 1006
      return dim2::Point<double>(W*V1,W*V2);
1021 1007
    }
1022 1008
    /// A kind of two dimensional exponential distribution
1023 1009

	
1024 1010
    /// This function provides a turning symmetric two-dimensional distribution.
1025 1011
    /// The x-coordinate is of conditionally exponential distribution
1026 1012
    /// with the condition that x is positive and y=0. If x is negative and
1027 1013
    /// y=0 then, -x is of exponential distribution. The same is true for the
1028 1014
    /// y-coordinate.
1029 1015
    dim2::Point<double> exponential2()
1030 1016
    {
1031 1017
      double V1,V2,S;
1032 1018
      do {
1033 1019
        V1=2*real<double>()-1;
1034 1020
        V2=2*real<double>()-1;
1035 1021
        S=V1*V1+V2*V2;
1036 1022
      } while(S>=1);
1037 1023
      double W=-std::log(S)/S;
1038 1024
      return dim2::Point<double>(W*V1,W*V2);
1039 1025
    }
1040 1026

	
1041 1027
    ///@}
1042 1028
  };
1043 1029

	
1044 1030

	
1045 1031
  extern Random rnd;
1046 1032

	
1047 1033
}
1048 1034

	
1049 1035
#endif
0 comments (0 inline)