Exemplo n.º 1
0
        /// <summary>
        /// Initializes generator with a set of random numbers.
        /// </summary>
        /// <param name="randomGeneratorFactory">Factory used to create random number batch generators.</param>
        /// <param name="segmentIndexBits">Number of significant bits in segment index, i.e. value of 3 means 8 segments of random numbers - 0..7.</param>
        /// <param name="segmentBits">Number of significant bits in random number index within segment, i.e. value of 10 means 1024 random numbers per segment.</param>
        public void Initialize(Func <ulong, IRandomNumberBatchGenerator> randomGeneratorFactory, int segmentIndexBits, int segmentBits)
        {
            int num = segmentIndexBits;

            if (segmentIndexBits < 1 || segmentIndexBits > 4)
            {
                num = 3;
            }
            int num2 = segmentBits;

            if (segmentBits < 7 || segmentBits > 15)
            {
                num2 = 9;
            }
            bitsToStoreRandomIndexWithinSegment = num2;
            segmentCount                 = 1 << num;
            segmentSize                  = 1 << num2;
            segmentIndexMask             = segmentCount - 1 << bitsToStoreRandomIndexWithinSegment;
            randomIndexWithinSegmentMask = segmentSize - 1;
            randomArrayIndexMask         = (segmentIndexMask | randomIndexWithinSegmentMask);
            int num3 = segmentCount * segmentSize;

            randomGemerators = new IRandomNumberBatchGenerator[segmentCount];
            XorshiftRandomBatchGenerator xorshiftRandomBatchGenerator = new XorshiftRandomBatchGenerator((ulong)Environment.TickCount);

            ulong[] array = new ulong[segmentCount];
            xorshiftRandomBatchGenerator.NextBatch(array, 0, segmentCount);
            for (int i = 0; i < segmentCount; i++)
            {
                Func <ulong, IRandomNumberBatchGenerator> func         = (ulong seed) => new XorshiftRandomBatchGenerator(seed);
                IRandomNumberBatchGenerator randomNumberBatchGenerator = (randomGeneratorFactory == null) ? func(array[i]) : (randomGeneratorFactory(array[i]) ?? func(array[i]));
                randomGemerators[i] = randomNumberBatchGenerator;
            }
            randomNumbers = new ulong[num3];
            xorshiftRandomBatchGenerator.NextBatch(randomNumbers, 0, num3);
        }
        /// <summary>
        /// Initializes generator with a set of random numbers.
        /// </summary>
        /// <param name="randomGeneratorFactory">Factory used to create random number batch generators.</param>
        /// <param name="segmentIndexBits">Number of significant bits in segment index, i.e. value of 3 means 8 segments of random numbers - 0..7.</param>
        /// <param name="segmentBits">Number of significant bits in random number index within segment, i.e. value of 10 means 1024 random numbers per segment.</param>
        public void Initialize(
            Func <ulong, IRandomNumberBatchGenerator> randomGeneratorFactory,
            int segmentIndexBits,
            int segmentBits)
        {
            // **************************************************
            // validate value of the segementIndexBits parameter
            int effectiveSegementIndexBits = segmentIndexBits;

            // number of segments must be between 1 and 15
            if ((segmentIndexBits < 1) || (segmentIndexBits > 4))
            {
                // 8 segments is default in case the value supplied by caller is incorrect
                effectiveSegementIndexBits = 3;
            }

            // **************************************************
            // validate value of the segementBits parameter
            int effectiveSegementBits = segmentBits;

            // number of randoms within segment must be between 256 and 64K
            if ((segmentBits < 7) || (segmentBits > 15))
            {
                // 1024 randoms is default in case the value supplied by caller is incorrect
                effectiveSegementBits = 9;
            }

            this.bitsToStoreRandomIndexWithinSegment = effectiveSegementBits;

            // store count of segments and count of randoms within the segment
            this.segmentCount = 1 << effectiveSegementIndexBits;
            this.segmentSize  = 1 << effectiveSegementBits;

            // store masks
            this.segmentIndexMask             = (this.segmentCount - 1) << this.bitsToStoreRandomIndexWithinSegment;
            this.randomIndexWithinSegmentMask = this.segmentSize - 1;
            this.randomArrayIndexMask         = this.segmentIndexMask | this.randomIndexWithinSegmentMask;

            int randomNumberCount = this.segmentCount * this.segmentSize;

            // create segmentCount random generators
            this.randomGemerators = new IRandomNumberBatchGenerator[this.segmentCount];

            // create random generator to seed the other ones
            XorshiftRandomBatchGenerator seedingRnd = new XorshiftRandomBatchGenerator((ulong)Environment.TickCount);

            ulong[] seeds = new ulong[this.segmentCount];

            seedingRnd.NextBatch(seeds, 0, this.segmentCount);

            for (int i = 0; i < this.segmentCount; i++)
            {
                // default random batch generator in case factory is null or returns null generator
                Func <ulong, IRandomNumberBatchGenerator> defaultGenerator = (ulong seed) => new XorshiftRandomBatchGenerator(seed);

                IRandomNumberBatchGenerator segmentGenerator = (randomGeneratorFactory == null)
                    ? defaultGenerator(seeds[i])
                    : randomGeneratorFactory(seeds[i]) ?? defaultGenerator(seeds[i]);

                this.randomGemerators[i] = segmentGenerator;
            }

            // allocate storage for random numbers
            this.randomNumbers = new ulong[randomNumberCount];

            // generate entire set of random numbers using seeding random
            seedingRnd.NextBatch(this.randomNumbers, 0, randomNumberCount);
        }