Пример #1
0
        /// <summary>
        /// Find the best single bitfield suitable for use in a switch statement.
        ///
        /// This algorithm is not perfect: it can sometimes return a sub-optimal bitfield. It uses a
        /// heuristic approach, under the assumption that the best bitfield is the same as the
        /// bitfield with the highest total bit quality (and nearest the desired bit length). This
        /// assumption tends to favour longer bitfields. In some cases, however, a shorter bitfield
        /// may have an equal ability to discriminate between rules.
        /// </summary>
        /// <param name="min">Fewest number of acceptable bits.</param>
        /// <param name="max">Largest number of acceptable bits.</param>
        /// <param name="ideal">Preferred number of acceptable bits.</param>
        /// <param name="exclusion">A mask indicating bits that should be excluded (optional).</param>
        /// <returns>The best bitfield meeting the criteria, or null in case of failure.</returns>
        private Bitfield?FindBestBitfield(int min, int max, int ideal, TristateBitArray?exclusion = null)
        {
            if (exclusion == null)
            {
                exclusion = ruleSet.Condition.DecodeBits;
            }

            Bitfield?best = null;

            // iterate through candidate start bits
            for (int start = MinSignificantBit; start <= MaxSignificantBit; start++)
            {
                // iterate through candidate end bits
                for (int end = start + min - 1; end <= start + max - 1; end++)
                {
                    // discard any bitfield that provably contains zero-quality bits
                    if (end <= MaxSignificantBit)
                    {
                        // viable bitfields cannot intersect with the exclusion mask
                        var bits = TristateBitArray.LoadBitfieldValue(Spec.NumBits, start, end, 0);
                        if (!exclusion.MaskIntersectsWith(bits))
                        {
                            // calculate total bit quality over the range
                            if (CalculateTotalQuality(start, end, out float totalQuality))
                            {
                                var tmp = new Bitfield(Spec, start, end, ideal, totalQuality);

                                // track highest overall quality
                                if (best == null || tmp.Quality > best.Quality)
                                {
                                    best = tmp;
                                }
                            }
                        }
                    }
                }
            }

            return(best);
        }