/// <summary> /// used by random table generators to select random number of columns and rows. This method will return very low numbers with high probability, /// </summary> public void NextTableDimentions(int maxRows, int maxColumns, int maxTotalSize, out int randRows, out int randColumns) { // prefer really low values to ensure table size will not go up way too much too frequently const LowValueEnforcementLevel level = LowValueEnforcementLevel.Medium; if (NextBit()) { // select rows first, then columns randColumns = NextAllocationUnit(1, maxColumns, level); randRows = NextAllocationUnit(1, Math.Min(maxRows, maxTotalSize / randColumns), level); } else { randRows = NextAllocationUnit(1, maxRows, level); randColumns = NextAllocationUnit(1, Math.Min(maxColumns, maxTotalSize / randRows), level); } }
/// <summary> /// generates size value with low probability of large size values within the given range /// </summary> /// <param name="lowValuesEnforcementLevel"> /// lowValuesEnforcementLevel is value between 0 and 31; /// 0 means uniform distribution in the min/max range; /// 31 means very low chances for high values /// </param> private int NextAllocationUnit(int minSize, int maxSize, LowValueEnforcementLevel lowValuesLevel) { if (minSize < 0 || maxSize < 0 || minSize > maxSize) { throw new ArgumentOutOfRangeException("minSize or maxSize are out of range"); } if (lowValuesLevel < LowValueEnforcementLevel.VeryStrong || lowValuesLevel > LowValueEnforcementLevel.Uniform) { throw new ArgumentOutOfRangeException("lowValuesLevel"); } if (minSize == maxSize) { return(minSize); // shortcut for fixed size } long longRange = (long)maxSize - (long)minSize + 1; // create a sample in range [0, 1) (it is never 1) double sample = base.NextDouble(); // decrease chances of large size values based on the how many bits digits are set in the maxValue int bitsPerLevel = (int)lowValuesLevel; long maxBitsLeft = longRange >> bitsPerLevel; while (maxBitsLeft > 0) { sample *= base.NextDouble(); maxBitsLeft >>= bitsPerLevel; } int res = minSize + (int)(sample * longRange); Debug.Assert(res >= minSize && res <= maxSize); return(res); }