context: /* 
   * 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 IndexReader = Lucene.Net.Index.IndexReader;
  using ByteParser = Lucene.Net.Search.ByteParser;
  using DoubleParser = Lucene.Net.Search.DoubleParser;
  using FloatParser = Lucene.Net.Search.FloatParser;
  using IntParser = Lucene.Net.Search.IntParser;
  using LongParser = Lucene.Net.Search.LongParser;
  using ShortParser = Lucene.Net.Search.ShortParser;
  using StringIndex = Lucene.Net.Search.StringIndex;
  
  namespace Lucene.Net.Search
  {
  	
  	/// <summary> Expert: a FieldComparator compares hits so as to determine their
  	/// sort order when collecting the top results with {@link
  	/// TopFieldCollector}.  The concrete public FieldComparator
  	/// classes here correspond to the SortField types.
  	/// 
  	/// <p/>This API is designed to achieve high performance
  	/// sorting, by exposing a tight interaction with {@link
  	/// FieldValueHitQueue} as it visits hits.  Whenever a hit is
  	/// competitive, it's enrolled into a virtual slot, which is
  	/// an int ranging from 0 to numHits-1.  The {@link
  	/// FieldComparator} is made aware of segment transitions
  	/// during searching in case any internal state it's tracking
  	/// needs to be recomputed during these transitions.<p/>
  	/// 
  	/// <p/>A comparator must define these functions:<p/>
  	/// 
  	/// <ul>
  	/// 
  	/// <li> {@link #compare} Compare a hit at 'slot a'
  	/// with hit 'slot b'.</li>
  	/// 
  	/// <li> {@link #setBottom} This method is called by
  	/// {@link FieldValueHitQueue} to notify the
  	/// FieldComparator of the current weakest ("bottom")
  	/// slot.  Note that this slot may not hold the weakest
  	/// value according to your comparator, in cases where
  	/// your comparator is not the primary one (ie, is only
  	/// used to break ties from the comparators before it).</li>
  	/// 
  	/// <li> {@link #compareBottom} Compare a new hit (docID)
  	/// against the "weakest" (bottom) entry in the queue.</li>
  	/// 
  	/// <li> {@link #copy} Installs a new hit into the
  	/// priority queue.  The {@link FieldValueHitQueue}
  	/// calls this method when a new hit is competitive.</li>
  	/// 
  	/// <li> {@link #setNextReader} Invoked
  	/// when the search is switching to the next segment.
  	/// You may need to update internal state of the
  	/// comparator, for example retrieving new values from
  	/// the {@link FieldCache}.</li>
  	/// 
  	/// <li> {@link #value} Return the sort value stored in
  	/// the specified slot.  This is only called at the end
  	/// of the search, in order to populate {@link
  	/// FieldDoc#fields} when returning the top results.</li>
  	/// </ul>
  	/// 
  	/// <b>NOTE:</b> This API is experimental and might change in
  	/// incompatible ways in the next release.
  	/// </summary>
  	public abstract class FieldComparator
  	{
  		
  		/// <summary>Parses field's values as byte (using {@link
  		/// FieldCache#getBytes} and sorts by ascending value 
  		/// </summary>
  		public sealed class ByteComparator:FieldComparator
  		{
  			private sbyte[] values;
  			private sbyte[] currentReaderValues;
  			private System.String field;
  			private ByteParser parser;
  			private sbyte bottom;
  			
  			internal ByteComparator(int numHits, System.String field, Lucene.Net.Search.Parser parser)
  			{
  				values = new sbyte[numHits];
  				this.field = field;
  				this.parser = (ByteParser) parser;
  			}
  			
  			public override int Compare(int slot1, int slot2)
  			{
  				return values[slot1] - values[slot2];
  			}
  			
  			public override int CompareBottom(int doc)
  			{
  				return bottom - currentReaderValues[doc];
  			}
  			
  			public override void  Copy(int slot, int doc)
  			{
  				values[slot] = currentReaderValues[doc];
  			}
  			
  			public override void  SetNextReader(IndexReader reader, int docBase)
  			{
  				currentReaderValues = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetBytes(reader, field, parser);
  			}
  			
  			public override void  SetBottom(int bottom)
  			{
  				this.bottom = values[bottom];
  			}
  			
  			public override System.IComparable Value(int slot)
  			{
  				return (sbyte) values[slot];
  			}
  		}
  		
  		/// <summary>Sorts by ascending docID </summary>
  		public sealed class DocComparator:FieldComparator
  		{
  			private int[] docIDs;
  			private int docBase;
  			private int bottom;
  			
  			internal DocComparator(int numHits)
  			{
  				docIDs = new int[numHits];
  			}
  			
  			public override int Compare(int slot1, int slot2)
  			{
  				// No overflow risk because docIDs are non-negative
  				return docIDs[slot1] - docIDs[slot2];
  			}
  			
  			public override int CompareBottom(int doc)
  			{
  				// No overflow risk because docIDs are non-negative
  				return bottom - (docBase + doc);
  			}
  			
  			public override void  Copy(int slot, int doc)
  			{
  				docIDs[slot] = docBase + doc;
  			}
  			
  			public override void  SetNextReader(IndexReader reader, int docBase)
  			{
  				// TODO: can we "map" our docIDs to the current
  				// reader? saves having to then subtract on every
  				// compare call
  				this.docBase = docBase;
  			}
  			
  			public override void  SetBottom(int bottom)
  			{
  				this.bottom = docIDs[bottom];
  			}
  			
  			public override System.IComparable Value(int slot)
  			{
  				return (System.Int32) docIDs[slot];
  			}
  		}
  		
  		/// <summary>Parses field's values as double (using {@link
  		/// FieldCache#getDoubles} and sorts by ascending value 
  		/// </summary>
  		public sealed class DoubleComparator:FieldComparator
  		{
  			private double[] values;
  			private double[] currentReaderValues;
  			private System.String field;
  			private DoubleParser parser;
  			private double bottom;
  			
  			internal DoubleComparator(int numHits, System.String field, Lucene.Net.Search.Parser parser)
  			{
  				values = new double[numHits];
  				this.field = field;
  				this.parser = (DoubleParser) parser;
  			}
  			
  			public override int Compare(int slot1, int slot2)
  			{
  				double v1 = values[slot1];
  				double v2 = values[slot2];
  				if (v1 > v2)
  				{
  					return 1;
  				}
  				else if (v1 < v2)
  				{
  					return - 1;
  				}
  				else
  				{
  					return 0;
  				}
  			}
  			
  			public override int CompareBottom(int doc)
  			{
  				double v2 = currentReaderValues[doc];
  
gt: 				if (bottom > v2)