Exemple #1
0
        private BigInteger BenchmarkBCRank(int n, int k, out long ticks)
        {
            // This method benchmarks obtaining the rank for this n choose k case.
            //
            BigInteger rank;

            GC.Collect();
            var bc = new BinCoeffBigInt(n, k);

            int[] kIndexes = new int[k];
            bc.GetCombFromRank(bc.TotalCombos / 2, kIndexes);
            Stopwatch sw = Stopwatch.StartNew();

            rank = bc.GetRank(true, kIndexes);
            sw.Stop();
            ticks = sw.ElapsedTicks;
            return(rank);
        }
        private void BenchmarkBinCoeffMultiple(int[] numElemArray, int[] numGroupArray)
        {
            // This method benchmarks the n choose k tests for many subcases & ranks, and compares the performance against the Combination class methods.
            // The first benchmark compares the performance of single methods. This one attempts a more "real-life" analysis and calls GetRank and
            // GetComboFromRank 1,000 times for all the subcases for each test case.
            //
            int numItems, groupSize, caseLoop;

            int[]          kIndexes = new int[100];
            BigInteger     rankSum  = 1;
            int            kLoop;
            BinCoeffBigInt bcbi;
            long           ticks, ticksAlt, ticksSum = 0, ticksSumAlt = 0;
            BigInteger     numCombos, rank, rank2;
            int            rankCount = 1000, rankLoop;
            double         d;
            Stopwatch      sw;

            // Benchmark all the specified n choose k test cases.
            for (caseLoop = 0; caseLoop < numElemArray.Length; caseLoop++)
            {
                numItems  = numElemArray[caseLoop];
                groupSize = numGroupArray[caseLoop];
                GC.Collect();
                sw   = Stopwatch.StartNew();
                bcbi = new BinCoeffBigInt(numItems, groupSize);
                // Benchmark the subcases > 1,000 combinations.
                for (kLoop = groupSize; kLoop > 3; kLoop--)
                {
                    numCombos = bcbi.GetNumCombos(numItems, kLoop);
                    rank      = (numCombos / 2) - (rankCount / 2);
                    for (rankLoop = 0; rankLoop < rankCount; rankLoop++)
                    {
                        bcbi.GetCombFromRank(rank, kIndexes, numItems, kLoop);
                        rank2 = bcbi.GetRank(true, kIndexes, kLoop);
                        if (rankLoop > rankCount)
                        {
                            rankSum += rank2;
                        }
                        rank += 1;
                    }
                }
                sw.Stop();
                ticks = sw.ElapsedTicks;
                // Benchmark the combination class using the same code as above.
                sw = Stopwatch.StartNew();
                for (kLoop = groupSize; kLoop > 3; kLoop--)
                {
                    numCombos = Combination.GetNumCombos(numItems, kLoop);
                    rank      = (numCombos / 2) - (rankCount / 2);
                    for (rankLoop = 0; rankLoop < rankCount; rankLoop++)
                    {
                        Combination.GetCombFromRankBigInt(rank, kIndexes, numItems, kLoop);
                        rank2 = Combination.GetRankBigInt(kIndexes, numItems, kLoop);
                        // rankLoop will never be > rankCount, but the compiler does not know this -> trying to avoid unnecessary bigint ops,
                        // but making sure that the compiler does not optimize away code that it thinks is not being used.
                        if (rankLoop > rankCount)
                        {
                            rankSum += rank2;
                        }
                        rank += 1;
                    }
                }
                sw.Stop();
                ticksAlt = sw.ElapsedTicks;
                // Display the results.
                d = (double)ticksAlt / (double)ticks;
                d = Math.Round(d, 2);
                Console.WriteLine($"Multiple methods benchmark for {numItems} choose {groupSize} & subcases .vs. Combination class ratio = {d} to 1.");
                ticksSum    += ticks;
                ticksSumAlt += ticksAlt;
            }
            d = (double)ticksSumAlt / (double)ticksSum;
            d = Math.Round(d, 2);
            Console.WriteLine($"Average for all n choose k cases & subcases .vs. Combination class ratio = {d} to 1.");
            // Looking at the sum of the return values makes sure that the compiler does not optimize the code away.
            if (rankSum == 0)
            {
                Console.WriteLine("Error - rankSum = 0?");
            }
        }