<commit_before>using System;
using System.Diagnostics;
using System.Text;

namespace Lucene.Net.Search
{
    /*
     * Licensed to the Apache Software Foundation (ASF) under one or more
     * contributor license agreements.  See the NOTICE file distributed with
     * this work for additional information regarding copyright ownership.
     * The ASF licenses this file to You under the Apache License, Version 2.0
     * (the "License"); you may not use this file except in compliance with
     * the License.  You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */

    using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
    using IBits = Lucene.Net.Util.IBits;
    using BytesRef = Lucene.Net.Util.BytesRef;
    using NumericUtils = Lucene.Net.Util.NumericUtils;
    using SortedDocValues = Lucene.Net.Index.SortedDocValues;

    /// <summary>
    /// A range filter built on top of a cached single term field (in <see cref="IFieldCache"/>).
    ///
    /// <para/><see cref="FieldCacheRangeFilter"/> builds a single cache for the field the first time it is used.
    /// Each subsequent <see cref="FieldCacheRangeFilter"/> on the same field then reuses this cache,
    /// even if the range itself changes.
    ///
    /// <para/>this means that <see cref="FieldCacheRangeFilter"/> is much faster (sometimes more than 100x as fast)
    /// as building a <see cref="TermRangeFilter"/>, if using a <see cref="NewStringRange(string, string, string, bool, bool)"/>.
    /// However, if the range never changes it is slower (around 2x as slow) than building
    /// a <see cref="CachingWrapperFilter"/> on top of a single <see cref="TermRangeFilter"/>.
    ///
    /// <para/>For numeric data types, this filter may be significantly faster than <see cref="NumericRangeFilter"/>.
    /// Furthermore, it does not need the numeric values encoded
    /// by <see cref="Documents.Int32Field"/>, <see cref="Documents.SingleField"/>,
    /// <see cref="Documents.Int64Field"/> or <see cref="Documents.DoubleField"/>. But
    /// it has the problem that it only works with exact one value/document (see below).
    ///
    /// <para/>As with all <see cref="IFieldCache"/> based functionality, <see cref="FieldCacheRangeFilter"/> is only valid for
    /// fields which exact one term for each document (except for <see cref="NewStringRange(string, string, string, bool, bool)"/>
    /// where 0 terms are also allowed). Due to a restriction of <see cref="IFieldCache"/>, for numeric ranges
    /// all terms that do not have a numeric value, 0 is assumed.
    ///
    /// <para/>Thus it works on dates, prices and other single value fields but will not work on
    /// regular text fields. It is preferable to use a <see cref="Documents.Field.Index.NOT_ANALYZED"/> field to ensure that
    /// there is only a single term.
    ///
    /// <para/>This class does not have an constructor, use one of the static factory methods available,
    /// that create a correct instance for different data types supported by <see cref="IFieldCache"/>.
    /// </summary>
#if FEATURE_SERIALIZABLE
    [Serializable]
#endif
    public static class FieldCacheRangeFilter
    {
#if FEATURE_SERIALIZABLE
        [Serializable]
#endif
        private class AnonymousStringFieldCacheRangeFilter : FieldCacheRangeFilter<string>
        {
#if FEATURE_SERIALIZABLE
            [Serializable]
#endif
            private class AnonymousClassFieldCacheDocIdSet : FieldCacheDocIdSet
            {
                private SortedDocValues fcsi;
                private int inclusiveLowerPoint;
                private int inclusiveUpperPoint;

                internal AnonymousClassFieldCacheDocIdSet(SortedDocValues fcsi, int inclusiveLowerPoint, int inclusiveUpperPoint, int maxDoc, IBits acceptDocs)
                    : base(maxDoc, acceptDocs)
                {
                    this.fcsi = fcsi;
                    this.inclusiveLowerPoint = inclusiveLowerPoint;
                    this.inclusiveUpperPoint = inclusiveUpperPoint;
                }

                protected internal override bool MatchDoc(int doc)
                {
                    int docOrd = fcsi.GetOrd(doc);
                    return docOrd >= inclusiveLowerPoint && docOrd <= inclusiveUpperPoint;
                }
            }

            internal AnonymousStringFieldCacheRangeFilter(string field, string lowerVal, string upperVal, bool includeLower, bool includeUpper)
                : base(field, null, lowerVal, upperVal, includeLower, includeUpper)
            {
            }

            public override DocIdSet GetDocIdSet(AtomicReaderContext context, IBits acceptDocs)
            {
                SortedDocValues fcsi = FieldCache.DEFAULT.GetTermsIndex(context.AtomicReader, field);
                int lowerPoint = lowerVal == null ? -1 : fcsi.LookupTerm(new BytesRef(lowerVal));
                int upperPoint = upperVal == null ? -1 : fcsi.LookupTerm(new BytesRef(upperVal));

                int inclusiveLowerPoint, inclusiveUpperPoint;

                // Hints:
                // * binarySearchLookup returns 0, if value was null.
                // * the value is <0 if no exact hit was found, the returned value
                //   is (-(insertion point) - 1)
                if (lowerPoint == -1 && lowerVal == null)
                {
                    inclusiveLowerPoint = 0;
                }
                else if (includeLower && lowerPoint >= 0)
                {
                    inclusiveLowerPoint = lowerPoint;
                }
                else if (lowerPoint >= 0)
                {
                    inclusiveLowerPoint = lowerPoint + 1;
                }
                else
                {
                    inclusiveLowerPoint = Math.Max(0, -lowerPoint - 1);
                }

                if (upperPoint == -1 && upperVal == null)
                {
                    inclusiveUpperPoint = int.MaxValue;
                }
                else if (includeUpper && upperPoint >= 0)
                {
                    inclusiveUpperPoint = upperPoint;
                }
                else if (upperPoint >= 0)
                {
                    inclusiveUpperPoint = upperPoint - 1;
                }
                else
                {
                    inclusiveUpperPoint = -upperPoint - 2;
                }

                if (inclusiveUpperPoint < 0 || inclusiveLowerPoint > inclusiveUpperPoint)
                {
                    return null;
                }

                // TODO: LUCENENET This should be throwing an exception during
                // a test run on the original solution, but does not.
                // ie. inclusiveLowerPoint > 0 && inclusiveUpperPoint > 0
                // evaluates to false, but a DebugAssertionException is not
                // thrown on the original test runs.
                Debug.Assert(inclusiveLowerPoint > 0 && inclusiveUpperPoint > 0);

                return new AnonymousClassFieldCacheDocIdSet(fcsi, inclusiveLowerPoint, inclusiveUpperPoint, context.Reader.MaxDoc, acceptDocs);
            }
        }

#if FEATURE_SERIALIZABLE
        [Serializable]
#endif
        private class AnonymousBytesRefFieldCacheRangeFilter : FieldCacheRangeFilter<BytesRef>
        {
#if FEATURE_SERIALIZABLE
            [Serializable]
#endif
            private class AnonymousClassFieldCacheDocIdSet : FieldCacheDocIdSet
            {
                private SortedDocValues fcsi;
                private int inclusiveLowerPoint;
                private int inclusiveUpperPoint;

                internal AnonymousClassFieldCacheDocIdSet(SortedDocValues fcsi, int inclusiveLowerPoint, int inclusiveUpperPoint, int maxDoc, IBits acceptDocs)
                    : base(maxDoc, acceptDocs)
                {
                    this.fcsi = fcsi;
                    this.inclusiveLowerPoint = inclusiveLowerPoint;<commit_msg>BUG: Lucene.Net.Search.FieldCacheRangeFilter.AnonymousStringFieldCacheRangeFilter: Fixed Debug.Assert condition that was causing assert to fail.<commit_after>using System;
using System.Diagnostics;
using System.Text;

namespace Lucene.Net.Search
{
    /*
     * Licensed to the Apache Software Foundation (ASF) under one or more
     * contributor license agreements.  See the NOTICE file distributed with
     * this work for additional information regarding copyright ownership.
     * The ASF licenses this file to You under the Apache License, Version 2.0
     * (the "License"); you may not use this file except in compliance with
     * the License.  You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */

    using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
    using IBits = Lucene.Net.Util.IBits;
    using BytesRef = Lucene.Net.Util.BytesRef;
    using NumericUtils = Lucene.Net.Util.NumericUtils;
    using SortedDocValues = Lucene.Net.Index.SortedDocValues;

    /// <summary>
    /// A range filter built on top of a cached single term field (in <see cref="IFieldCache"/>).
    ///
    /// <para/><see cref="FieldCacheRangeFilter"/> builds a single cache for the field the first time it is used.
    /// Each subsequent <see cref="FieldCacheRangeFilter"/> on the same field then reuses this cache,
    /// even if the range itself changes.
    ///
    /// <para/>this means that <see cref="FieldCacheRangeFilter"/> is much faster (sometimes more than 100x as fast)
    /// as building a <see cref="TermRangeFilter"/>, if using a <see cref="NewStringRange(string, string, string, bool, bool)"/>.
    /// However, if the range never changes it is slower (around 2x as slow) than building
    /// a <see cref="CachingWrapperFilter"/> on top of a single <see cref="TermRangeFilter"/>.
    ///
    /// <para/>For numeric data types, this filter may be significantly faster than <see cref="NumericRangeFilter"/>.
    /// Furthermore, it does not need the numeric values encoded
    /// by <see cref="Documents.Int32Field"/>, <see cref="Documents.SingleField"/>,
    /// <see cref="Documents.Int64Field"/> or <see cref="Documents.DoubleField"/>. But
    /// it has the problem that it only works with exact one value/document (see below).
    ///
    /// <para/>As with all <see cref="IFieldCache"/> based functionality, <see cref="FieldCacheRangeFilter"/> is only valid for
    /// fields which exact one term for each document (except for <see cref="NewStringRange(string, string, string, bool, bool)"/>
    /// where 0 terms are also allowed). Due to a restriction of <see cref="IFieldCache"/>, for numeric ranges
    /// all terms that do not have a numeric value, 0 is assumed.
    ///
    /// <para/>Thus it works on dates, prices and other single value fields but will not work on
    /// regular text fields. It is preferable to use a <see cref="Documents.Field.Index.NOT_ANALYZED"/> field to ensure that
    /// there is only a single term.
    ///
    /// <para/>This class does not have an constructor, use one of the static factory methods available,
    /// that create a correct instance for different data types supported by <see cref="IFieldCache"/>.
    /// </summary>
#if FEATURE_SERIALIZABLE
    [Serializable]
#endif
    public static class FieldCacheRangeFilter
    {
#if FEATURE_SERIALIZABLE
        [Serializable]
#endif
        private class AnonymousStringFieldCacheRangeFilter : FieldCacheRangeFilter<string>
        {
#if FEATURE_SERIALIZABLE
            [Serializable]
#endif
            private class AnonymousClassFieldCacheDocIdSet : FieldCacheDocIdSet
            {
                private SortedDocValues fcsi;
                private int inclusiveLowerPoint;
                private int inclusiveUpperPoint;

                internal AnonymousClassFieldCacheDocIdSet(SortedDocValues fcsi, int inclusiveLowerPoint, int inclusiveUpperPoint, int maxDoc, IBits acceptDocs)
                    : base(maxDoc, acceptDocs)
                {
                    this.fcsi = fcsi;
                    this.inclusiveLowerPoint = inclusiveLowerPoint;
                    this.inclusiveUpperPoint = inclusiveUpperPoint;
                }

                protected internal override bool MatchDoc(int doc)
                {
                    int docOrd = fcsi.GetOrd(doc);
                    return docOrd >= inclusiveLowerPoint && docOrd <= inclusiveUpperPoint;
                }
            }

            internal AnonymousStringFieldCacheRangeFilter(string field, string lowerVal, string upperVal, bool includeLower, bool includeUpper)
                : base(field, null, lowerVal, upperVal, includeLower, includeUpper)
            {
            }

            public override DocIdSet GetDocIdSet(AtomicReaderContext context, IBits acceptDocs)
            {
                SortedDocValues fcsi = FieldCache.DEFAULT.GetTermsIndex(context.AtomicReader, field);
                int lowerPoint = lowerVal == null ? -1 : fcsi.LookupTerm(new BytesRef(lowerVal));
                int upperPoint = upperVal == null ? -1 : fcsi.LookupTerm(new BytesRef(upperVal));

                int inclusiveLowerPoint, inclusiveUpperPoint;

                // Hints:
                // * binarySearchLookup returns 0, if value was null.
                // * the value is <0 if no exact hit was found, the returned value
                //   is (-(insertion point) - 1)
                if (lowerPoint == -1 && lowerVal == null)
                {
                    inclusiveLowerPoint = 0;
                }
                else if (includeLower && lowerPoint >= 0)
                {
                    inclusiveLowerPoint = lowerPoint;
                }
                else if (lowerPoint >= 0)
                {
                    inclusiveLowerPoint = lowerPoint + 1;
                }
                else
                {
                    inclusiveLowerPoint = Math.Max(0, -lowerPoint - 1);
                }

                if (upperPoint == -1 && upperVal == null)
                {
                    inclusiveUpperPoint = int.MaxValue;
                }
                else if (includeUpper && upperPoint >= 0)
                {
                    inclusiveUpperPoint = upperPoint;
                }
                else if (upperPoint >= 0)
                {
                    inclusiveUpperPoint = upperPoint - 1;
                }
                else
                {
                    inclusiveUpperPoint = -upperPoint - 2;
                }

                if (inclusiveUpperPoint < 0 || inclusiveLowerPoint > inclusiveUpperPoint)
                {
                    return null;
                }

                Debug.Assert(inclusiveLowerPoint >= 0 && inclusiveUpperPoint >= 0);

                return new AnonymousClassFieldCacheDocIdSet(fcsi, inclusiveLowerPoint, inclusiveUpperPoint, context.Reader.MaxDoc, acceptDocs);
            }
        }

#if FEATURE_SERIALIZABLE
        [Serializable]
#endif
        private class AnonymousBytesRefFieldCacheRangeFilter : FieldCacheRangeFilter<BytesRef>
        {
#if FEATURE_SERIALIZABLE
            [Serializable]
#endif
            private class AnonymousClassFieldCacheDocIdSet : FieldCacheDocIdSet
            {
                private SortedDocValues fcsi;
                private int inclusiveLowerPoint;
                private int inclusiveUpperPoint;

                internal AnonymousClassFieldCacheDocIdSet(SortedDocValues fcsi, int inclusiveLowerPoint, int inclusiveUpperPoint, int maxDoc, IBits acceptDocs)
                    : base(maxDoc, acceptDocs)
                {
                    this.fcsi = fcsi;
                    this.inclusiveLowerPoint = inclusiveLowerPoint;
{'fraction_non_alphanumeric': 0.08005353123669323, 'fraction_numerical': 0.004258166555143257, 'mean_word_length': 1.994535519125683, 'pattern_counts': {'":': 0, '<': 67, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6711590', 'n_tokens_mistral': 4189, 'n_tokens_neox': 3937, 'n_words': 1355}