/* * 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 System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using Lucene.Net.Analysis.Tokenattributes; using Lucene.Net.Index; using Lucene.Net.Search; namespace Lucene.Net.Spatial.Util { public static class CompatibilityExtensions { public static void Append(this ITermAttribute termAtt, string str) { termAtt.SetTermBuffer(termAtt.Term() + str); // TODO: Not optimal, but works } public static void Append(this ITermAttribute termAtt, char ch) { termAtt.SetTermBuffer(termAtt.Term() + new string(new[] { ch })); // TODO: Not optimal, but works } private static readonly ConcurrentDictionary _docsWithFieldCache = new ConcurrentDictionary(); internal static Bits GetDocsWithField(this FieldCache fc, IndexReader reader, String field) { return _docsWithFieldCache.GetOrAdd(field, f => DocsWithFieldCacheEntry_CreateValue(reader, new Entry(field, null), false)); } private static Bits DocsWithFieldCacheEntry_CreateValue(IndexReader reader, Entry entryKey, bool setDocsWithField /* ignored */) { var field = entryKey.field; FixedBitSet res = null; var terms = new TermsEnumCompatibility(reader, field); var maxDoc = reader.MaxDoc; var term = terms.Next(); if (term != null) { int termsDocCount = terms.GetDocCount(); Debug.Assert(termsDocCount <= maxDoc); if (termsDocCount == maxDoc) { // Fast case: all docs have this field: return new Bits.MatchAllBits(maxDoc); } while (true) { if (res == null) { // lazy init res = new FixedBitSet(maxDoc); } var termDocs = reader.TermDocs(term); while (termDocs.Next()) { res.Set(termDocs.Doc); } term = terms.Next(); if (term == null) { break; } } } if (res == null) { return new Bits.MatchNoBits(maxDoc); } int numSet = res.Cardinality(); if (numSet >= maxDoc) { // The cardinality of the BitSet is maxDoc if all documents have a value. Debug.Assert(numSet == maxDoc); return new Bits.MatchAllBits(maxDoc); } return res; } /** table of number of leading zeros in a byte */ public static readonly byte[] nlzTable = { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /// /// Returns the number of leading zero bits. /// /// /// public static int BitUtilNlz(long x) { int n = 0; // do the first step as a long int y = (int)((ulong)x >> 32); if (y == 0) { n += 32; y = (int)(x); } if ((y & 0xFFFF0000) == 0) { n += 16; y <<= 16; } if ((y & 0xFF000000) == 0) { n += 8; y <<= 8; } return n + nlzTable[(uint)y >> 24]; /* implementation without table: if ((y & 0xF0000000) == 0) { n+=4; y<<=4; } if ((y & 0xC0000000) == 0) { n+=2; y<<=2; } if ((y & 0x80000000) == 0) { n+=1; y<<=1; } if ((y & 0x80000000) == 0) { n+=1;} return n; */ } } public static class Arrays { public static void Fill(T[] array, int fromIndex, int toIndex, T value) { if (array == null) { throw new ArgumentNullException("array"); } if (fromIndex < 0 || fromIndex > toIndex) { throw new ArgumentOutOfRangeException("fromIndex"); } if (toIndex > array.Length) { throw new ArgumentOutOfRangeException("toIndex"); } for (var i = fromIndex; i < toIndex; i++) { array[i] = value; } } } /// /// Expert: Every composite-key in the internal cache is of this type. /// internal class Entry { internal readonly String field; // which Fieldable internal readonly Object custom; // which custom comparator or parser /** Creates one of these objects for a custom comparator/parser. */ public Entry(String field, Object custom) { this.field = field; this.custom = custom; } /** Two of these are equal iff they reference the same field and type. */ public override bool Equals(Object o) { var other = o as Entry; if (other != null) { if (other.field.Equals(field)) { if (other.custom == null) { if (custom == null) return true; } else if (other.custom.Equals(custom)) { return true; } } } return false; } /** Composes a hashcode based on the field and type. */ public override int GetHashCode() { return field.GetHashCode() ^ (custom == null ? 0 : custom.GetHashCode()); } } }