/// <summary>Initializes of RandomGenerator.</summary> /// <param name="randGen">Type of random generator: /// 0 Mersenne Twister, 1 O'Neill, 2 C std, 3 XorShift, 4 C# std, 5 C# strong.</param> /// <param name="normGen">Type of Gauss generator: /// -1 no generator, 0 Abramowitz and Stegun, 1 Central Limit Theorem, /// 2 Fog, 3Marsaglia, 4 C/C# std</param> /// <param name="isExp">True if include lognorm generation</param> /// <param name="isStdLogNorm">True if use C++ standard lognorm generation</param> /// <param name="distVars">Gauss or lognorm mean and sigma</param> /// <param name="ssVars">Size selection distribution mean and sigma, or null if size selection is inactive</param> /// <returns>False if extern CRandom dll is not found, otherwise true</returns> public static bool Init(int randGen, int normGen, bool isExp, bool isStdLogNorm, float[] distVars, int[] ssVars) { Library = randGen < FIRST_IND_CSH ? ON_C : (randGen == FIRST_IND_CSH + 1 ? ON_SCH_STRONG : ON_CSH); IsExp = isExp; DistVars = distVars; if (normGen == -1 && !isExp) { DistVars[0] = 0; DistVars[1] = 1000; } if (Library == ON_C) { if (System.IO.File.Exists(CRandom.FullDllFile)) { CRandom.Init(randGen, normGen, isExp, isStdLogNorm, distVars, ssVars); } else { return(false); } } else { RandomNumb = GetRandom; CshStrongRandomGen.RecordGaussGen(normGen); Distrib = Distribs[normGen + 1]; } if (ssVars != null) // size selection is able { ssMean = ssVars[0]; //ssDVariance = 2 * ssVars[1] * ssVars[1]; //ssFactor = ssVars[1] * Math.Sqrt(2 * Math.PI); //ssAlignRatio = 2.5 * ssVars[1]; ssFactor0 = (float)(ssVars[1] * Math.Sqrt(2)); ssFactor1 = 2.5f / (float)Math.Sqrt(2 * Math.PI); } else { ssMean = 0; } return(true); }
/// <summary>Fills data by current distribution.</summary> /// <param name="numbers">Data that should be filled</param> /// <param name="cnt">Number or repetitions. Returned the number of random generator calls.</param> /// <returns>Average Y value.</returns> public static float GetDistrib(Numbers numbers, ref int cnt) { GenCallCnt = 0; if (Library == ON_C) { float res = CRandom.GetDistrib( numbers != null ? numbers.Data : null, ref cnt, ref GenCallCnt); cnt = GenCallCnt; return(res); } else if (Library == ON_SCH_STRONG) { CshStrongRandomGen gen = new CshStrongRandomGen(cnt); RandomNumb = gen.GetNext; } decimal sum = 0; int val; int actualCnt = 0; double dval; float ssDev; // result of inverse normal distrib int min, max; for (int i = 0; i < cnt; i++) { dval = Distrib() * DistVars[1] + DistVars[0]; if (IsExp) // lognorm is able { val = (int)Math.Exp(dval); if (ssMean > 0) // size selection is able // === simple method //if (GetRandom() > ssAlignRatio * // Math.Exp(-Math.Pow(dval - ssMean, 2) / ssDVariance) / ssFactor) // continue; // filter by size selection // === method with using min and max { ssDev = ssFactor0 * (float)Math.Sqrt(Math.Log(ssFactor1 / GetRandom())); min = (int)(ssMean - ssDev); max = (int)(ssMean + ssDev); if (val < min || val > max) { continue; // filter by size selection } } } else // lognorm is disable { val = (int)dval; // round up val: otherwise all values will be round down during casting to int. // in this case the distribution will not only be inaccurate, // but worse - values less than 1 will be rounded to 0, // which leads to a falsely large number of zero points. // The variant val = (int)Math.Round(dval, 0) is much slower if (dval > 0) { if (dval - val >= 0.5) { val++; } } // round up positives else { if (dval - val <= -0.5) { val--; } } // round up negatieves } sum += val; if (numbers != null) { numbers.Data[actualCnt] = val; } actualCnt++; } cnt = GenCallCnt; return((float)sum / actualCnt); }