/// <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 segements must be between 1 and 15 if ((segmentIndexBits < 1) || (segmentIndexBits > 4)) { // 8 segements 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 segement 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); }
/// <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 segements must be between 1 and 15 if ((segmentIndexBits < 1) || (segmentIndexBits > 4)) { // 8 segements 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 segement 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); }