#region License Information /* HeuristicLab * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using HeuristicLab.Core; using System; using HeuristicLab.Common; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Problems.BinPacking.Random { /* * C# port of the implementation of the srand48 random generator. * First implemented in test3dbpp.c by S. Martello, D. Pisinger, D. Vigo, E. den Boef, J. Korst (2003) */ [Item("SRand", "A pseudo random number generator which creates uniformly distributed random numbers.")] [StorableClass] public sealed class SRand48 : Item, IRandom { private object locker = new object(); [Storable] private bool init = false; [Storable] private uint _h48; [Storable] private uint _l48; /// /// Used by HeuristicLab.Persistence to initialize new instances during deserialization. /// /// true, if the constructor is called during deserialization. [StorableConstructor] private SRand48(bool deserializing) : base(deserializing) { } /// /// Initializes a new instance from an existing one (copy constructor). /// /// The original instance which is used to initialize the new instance. /// A which is used to track all already cloned objects in order to avoid cycles. private SRand48(SRand48 original, Cloner cloner) : base(original, cloner) { _h48 = original._h48; _l48 = original._l48; init = original.init; } /// /// Initializes a new instance of . /// public SRand48() { if (!init) { Seed((uint)DateTime.Now.Ticks); init = true; } } /// /// Initializes a new instance of /// with the given seed . /// /// The seed with which to initialize the random number generator. public SRand48(uint seed) { if (!init) { Seed(seed); init = true; } } /// /// Clones the current instance (deep clone). /// /// Dictionary of all already cloned objects. (Needed to avoid cycles.) /// The cloned object as . public override IDeepCloneable Clone(Cloner cloner) { return new SRand48(this, cloner); } /// /// Gets a new random number. /// /// A new int random number. public int Next() { lock (locker) { return (int)LRand48x(); } } /// /// Gets a new random number being smaller than the given . /// /// Thrown when the given maximum value is /// smaller or equal to zero. /// The maximum value of the generated random number. /// A new int random number. public int Next(int maxVal) { lock (locker) { if (maxVal <= 0) throw new ArgumentException("The interval [0, " + maxVal + ") is empty"); return (int)(LRand48x() % maxVal); } } /// /// Gets a new random number being in the given interval and /// . /// /// The minimum value of the generated random number. /// The maximum value of the generated random number. /// A new int random number. public int Next(int minVal, int maxVal) { lock (locker) { if (maxVal <= minVal) throw new ArgumentException("The interval [" + minVal + ", " + maxVal + ") is empty"); return Next(maxVal - minVal + 1) + minVal; } } /// /// Gets a new double random variable. /// /// public double NextDouble() { lock (locker) { return ((double)Next()) * (1.0 / 4294967296.0); } } /// /// Resets the current random number generator. /// public void Reset() { lock (locker) { Seed((uint)DateTime.Now.Ticks); } } /// /// Resets the current random number generator with the given seed . /// /// The seed with which to reset the current instance. public void Reset(int seed) { lock (locker) { Seed((uint)seed); } } /// /// Initializes current instance with random seed. /// /// A starting seed. private void Seed(uint seed) { _h48 = seed; _l48 = 0x330E; } private int LRand48x() { _h48 = (_h48 * 0xDEECE66D) + (_l48 * 0x5DEEC); _l48 = _l48 * 0xE66D + 0xB; _h48 = _h48 + (_l48 >> 16); _l48 = _l48 & 0xFFFF; return (int)(_h48 >> 1); } } }