Index: ../lucene-clean/src/java/org/apache/lucene/search/SortField.java
===================================================================
--- ../lucene-clean/src/java/org/apache/lucene/search/SortField.java	(revision 583654)
+++ ../lucene-clean/src/java/org/apache/lucene/search/SortField.java	Mon Oct 22 14:55:56 EDT 2007
@@ -60,6 +60,14 @@
    * lower values are at the front. */
   public static final int FLOAT = 5;
 
+  /** Sort using term values as encoded Longs.  Sort values are Long and
+   * lower values are at the front. */
+  public static final int LONG = 6;
+
+  /** Sort using term values as encoded Doubles.  Sort values are Double and
+   * lower values are at the front. */
+  public static final int DOUBLE = 7;
+
   /** Sort using a custom Comparator.  Sort values are any Comparable and
    * sorting is done according to natural order. */
   public static final int CUSTOM = 9;
Index: ../lucene-clean/src/java/org/apache/lucene/search/LongDoubleFieldCacheImpl.java
===================================================================
--- ../lucene-clean/src/java/org/apache/lucene/search/LongDoubleFieldCacheImpl.java	Mon Oct 22 15:00:18 EDT 2007
+++ ../lucene-clean/src/java/org/apache/lucene/search/LongDoubleFieldCacheImpl.java	Mon Oct 22 15:00:18 EDT 2007
@@ -0,0 +1,105 @@
+package org.apache.lucene.search;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermDocs;
+import org.apache.lucene.index.TermEnum;
+
+import java.io.IOException;
+
+
+/**
+ *
+ *
+ **/
+class LongDoubleFieldCacheImpl extends FieldCacheImpl implements LongDoubleFieldCache{
+  private static final LongParser LONG_PARSER = new LongParser() {
+      public long parseLong(String value) {
+        return Long.parseLong(value);
+      }
+  };
+
+  private static final DoubleParser DOUBLE_PARSER = new DoubleParser() {
+      public double parseDouble(String value) {
+        return Double.parseDouble(value);
+      }
+  };
+
+  public long[] getLongs(IndexReader reader, String field) throws IOException {
+    return getLongs(reader, field, LONG_PARSER);
+  }
+
+  // inherit javadocs
+  public long[] getLongs(IndexReader reader, String field, LongParser parser)
+      throws IOException {
+    return (long[]) longsCache.get(reader, new Entry(field, parser));
+  }
+
+  Cache longsCache = new Cache() {
+
+    protected Object createValue(IndexReader reader, Object entryKey)
+        throws IOException {
+      Entry entry = (Entry) entryKey;
+      String field = entry.field;
+      LongParser parser = (LongParser) entry.custom;
+      final long[] retArray = new long[reader.maxDoc()];
+      TermDocs termDocs = reader.termDocs();
+      TermEnum termEnum = reader.terms (new Term(field, ""));
+      try {
+        do {
+          Term term = termEnum.term();
+          if (term==null || term.field() != field) break;
+          long termval = parser.parseLong(term.text());
+          termDocs.seek (termEnum);
+          while (termDocs.next()) {
+            retArray[termDocs.doc()] = termval;
+          }
+        } while (termEnum.next());
+      } finally {
+        termDocs.close();
+        termEnum.close();
+      }
+      return retArray;
+    }
+  };
+
+  // inherit javadocs
+  public double[] getDoubles(IndexReader reader, String field)
+    throws IOException {
+    return getDoubles(reader, field, DOUBLE_PARSER);
+  }
+
+  // inherit javadocs
+  public double[] getDoubles(IndexReader reader, String field, DoubleParser parser)
+      throws IOException {
+    return (double[]) doublesCache.get(reader, new Entry(field, parser));
+  }
+
+  Cache doublesCache = new Cache() {
+
+    protected Object createValue(IndexReader reader, Object entryKey)
+        throws IOException {
+      Entry entry = (Entry) entryKey;
+      String field = entry.field;
+      DoubleParser parser = (DoubleParser) entry.custom;
+      final double[] retArray = new double[reader.maxDoc()];
+      TermDocs termDocs = reader.termDocs();
+      TermEnum termEnum = reader.terms (new Term (field, ""));
+      try {
+        do {
+          Term term = termEnum.term();
+          if (term==null || term.field() != field) break;
+          double termval = parser.parseDouble(term.text());
+          termDocs.seek (termEnum);
+          while (termDocs.next()) {
+            retArray[termDocs.doc()] = termval;
+          }
+        } while (termEnum.next());
+      } finally {
+        termDocs.close();
+        termEnum.close();
+      }
+      return retArray;
+    }
+  };
+}
Index: ../lucene-clean/src/java/org/apache/lucene/search/LongDoubleFieldCache.java
===================================================================
--- ../lucene-clean/src/java/org/apache/lucene/search/LongDoubleFieldCache.java	Mon Oct 22 14:55:56 EDT 2007
+++ ../lucene-clean/src/java/org/apache/lucene/search/LongDoubleFieldCache.java	Mon Oct 22 14:55:56 EDT 2007
@@ -0,0 +1,88 @@
+package org.apache.lucene.search;
+
+import org.apache.lucene.index.IndexReader;
+
+import java.io.IOException;
+
+
+/**
+ *
+ *
+ **/
+public interface LongDoubleFieldCache extends FieldCache {
+  public interface LongParser {
+    /**
+     * Return an long representation of this field's value.
+     */
+    public long parseLong(String string);
+  }
+
+  public interface DoubleParser {
+    /**
+     * Return an long representation of this field's value.
+     */
+    public double parseDouble(String string);
+  }
+
+  public static LongDoubleFieldCache LD_DEFAULT = new LongDoubleFieldCacheImpl();
+
+  /**
+   * Checks the internal cache for an appropriate entry, and if none is
+   * found, reads the terms in <code>field</code> as integers and returns an array
+   * of size <code>reader.maxDoc()</code> of the value each document
+   * has in the given field.
+   *
+   * @param reader Used to get field values.
+   * @param field  Which field contains the integers.
+   * @return The values in the given field for each document.
+   * @throws java.io.IOException If any error occurs.
+   */
+  public long[] getLongs(IndexReader reader, String field)
+          throws IOException;
+
+  /**
+   * Checks the internal cache for an appropriate entry, and if none is found,
+   * reads the terms in <code>field</code> as integers and returns an array of
+   * size <code>reader.maxDoc()</code> of the value each document has in the
+   * given field.
+   *
+   * @param reader Used to get field values.
+   * @param field  Which field contains the integers.
+   * @param parser Computes integer for string values.
+   * @return The values in the given field for each document.
+   * @throws IOException If any error occurs.
+   */
+  public long[] getLongs(IndexReader reader, String field, LongParser parser)
+          throws IOException;
+
+
+  /**
+   * Checks the internal cache for an appropriate entry, and if none is
+   * found, reads the terms in <code>field</code> as integers and returns an array
+   * of size <code>reader.maxDoc()</code> of the value each document
+   * has in the given field.
+   *
+   * @param reader Used to get field values.
+   * @param field  Which field contains the integers.
+   * @return The values in the given field for each document.
+   * @throws IOException If any error occurs.
+   */
+  public double[] getDoubles(IndexReader reader, String field)
+          throws IOException;
+
+  /**
+   * Checks the internal cache for an appropriate entry, and if none is found,
+   * reads the terms in <code>field</code> as integers and returns an array of
+   * size <code>reader.maxDoc()</code> of the value each document has in the
+   * given field.
+   *
+   * @param reader Used to get field values.
+   * @param field  Which field contains the integers.
+   * @param parser Computes integer for string values.
+   * @return The values in the given field for each document.
+   * @throws IOException If any error occurs.
+   */
+  public double[] getDoubles(IndexReader reader, String field, DoubleParser parser)
+          throws IOException;
+
+}
Index: ../lucene-clean/src/java/org/apache/lucene/search/FieldDocSortedHitQueue.java
===================================================================
--- ../lucene-clean/src/java/org/apache/lucene/search/FieldDocSortedHitQueue.java	(revision 583654)
+++ ../lucene-clean/src/java/org/apache/lucene/search/FieldDocSortedHitQueue.java	Mon Oct 22 14:55:56 EDT 2007
@@ -109,20 +109,29 @@
 		for (int i=0; i<n && c==0; ++i) {
 			final int type = fields[i].getType();
 			switch (type) {
-				case SortField.SCORE:
+				case SortField.SCORE:{
 					float r1 = ((Float)docA.fields[i]).floatValue();
 					float r2 = ((Float)docB.fields[i]).floatValue();
 					if (r1 > r2) c = -1;
 					if (r1 < r2) c = 1;
 					break;
+        }
-				case SortField.DOC:
+        case SortField.DOC:
-				case SortField.INT:
+				case SortField.INT:{
 					int i1 = ((Integer)docA.fields[i]).intValue();
 					int i2 = ((Integer)docB.fields[i]).intValue();
 					if (i1 < i2) c = -1;
 					if (i1 > i2) c = 1;
 					break;
-				case SortField.STRING:
+        }
+        case SortField.LONG:{
+					long l1 = ((Long)docA.fields[i]).longValue();
+					long l2 = ((Long)docB.fields[i]).longValue();
+					if (l1 < l2) c = -1;
+					if (l1 > l2) c = 1;
+					break;
+        }
+        case SortField.STRING:{
 					String s1 = (String) docA.fields[i];
 					String s2 = (String) docB.fields[i];
 					// null values need to be sorted first, because of how FieldCache.getStringIndex()
@@ -136,24 +145,36 @@
 						c = collators[i].compare (s1, s2);
 					}
 					break;
-				case SortField.FLOAT:
+        }
+        case SortField.FLOAT:{
 					float f1 = ((Float)docA.fields[i]).floatValue();
 					float f2 = ((Float)docB.fields[i]).floatValue();
 					if (f1 < f2) c = -1;
 					if (f1 > f2) c = 1;
 					break;
-				case SortField.CUSTOM:
+        }
+        case SortField.DOUBLE:{
+					double d1 = ((Double)docA.fields[i]).doubleValue();
+					double d2 = ((Double)docB.fields[i]).doubleValue();
+					if (d1 < d2) c = -1;
+					if (d1 > d2) c = 1;
+					break;
+        }
+        case SortField.CUSTOM:{
 					c = docA.fields[i].compareTo (docB.fields[i]);
 					break;
-				case SortField.AUTO:
+        }
+        case SortField.AUTO:{
 					// we cannot handle this - even if we determine the type of object (Float or
 					// Integer), we don't necessarily know how to compare them (both SCORE and
 					// FLOAT contain floats, but are sorted opposite of each other). Before
 					// we get here, each AUTO should have been replaced with its actual value.
 					throw new RuntimeException ("FieldDocSortedHitQueue cannot use an AUTO SortField");
-				default:
+        }
+        default:{
 					throw new RuntimeException ("invalid SortField type: "+type);
-			}
+        }
+      }
 			if (fields[i].getReverse()) {
 				c = -c;
 			}
Index: ../lucene-clean/src/java/org/apache/lucene/search/FieldSortedHitQueue.java
===================================================================
--- ../lucene-clean/src/java/org/apache/lucene/search/FieldSortedHitQueue.java	(revision 583654)
+++ ../lucene-clean/src/java/org/apache/lucene/search/FieldSortedHitQueue.java	Mon Oct 22 15:00:18 EDT 2007
@@ -21,8 +21,8 @@
 import org.apache.lucene.util.PriorityQueue;
 
 import java.io.IOException;
-import java.util.Locale;
 import java.text.Collator;
+import java.util.Locale;
 
 /**
  * Expert: A hit queue for sorting by hits by terms in more than one field.
@@ -177,6 +177,12 @@
         case SortField.FLOAT:
           comparator = comparatorFloat (reader, fieldname);
           break;
+        case SortField.LONG:
+          comparator = comparatorLong(reader, fieldname);
+          break;
+        case SortField.DOUBLE:
+          comparator = comparatorDouble(reader, fieldname);
+          break;
         case SortField.STRING:
           if (locale != null) comparator = comparatorStringLocale (reader, fieldname, locale);
           else comparator = comparatorString (reader, fieldname);
@@ -223,6 +229,38 @@
   }
 
   /**
+   * Returns a comparator for sorting hits according to a field containing integers.
+   * @param reader  Index to use.
+   * @param fieldname  Fieldable containg integer values.
+   * @return  Comparator for sorting hits.
+   * @throws IOException If an error occurs reading the index.
+   */
+  static ScoreDocComparator comparatorLong (final IndexReader reader, final String fieldname)
+  throws IOException {
+    final String field = fieldname.intern();
+    final long[] fieldOrder = LongDoubleFieldCache.LD_DEFAULT.getLongs (reader, field);
+    return new ScoreDocComparator() {
+
+      public final int compare (final ScoreDoc i, final ScoreDoc j) {
+        final long li = fieldOrder[i.doc];
+        final long lj = fieldOrder[j.doc];
+        if (li < lj) return -1;
+        if (li > lj) return 1;
+        return 0;
+      }
+
+      public Comparable sortValue (final ScoreDoc i) {
+        return new Long(fieldOrder[i.doc]);
+      }
+
+      public int sortType() {
+        return SortField.LONG;
+      }
+    };
+  }
+
+
+  /**
    * Returns a comparator for sorting hits according to a field containing floats.
    * @param reader  Index to use.
    * @param fieldname  Fieldable containg float values.
@@ -254,6 +292,37 @@
   }
 
   /**
+   * Returns a comparator for sorting hits according to a field containing doubles.
+   * @param reader  Index to use.
+   * @param fieldname  Fieldable containg float values.
+   * @return  Comparator for sorting hits.
+   * @throws IOException If an error occurs reading the index.
+   */
+  static ScoreDocComparator comparatorDouble(final IndexReader reader, final String fieldname)
+  throws IOException {
+    final String field = fieldname.intern();
+    final double[] fieldOrder = LongDoubleFieldCache.LD_DEFAULT.getDoubles (reader, field);
+    return new ScoreDocComparator () {
+
+      public final int compare (final ScoreDoc i, final ScoreDoc j) {
+        final double di = fieldOrder[i.doc];
+        final double dj = fieldOrder[j.doc];
+        if (di < dj) return -1;
+        if (di > dj) return 1;
+        return 0;
+      }
+
+      public Comparable sortValue (final ScoreDoc i) {
+        return new Double (fieldOrder[i.doc]);
+      }
+
+      public int sortType() {
+        return SortField.DOUBLE;
+      }
+    };
+  }
+
+  /**
    * Returns a comparator for sorting hits according to a field containing strings.
    * @param reader  Index to use.
    * @param fieldname  Fieldable containg string values.
Index: ../lucene-clean/CHANGES.txt
===================================================================
--- ../lucene-clean/CHANGES.txt	(revision 587210)
+++ ../lucene-clean/CHANGES.txt	Mon Oct 22 15:25:39 EDT 2007
@@ -154,6 +154,8 @@
     obtained or released, throwing an exception if an illegal lock
     obtain occurred.  (Patrick Kimber vis Mike McCandless)
 
+  6. LUCENE-1015: Added FieldCache extension to support doubles and longs.  (Grant Ingersoll)
+
 Optimizations
 
  1. LUCENE-937: CachingTokenFilter now uses an iterator to access the 
