/// <inheritdoc/>
        protected override double GetLogNormalizerOfProduct(StringDictionaryWeightFunction weightFunction)
        {
            var    dict1 = (SortedList <string, Weight>)Dictionary;
            var    dict2 = (SortedList <string, Weight>)weightFunction.Dictionary;
            Weight normalizer = Weight.Zero;
            int    idx1 = 0, idx2 = 0;

            while (idx1 < dict1.Count && idx2 < dict2.Count)
            {
                int comparisonResult = string.CompareOrdinal(dict1.Keys[idx1], dict2.Keys[idx2]);
                if (comparisonResult < 0)
                {
                    ++idx1;
                }
                else if (comparisonResult > 0)
                {
                    ++idx2;
                }
                else
                {
                    normalizer += dict1.Values[idx1] * dict2.Values[idx2];
                    ++idx1;
                    ++idx2;
                }
            }

            return(normalizer.LogValue);
        }
        /// <inheritdoc/>
        public override StringDictionaryWeightFunction Product(StringDictionaryWeightFunction weightFunction)
        {
            var dict1 = (SortedList <string, Weight>)Dictionary;
            var dict2 = (SortedList <string, Weight>)weightFunction.Dictionary;
            var resultList = new SortedList <string, Weight>(Math.Min(dict1.Count, dict2.Count), StringComparer.Ordinal);
            int idx1 = 0, idx2 = 0;

            while (idx1 < dict1.Count && idx2 < dict2.Count)
            {
                int comparisonResult = string.CompareOrdinal(dict1.Keys[idx1], dict2.Keys[idx2]);
                if (comparisonResult < 0)
                {
                    ++idx1;
                }
                else if (comparisonResult > 0)
                {
                    ++idx2;
                }
                else
                {
                    resultList.Add(dict1.Keys[idx1], dict1.Values[idx1] * dict2.Values[idx2]);
                    ++idx1;
                    ++idx2;
                }
            }
            resultList.TrimExcess();

            return(new StringDictionaryWeightFunction(resultList));
        }