Пример #1
0
        /// <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);
        }
Пример #2
0
        /// <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);
        }