You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by rm...@apache.org on 2016/03/20 21:37:52 UTC

lucene-solr:branch_6_0: LUCENE-7117, LUCENE-7118: Remove multidimensional arrays from PointRangeQuery

Repository: lucene-solr
Updated Branches:
  refs/heads/branch_6_0 2ea8d4cd7 -> d8c4e6977


LUCENE-7117, LUCENE-7118: Remove multidimensional arrays from PointRangeQuery


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/d8c4e697
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/d8c4e697
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/d8c4e697

Branch: refs/heads/branch_6_0
Commit: d8c4e6977b0e93c538813f1db1dd67fcfc199356
Parents: 2ea8d4c
Author: Robert Muir <rm...@apache.org>
Authored: Sun Mar 20 16:05:17 2016 -0400
Committer: Robert Muir <rm...@apache.org>
Committed: Sun Mar 20 16:37:12 2016 -0400

----------------------------------------------------------------------
 .../org/apache/lucene/document/BinaryPoint.java |   2 +-
 .../org/apache/lucene/document/DoublePoint.java |  12 +-
 .../org/apache/lucene/document/FloatPoint.java  |  12 +-
 .../org/apache/lucene/document/IntPoint.java    |  12 +-
 .../org/apache/lucene/document/LongPoint.java   |  12 +-
 .../apache/lucene/search/PointRangeQuery.java   |  88 +++++-------
 .../apache/lucene/search/TestPointQueries.java  | 138 +++++++++++--------
 .../apache/lucene/document/BigIntegerPoint.java |  12 +-
 .../lucene/document/InetAddressPoint.java       |   6 +-
 .../org/apache/lucene/document/LatLonPoint.java |  32 ++---
 .../lucene/document/TestBigIntegerPoint.java    |  24 ++--
 .../lucene/document/TestInetAddressPoint.java   |  34 +++--
 .../apache/lucene/document/TestLatLonPoint.java |  28 ++--
 13 files changed, 188 insertions(+), 224 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d8c4e697/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java b/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java
index 4e27d81..60fd9d63 100644
--- a/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java
+++ b/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java
@@ -173,7 +173,7 @@ public final class BinaryPoint extends Field {
    * @return a query matching documents within this range.
    */
   public static Query newRangeQuery(String field, byte[][] lowerValue, byte[][] upperValue) {
-    return new PointRangeQuery(field, lowerValue, upperValue) {
+    return new PointRangeQuery(field, pack(lowerValue).bytes, pack(upperValue).bytes, lowerValue.length) {
       @Override
       protected String toString(int dimension, byte[] value) {
         assert value != null;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d8c4e697/lucene/core/src/java/org/apache/lucene/document/DoublePoint.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/DoublePoint.java b/lucene/core/src/java/org/apache/lucene/document/DoublePoint.java
index 1eb1d7e..53de127 100644
--- a/lucene/core/src/java/org/apache/lucene/document/DoublePoint.java
+++ b/lucene/core/src/java/org/apache/lucene/document/DoublePoint.java
@@ -126,16 +126,6 @@ public final class DoublePoint extends Field {
     return result.toString();
   }
   
-  /** Encode n-dimensional double point into binary encoding */
-  private static byte[][] encode(double value[]) {
-    byte[][] encoded = new byte[value.length][];
-    for (int i = 0; i < value.length; i++) {
-      encoded[i] = new byte[Double.BYTES];
-      encodeDimension(value[i], encoded[i], 0);
-    }
-    return encoded;
-  }
-  
   // public helper methods (e.g. for queries)
   
   /** Encode single double dimension */
@@ -207,7 +197,7 @@ public final class DoublePoint extends Field {
    */
   public static Query newRangeQuery(String field, double[] lowerValue, double[] upperValue) {
     PointRangeQuery.checkArgs(field, lowerValue, upperValue);
-    return new PointRangeQuery(field, encode(lowerValue), encode(upperValue)) {
+    return new PointRangeQuery(field, pack(lowerValue).bytes, pack(upperValue).bytes, lowerValue.length) {
       @Override
       protected String toString(int dimension, byte[] value) {
         return Double.toString(decodeDimension(value, 0));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d8c4e697/lucene/core/src/java/org/apache/lucene/document/FloatPoint.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/FloatPoint.java b/lucene/core/src/java/org/apache/lucene/document/FloatPoint.java
index 08192e5..ab20928 100644
--- a/lucene/core/src/java/org/apache/lucene/document/FloatPoint.java
+++ b/lucene/core/src/java/org/apache/lucene/document/FloatPoint.java
@@ -126,16 +126,6 @@ public final class FloatPoint extends Field {
     return result.toString();
   }
   
-  /** Encode n-dimensional float values into binary encoding */
-  private static byte[][] encode(float value[]) {
-    byte[][] encoded = new byte[value.length][];
-    for (int i = 0; i < value.length; i++) {
-      encoded[i] = new byte[Float.BYTES];
-      encodeDimension(value[i], encoded[i], 0);
-    }
-    return encoded;
-  }
-  
   // public helper methods (e.g. for queries)
   
   /** Encode single float dimension */
@@ -207,7 +197,7 @@ public final class FloatPoint extends Field {
    */
   public static Query newRangeQuery(String field, float[] lowerValue, float[] upperValue) {
     PointRangeQuery.checkArgs(field, lowerValue, upperValue);
-    return new PointRangeQuery(field, encode(lowerValue), encode(upperValue)) {
+    return new PointRangeQuery(field, pack(lowerValue).bytes, pack(upperValue).bytes, lowerValue.length) {
       @Override
       protected String toString(int dimension, byte[] value) {
         return Float.toString(decodeDimension(value, 0));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d8c4e697/lucene/core/src/java/org/apache/lucene/document/IntPoint.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/IntPoint.java b/lucene/core/src/java/org/apache/lucene/document/IntPoint.java
index c40a4b7..db24fc9 100644
--- a/lucene/core/src/java/org/apache/lucene/document/IntPoint.java
+++ b/lucene/core/src/java/org/apache/lucene/document/IntPoint.java
@@ -125,16 +125,6 @@ public final class IntPoint extends Field {
     result.append('>');
     return result.toString();
   }
-
-  /** Encode n-dimensional integer values into binary encoding */
-  private static byte[][] encode(int value[]) {
-    byte[][] encoded = new byte[value.length][];
-    for (int i = 0; i < value.length; i++) {
-      encoded[i] = new byte[Integer.BYTES];
-      encodeDimension(value[i], encoded[i], 0);
-    }
-    return encoded;
-  }
   
   // public helper methods (e.g. for queries)
   
@@ -205,7 +195,7 @@ public final class IntPoint extends Field {
    */
   public static Query newRangeQuery(String field, int[] lowerValue, int[] upperValue) {
     PointRangeQuery.checkArgs(field, lowerValue, upperValue);
-    return new PointRangeQuery(field, encode(lowerValue), encode(upperValue)) {
+    return new PointRangeQuery(field, pack(lowerValue).bytes, pack(upperValue).bytes, lowerValue.length) {
       @Override
       protected String toString(int dimension, byte[] value) {
         return Integer.toString(decodeDimension(value, 0));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d8c4e697/lucene/core/src/java/org/apache/lucene/document/LongPoint.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/LongPoint.java b/lucene/core/src/java/org/apache/lucene/document/LongPoint.java
index 46bf93c..ab2cb6f 100644
--- a/lucene/core/src/java/org/apache/lucene/document/LongPoint.java
+++ b/lucene/core/src/java/org/apache/lucene/document/LongPoint.java
@@ -126,16 +126,6 @@ public final class LongPoint extends Field {
     return result.toString();
   }
   
-  /** Encode n-dimensional long values into binary encoding */
-  private static byte[][] encode(long value[]) {
-    byte[][] encoded = new byte[value.length][];
-    for (int i = 0; i < value.length; i++) {
-      encoded[i] = new byte[Long.BYTES];
-      encodeDimension(value[i], encoded[i], 0);
-    }
-    return encoded;
-  }
-  
   // public helper methods (e.g. for queries)
   
   /** Encode single long dimension */
@@ -205,7 +195,7 @@ public final class LongPoint extends Field {
    */
   public static Query newRangeQuery(String field, long[] lowerValue, long[] upperValue) {
     PointRangeQuery.checkArgs(field, lowerValue, upperValue);
-    return new PointRangeQuery(field, encode(lowerValue), encode(upperValue)) {
+    return new PointRangeQuery(field, pack(lowerValue).bytes, pack(upperValue).bytes, lowerValue.length) {
       @Override
       protected String toString(int dimension, byte[] value) {
         return Long.toString(decodeDimension(value, 0));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d8c4e697/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java b/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java
index 9384d23..37580e0 100644
--- a/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java
@@ -47,8 +47,8 @@ public abstract class PointRangeQuery extends Query {
   final String field;
   final int numDims;
   final int bytesPerDim;
-  final byte[][] lowerPoint;
-  final byte[][] upperPoint;
+  final byte[] lowerPoint;
+  final byte[] upperPoint;
 
   /** 
    * Expert: create a multidimensional range query for point values.
@@ -56,40 +56,26 @@ public abstract class PointRangeQuery extends Query {
    * @param field field name. must not be {@code null}.
    * @param lowerPoint lower portion of the range (inclusive).
    * @param upperPoint upper portion of the range (inclusive).
+   * @param numDims number of dimensions.
    * @throws IllegalArgumentException if {@code field} is null, or if {@code lowerValue.length != upperValue.length}
    */
-  protected PointRangeQuery(String field, byte[][] lowerPoint, byte[][] upperPoint) {
+  protected PointRangeQuery(String field, byte[] lowerPoint, byte[] upperPoint, int numDims) {
     checkArgs(field, lowerPoint, upperPoint);
     this.field = field;
     if (lowerPoint.length == 0) {
       throw new IllegalArgumentException("lowerPoint has length of zero");
     }
-    this.numDims = lowerPoint.length;
-
-    if (upperPoint.length != numDims) {
+    if (lowerPoint.length % numDims != 0) {
+      throw new IllegalArgumentException("lowerPoint is not a fixed multiple of numDims");
+    }
+    if (upperPoint.length != upperPoint.length) {
       throw new IllegalArgumentException("lowerPoint has length=" + numDims + " but upperPoint has different length=" + upperPoint.length);
     }
+    this.numDims = numDims;
+    this.bytesPerDim = lowerPoint.length / numDims;
+
     this.lowerPoint = lowerPoint;
     this.upperPoint = upperPoint;
-
-    if (lowerPoint[0] == null) {
-      throw new IllegalArgumentException("lowerPoint[0] is null");
-    }
-    this.bytesPerDim = lowerPoint[0].length;
-    for (int i = 0; i < numDims; i++) {
-      if (lowerPoint[i] == null) {
-        throw new IllegalArgumentException("lowerPoint[" + i + "] is null");
-      }
-      if (upperPoint[i] == null) {
-        throw new IllegalArgumentException("upperPoint[" + i + "] is null");
-      }
-      if (lowerPoint[i].length != bytesPerDim) {
-        throw new IllegalArgumentException("all dimensions must have same bytes length, but saw " + bytesPerDim + " and " + lowerPoint[i].length);
-      }
-      if (upperPoint[i].length != bytesPerDim) {
-        throw new IllegalArgumentException("all dimensions must have same bytes length, but saw " + bytesPerDim + " and " + upperPoint[i].length);
-      }
-    }
   }
 
   /** 
@@ -116,8 +102,7 @@ public abstract class PointRangeQuery extends Query {
 
     return new ConstantScoreWeight(this) {
 
-      private DocIdSet buildMatchingDocIdSet(LeafReader reader, PointValues values,
-          byte[] packedLower, byte[] packedUpper) throws IOException {
+      private DocIdSet buildMatchingDocIdSet(LeafReader reader, PointValues values) throws IOException {
         DocIdSetBuilder result = new DocIdSetBuilder(reader.maxDoc());
 
         values.intersect(field,
@@ -137,11 +122,11 @@ public abstract class PointRangeQuery extends Query {
               public void visit(int docID, byte[] packedValue) {
                 for(int dim=0;dim<numDims;dim++) {
                   int offset = dim*bytesPerDim;
-                  if (StringHelper.compare(bytesPerDim, packedValue, offset, packedLower, offset) < 0) {
+                  if (StringHelper.compare(bytesPerDim, packedValue, offset, lowerPoint, offset) < 0) {
                     // Doc's value is too low, in this dimension
                     return;
                   }
-                  if (StringHelper.compare(bytesPerDim, packedValue, offset, packedUpper, offset) > 0) {
+                  if (StringHelper.compare(bytesPerDim, packedValue, offset, upperPoint, offset) > 0) {
                     // Doc's value is too high, in this dimension
                     return;
                   }
@@ -159,13 +144,13 @@ public abstract class PointRangeQuery extends Query {
                 for(int dim=0;dim<numDims;dim++) {
                   int offset = dim*bytesPerDim;
 
-                  if (StringHelper.compare(bytesPerDim, minPackedValue, offset, packedUpper, offset) > 0 ||
-                      StringHelper.compare(bytesPerDim, maxPackedValue, offset, packedLower, offset) < 0) {
+                  if (StringHelper.compare(bytesPerDim, minPackedValue, offset, upperPoint, offset) > 0 ||
+                      StringHelper.compare(bytesPerDim, maxPackedValue, offset, lowerPoint, offset) < 0) {
                     return Relation.CELL_OUTSIDE_QUERY;
                   }
 
-                  crosses |= StringHelper.compare(bytesPerDim, minPackedValue, offset, packedLower, offset) < 0 ||
-                    StringHelper.compare(bytesPerDim, maxPackedValue, offset, packedUpper, offset) > 0;
+                  crosses |= StringHelper.compare(bytesPerDim, minPackedValue, offset, lowerPoint, offset) < 0 ||
+                    StringHelper.compare(bytesPerDim, maxPackedValue, offset, upperPoint, offset) > 0;
                 }
 
                 if (crosses) {
@@ -197,16 +182,6 @@ public abstract class PointRangeQuery extends Query {
         if (bytesPerDim != fieldInfo.getPointNumBytes()) {
           throw new IllegalArgumentException("field=\"" + field + "\" was indexed with bytesPerDim=" + fieldInfo.getPointNumBytes() + " but this query has bytesPerDim=" + bytesPerDim);
         }
-        int bytesPerDim = fieldInfo.getPointNumBytes();
-
-        byte[] packedLower = new byte[numDims * bytesPerDim];
-        byte[] packedUpper = new byte[numDims * bytesPerDim];
-
-        // Carefully pack lower and upper bounds
-        for(int dim=0;dim<numDims;dim++) {
-          System.arraycopy(lowerPoint[dim], 0, packedLower, dim*bytesPerDim, bytesPerDim);
-          System.arraycopy(upperPoint[dim], 0, packedUpper, dim*bytesPerDim, bytesPerDim);
-        }
 
         boolean allDocsMatch;
         if (values.getDocCount(field) == reader.maxDoc()) {
@@ -215,8 +190,8 @@ public abstract class PointRangeQuery extends Query {
           allDocsMatch = true;
           for (int i = 0; i < numDims; ++i) {
             int offset = i * bytesPerDim;
-            if (StringHelper.compare(bytesPerDim, packedLower, offset, fieldPackedLower, offset) > 0
-                || StringHelper.compare(bytesPerDim, packedUpper, offset, fieldPackedUpper, offset) < 0) {
+            if (StringHelper.compare(bytesPerDim, lowerPoint, offset, fieldPackedLower, offset) > 0
+                || StringHelper.compare(bytesPerDim, upperPoint, offset, fieldPackedUpper, offset) < 0) {
               allDocsMatch = false;
               break;
             }
@@ -230,7 +205,7 @@ public abstract class PointRangeQuery extends Query {
           // all docs have a value and all points are within bounds, so everything matches
           iterator = DocIdSetIterator.all(reader.maxDoc());
         } else {
-          iterator = buildMatchingDocIdSet(reader, values, packedLower, packedUpper).iterator();
+          iterator = buildMatchingDocIdSet(reader, values).iterator();
         }
 
         return new ConstantScoreScorer(this, score(), iterator);
@@ -263,15 +238,12 @@ public abstract class PointRangeQuery extends Query {
       return false;
     }
 
-    // Cannot use Arrays.equals here, because it in turn uses byte[].equals
-    // to compare each value, which only uses "=="
-    for(int dim=0;dim<numDims;dim++) {
-      if (Arrays.equals(lowerPoint[dim], q.lowerPoint[dim]) == false) {
-        return false;
-      }
-      if (Arrays.equals(upperPoint[dim], q.upperPoint[dim]) == false) {
-        return false;
-      }
+    if (!Arrays.equals(lowerPoint, q.lowerPoint)) {
+      return false;
+    }
+    
+    if (!Arrays.equals(upperPoint, q.upperPoint)) {
+      return false;
     }
 
     return true;
@@ -290,11 +262,13 @@ public abstract class PointRangeQuery extends Query {
       if (i > 0) {
         sb.append(',');
       }
+      
+      int startOffset = bytesPerDim * i;
 
       sb.append('[');
-      sb.append(toString(i, lowerPoint[i]));
+      sb.append(toString(i, Arrays.copyOfRange(lowerPoint, startOffset, startOffset + bytesPerDim)));
       sb.append(" TO ");
-      sb.append(toString(i, upperPoint[i]));
+      sb.append(toString(i, Arrays.copyOfRange(upperPoint, startOffset, startOffset + bytesPerDim)));
       sb.append(']');
     }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d8c4e697/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java b/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java
index c72ab44..b4a586d 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java
@@ -1896,82 +1896,112 @@ public class TestPointQueries extends LuceneTestCase {
   }
 
   public void testPointRangeEquals() {
-    Query q = IntPoint.newRangeQuery("a", 0, 1000);
-    assertEquals(q, IntPoint.newRangeQuery("a", 0, 1000));
-    assertFalse(q.equals(IntPoint.newRangeQuery("a", 1, 1000)));
-
-    q = LongPoint.newRangeQuery("a", 0, 1000);
-    assertEquals(q, LongPoint.newRangeQuery("a", 0, 1000));
-    assertFalse(q.equals(LongPoint.newRangeQuery("a", 1, 1000)));
-
-    q = FloatPoint.newRangeQuery("a", 0, 1000);
-    assertEquals(q, FloatPoint.newRangeQuery("a", 0, 1000));
-    assertFalse(q.equals(FloatPoint.newRangeQuery("a", 1, 1000)));
-
-    q = DoublePoint.newRangeQuery("a", 0, 1000);
-    assertEquals(q, DoublePoint.newRangeQuery("a", 0, 1000));
-    assertFalse(q.equals(DoublePoint.newRangeQuery("a", 1, 1000)));
+    Query q1 = IntPoint.newRangeQuery("a", 0, 1000);
+    Query q2 = IntPoint.newRangeQuery("a", 0, 1000);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(IntPoint.newRangeQuery("a", 1, 1000)));
+
+    q1 = LongPoint.newRangeQuery("a", 0, 1000);
+    q2 = LongPoint.newRangeQuery("a", 0, 1000);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(LongPoint.newRangeQuery("a", 1, 1000)));
+
+    q1 = FloatPoint.newRangeQuery("a", 0, 1000);
+    q2 = FloatPoint.newRangeQuery("a", 0, 1000);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(FloatPoint.newRangeQuery("a", 1, 1000)));
+
+    q1 = DoublePoint.newRangeQuery("a", 0, 1000);
+    q2 = DoublePoint.newRangeQuery("a", 0, 1000);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(DoublePoint.newRangeQuery("a", 1, 1000)));
 
     byte[] zeros = new byte[5];
     byte[] ones = new byte[5];
     Arrays.fill(ones, (byte) 0xff);
-    q = BinaryPoint.newRangeQuery("a", new byte[][] {zeros}, new byte[][] {ones});
-    assertEquals(q, BinaryPoint.newRangeQuery("a", new byte[][] {zeros}, new byte[][] {ones}));
+    q1 = BinaryPoint.newRangeQuery("a", new byte[][] {zeros}, new byte[][] {ones});
+    q2 = BinaryPoint.newRangeQuery("a", new byte[][] {zeros}, new byte[][] {ones});
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
     byte[] other = ones.clone();
     other[2] = (byte) 5;
-    assertFalse(q.equals(BinaryPoint.newRangeQuery("a", new byte[][] {zeros}, new byte[][] {other})));
+    assertFalse(q1.equals(BinaryPoint.newRangeQuery("a", new byte[][] {zeros}, new byte[][] {other})));
   }
 
   public void testPointExactEquals() {
-    Query q = IntPoint.newExactQuery("a", 1000);
-    assertEquals(q, IntPoint.newExactQuery("a", 1000));
-    assertFalse(q.equals(IntPoint.newExactQuery("a", 1)));
-
-    q = LongPoint.newExactQuery("a", 1000);
-    assertEquals(q, LongPoint.newExactQuery("a", 1000));
-    assertFalse(q.equals(LongPoint.newExactQuery("a", 1)));
-
-    q = FloatPoint.newExactQuery("a", 1000);
-    assertEquals(q, FloatPoint.newExactQuery("a", 1000));
-    assertFalse(q.equals(FloatPoint.newExactQuery("a", 1)));
-
-    q = DoublePoint.newExactQuery("a", 1000);
-    assertEquals(q, DoublePoint.newExactQuery("a", 1000));
-    assertFalse(q.equals(DoublePoint.newExactQuery("a", 1)));
+    Query q1 = IntPoint.newExactQuery("a", 1000);
+    Query q2 = IntPoint.newExactQuery("a", 1000);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(IntPoint.newExactQuery("a", 1)));
+
+    q1 = LongPoint.newExactQuery("a", 1000);
+    q2 = LongPoint.newExactQuery("a", 1000);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(LongPoint.newExactQuery("a", 1)));
+
+    q1 = FloatPoint.newExactQuery("a", 1000);
+    q2 = FloatPoint.newExactQuery("a", 1000);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(FloatPoint.newExactQuery("a", 1)));
+
+    q1 = DoublePoint.newExactQuery("a", 1000);
+    q2 = DoublePoint.newExactQuery("a", 1000);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(DoublePoint.newExactQuery("a", 1)));
 
     byte[] ones = new byte[5];
     Arrays.fill(ones, (byte) 0xff);
-    q = BinaryPoint.newExactQuery("a", ones);
-    assertEquals(q, BinaryPoint.newExactQuery("a", ones));
+    q1 = BinaryPoint.newExactQuery("a", ones);
+    q2 = BinaryPoint.newExactQuery("a", ones);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
     byte[] other = ones.clone();
     other[2] = (byte) 5;
-    assertFalse(q.equals(BinaryPoint.newExactQuery("a", other)));
+    assertFalse(q1.equals(BinaryPoint.newExactQuery("a", other)));
   }
 
   public void testPointInSetEquals() {
-    Query q = IntPoint.newSetQuery("a", 0, 1000, 17);
-    assertEquals(q, IntPoint.newSetQuery("a", 17, 0, 1000));
-    assertFalse(q.equals(IntPoint.newSetQuery("a", 1, 17, 1000)));
-
-    q = LongPoint.newSetQuery("a", 0, 1000, 17);
-    assertEquals(q, LongPoint.newSetQuery("a", 17, 0, 1000));
-    assertFalse(q.equals(LongPoint.newSetQuery("a", 1, 17, 1000)));
-
-    q = FloatPoint.newSetQuery("a", 0, 1000, 17);
-    assertEquals(q, FloatPoint.newSetQuery("a", 17, 0, 1000));
-    assertFalse(q.equals(FloatPoint.newSetQuery("a", 1, 17, 1000)));
-
-    q = DoublePoint.newSetQuery("a", 0, 1000, 17);
-    assertEquals(q, DoublePoint.newSetQuery("a", 17, 0, 1000));
-    assertFalse(q.equals(DoublePoint.newSetQuery("a", 1, 17, 1000)));
+    Query q1 = IntPoint.newSetQuery("a", 0, 1000, 17);
+    Query q2 = IntPoint.newSetQuery("a", 17, 0, 1000);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(IntPoint.newSetQuery("a", 1, 17, 1000)));
+
+    q1 = LongPoint.newSetQuery("a", 0, 1000, 17);
+    q2 = LongPoint.newSetQuery("a", 17, 0, 1000);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(LongPoint.newSetQuery("a", 1, 17, 1000)));
+
+    q1 = FloatPoint.newSetQuery("a", 0, 1000, 17);
+    q2 = FloatPoint.newSetQuery("a", 17, 0, 1000);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(FloatPoint.newSetQuery("a", 1, 17, 1000)));
+
+    q1 = DoublePoint.newSetQuery("a", 0, 1000, 17);
+    q2 = DoublePoint.newSetQuery("a", 17, 0, 1000);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(DoublePoint.newSetQuery("a", 1, 17, 1000)));
 
     byte[] zeros = new byte[5];
     byte[] ones = new byte[5];
     Arrays.fill(ones, (byte) 0xff);
-    q = BinaryPoint.newSetQuery("a", new byte[][] {zeros, ones});
-    assertEquals(q, BinaryPoint.newSetQuery("a", new byte[][] {zeros, ones}));
+    q1 = BinaryPoint.newSetQuery("a", new byte[][] {zeros, ones});
+    q2 = BinaryPoint.newSetQuery("a", new byte[][] {zeros, ones});
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
     byte[] other = ones.clone();
     other[2] = (byte) 5;
-    assertFalse(q.equals(BinaryPoint.newSetQuery("a", new byte[][] {zeros, other})));
+    assertFalse(q1.equals(BinaryPoint.newSetQuery("a", new byte[][] {zeros, other})));
   }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d8c4e697/lucene/sandbox/src/java/org/apache/lucene/document/BigIntegerPoint.java
----------------------------------------------------------------------
diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/BigIntegerPoint.java b/lucene/sandbox/src/java/org/apache/lucene/document/BigIntegerPoint.java
index 70445d6..efbb37c 100644
--- a/lucene/sandbox/src/java/org/apache/lucene/document/BigIntegerPoint.java
+++ b/lucene/sandbox/src/java/org/apache/lucene/document/BigIntegerPoint.java
@@ -129,16 +129,6 @@ public class BigIntegerPoint extends Field {
     result.append('>');
     return result.toString();
   }
-  
-  /** sugar: Encode n-dimensional BigInteger values into binary encoding */
-  private static byte[][] encode(BigInteger value[]) {
-    byte[][] encoded = new byte[value.length][];
-    for (int i = 0; i < value.length; i++) {
-      encoded[i] = new byte[BYTES];
-      encodeDimension(value[i], encoded[i], 0);
-    }
-    return encoded;
-  }
 
   // public helper methods (e.g. for queries)
   
@@ -212,7 +202,7 @@ public class BigIntegerPoint extends Field {
    */
   public static Query newRangeQuery(String field, BigInteger[] lowerValue, BigInteger[] upperValue) {
     PointRangeQuery.checkArgs(field, lowerValue, upperValue);
-    return new PointRangeQuery(field, BigIntegerPoint.encode(lowerValue), BigIntegerPoint.encode(upperValue)) {
+    return new PointRangeQuery(field, pack(lowerValue).bytes, pack(upperValue).bytes, lowerValue.length) {
       @Override
       protected String toString(int dimension, byte[] value) {
         return BigIntegerPoint.decodeDimension(value, 0).toString();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d8c4e697/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java
----------------------------------------------------------------------
diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java b/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java
index 7abc1b6..c0739a4 100644
--- a/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java
+++ b/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java
@@ -196,11 +196,7 @@ public class InetAddressPoint extends Field {
    */
   public static Query newRangeQuery(String field, InetAddress lowerValue, InetAddress upperValue) {
     PointRangeQuery.checkArgs(field, lowerValue, upperValue);
-    byte[][] lowerBytes = new byte[1][];
-    lowerBytes[0] = encode(lowerValue);
-    byte[][] upperBytes = new byte[1][];
-    upperBytes[0] = encode(upperValue);
-    return new PointRangeQuery(field, lowerBytes, upperBytes) {
+    return new PointRangeQuery(field, encode(lowerValue), encode(upperValue), 1) {
       @Override
       protected String toString(int dimension, byte[] value) {
         return decode(value).getHostAddress(); // for ranges, the range itself is already bracketed

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d8c4e697/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java
----------------------------------------------------------------------
diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java
index fd3284b..266066c 100644
--- a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java
+++ b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java
@@ -185,13 +185,11 @@ public class LatLonPoint extends Field {
     return decodeLongitude(NumericUtils.sortableBytesToInt(src, offset));
   }
   
-  /** sugar encodes a single point as a 2D byte array */
-  private static byte[][] encode(double latitude, double longitude) {
-    byte[][] bytes = new byte[2][];
-    bytes[0] = new byte[4];
-    NumericUtils.intToSortableBytes(encodeLatitude(latitude), bytes[0], 0);
-    bytes[1] = new byte[4];
-    NumericUtils.intToSortableBytes(encodeLongitude(longitude), bytes[1], 0);
+  /** sugar encodes a single point as a byte array */
+  private static byte[] encode(double latitude, double longitude) {
+    byte[] bytes = new byte[2 * Integer.BYTES];
+    NumericUtils.intToSortableBytes(encodeLatitude(latitude), bytes, 0);
+    NumericUtils.intToSortableBytes(encodeLongitude(longitude), bytes, Integer.BYTES);
     return bytes;
   }
 
@@ -224,8 +222,8 @@ public class LatLonPoint extends Field {
    * @throws IllegalArgumentException if {@code field} is null, or the box has invalid coordinates.
    */
   public static Query newBoxQuery(String field, double minLatitude, double maxLatitude, double minLongitude, double maxLongitude) {
-    byte[][] lower = encode(minLatitude, minLongitude);
-    byte[][] upper = encode(maxLatitude, maxLongitude);
+    byte[] lower = encode(minLatitude, minLongitude);
+    byte[] upper = encode(maxLatitude, maxLongitude);
     // Crosses date line: we just rewrite into OR of two bboxes, with longitude as an open range:
     if (maxLongitude < minLongitude) {
       // Disable coord here because a multi-valued doc could match both rects and get unfairly boosted:
@@ -233,19 +231,15 @@ public class LatLonPoint extends Field {
       q.setDisableCoord(true);
 
       // E.g.: maxLon = -179, minLon = 179
-      byte[][] leftOpen = new byte[2][];
-      leftOpen[0] = lower[0];
+      byte[] leftOpen = lower.clone();
       // leave longitude open
-      leftOpen[1] = new byte[Integer.BYTES];
-      NumericUtils.intToSortableBytes(Integer.MIN_VALUE, leftOpen[1], 0);
+      NumericUtils.intToSortableBytes(Integer.MIN_VALUE, leftOpen, Integer.BYTES);
       Query left = newBoxInternal(field, leftOpen, upper);
       q.add(new BooleanClause(left, BooleanClause.Occur.SHOULD));
 
-      byte[][] rightOpen = new byte[2][];
-      rightOpen[0] = upper[0];
+      byte[] rightOpen = upper.clone();
       // leave longitude open
-      rightOpen[1] = new byte[Integer.BYTES];
-      NumericUtils.intToSortableBytes(Integer.MAX_VALUE, rightOpen[1], 0);
+      NumericUtils.intToSortableBytes(Integer.MAX_VALUE, rightOpen, Integer.BYTES);
       Query right = newBoxInternal(field, lower, rightOpen);
       q.add(new BooleanClause(right, BooleanClause.Occur.SHOULD));
       return new ConstantScoreQuery(q.build());
@@ -254,8 +248,8 @@ public class LatLonPoint extends Field {
     }
   }
   
-  private static Query newBoxInternal(String field, byte[][] min, byte[][] max) {
-    return new PointRangeQuery(field, min, max) {
+  private static Query newBoxInternal(String field, byte[] min, byte[] max) {
+    return new PointRangeQuery(field, min, max, 2) {
       @Override
       protected String toString(int dimension, byte[] value) {
         if (dimension == 0) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d8c4e697/lucene/sandbox/src/test/org/apache/lucene/document/TestBigIntegerPoint.java
----------------------------------------------------------------------
diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/TestBigIntegerPoint.java b/lucene/sandbox/src/test/org/apache/lucene/document/TestBigIntegerPoint.java
index 8f38bcd..23b5422 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/document/TestBigIntegerPoint.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/TestBigIntegerPoint.java
@@ -96,16 +96,22 @@ public class TestBigIntegerPoint extends LuceneTestCase {
   }
 
   public void testQueryEquals() throws Exception {
-    Query q = BigIntegerPoint.newRangeQuery("a", BigInteger.valueOf(0), BigInteger.valueOf(1000));
-    assertEquals(q, BigIntegerPoint.newRangeQuery("a", BigInteger.valueOf(0), BigInteger.valueOf(1000)));
-    assertFalse(q.equals(BigIntegerPoint.newRangeQuery("a", BigInteger.valueOf(1), BigInteger.valueOf(1000))));
+    Query q1 = BigIntegerPoint.newRangeQuery("a", BigInteger.valueOf(0), BigInteger.valueOf(1000));
+    Query q2 = BigIntegerPoint.newRangeQuery("a", BigInteger.valueOf(0), BigInteger.valueOf(1000));
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(BigIntegerPoint.newRangeQuery("a", BigInteger.valueOf(1), BigInteger.valueOf(1000))));
 
-    q = BigIntegerPoint.newExactQuery("a", BigInteger.valueOf(1000));
-    assertEquals(q, BigIntegerPoint.newExactQuery("a", BigInteger.valueOf(1000)));
-    assertFalse(q.equals(BigIntegerPoint.newExactQuery("a", BigInteger.valueOf(1))));
+    q1 = BigIntegerPoint.newExactQuery("a", BigInteger.valueOf(1000));
+    q2 = BigIntegerPoint.newExactQuery("a", BigInteger.valueOf(1000));
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(BigIntegerPoint.newExactQuery("a", BigInteger.valueOf(1))));
 
-    q = BigIntegerPoint.newSetQuery("a", BigInteger.valueOf(0), BigInteger.valueOf(1000), BigInteger.valueOf(17));
-    assertEquals(q, BigIntegerPoint.newSetQuery("a", BigInteger.valueOf(17), BigInteger.valueOf(0), BigInteger.valueOf(1000)));
-    assertFalse(q.equals(BigIntegerPoint.newSetQuery("a", BigInteger.valueOf(1), BigInteger.valueOf(17), BigInteger.valueOf(1000))));
+    q1 = BigIntegerPoint.newSetQuery("a", BigInteger.valueOf(0), BigInteger.valueOf(1000), BigInteger.valueOf(17));
+    q2 = BigIntegerPoint.newSetQuery("a", BigInteger.valueOf(17), BigInteger.valueOf(0), BigInteger.valueOf(1000));
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(BigIntegerPoint.newSetQuery("a", BigInteger.valueOf(1), BigInteger.valueOf(17), BigInteger.valueOf(1000))));
   }     
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d8c4e697/lucene/sandbox/src/test/org/apache/lucene/document/TestInetAddressPoint.java
----------------------------------------------------------------------
diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/TestInetAddressPoint.java b/lucene/sandbox/src/test/org/apache/lucene/document/TestInetAddressPoint.java
index c91b52b..3f3a6e9 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/document/TestInetAddressPoint.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/TestInetAddressPoint.java
@@ -92,21 +92,29 @@ public class TestInetAddressPoint extends LuceneTestCase {
   }
 
   public void testQueryEquals() throws Exception {
-    Query q = InetAddressPoint.newRangeQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.5"));
-    assertEquals(q, InetAddressPoint.newRangeQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.5")));
-    assertFalse(q.equals(InetAddressPoint.newRangeQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.7"))));
+    Query q1 = InetAddressPoint.newRangeQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.5"));
+    Query q2 = InetAddressPoint.newRangeQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.5"));
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(InetAddressPoint.newRangeQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.7"))));
 
-    q = InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.2.3.3"), 16);
-    assertEquals(q, InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.2.3.3"), 16));
-    assertFalse(q.equals(InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.1.3.5"), 16)));
-    assertFalse(q.equals(InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.2.3.5"), 24)));
+    q1 = InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.2.3.3"), 16);
+    q2 = InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.2.3.3"), 16);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.1.3.5"), 16)));
+    assertFalse(q1.equals(InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.2.3.5"), 24)));
 
-    q = InetAddressPoint.newExactQuery("a", InetAddress.getByName("1.2.3.3"));
-    assertEquals(q, InetAddressPoint.newExactQuery("a", InetAddress.getByName("1.2.3.3")));
-    assertFalse(q.equals(InetAddressPoint.newExactQuery("a", InetAddress.getByName("1.2.3.5"))));
+    q1 = InetAddressPoint.newExactQuery("a", InetAddress.getByName("1.2.3.3"));
+    q2 = InetAddressPoint.newExactQuery("a", InetAddress.getByName("1.2.3.3"));
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(InetAddressPoint.newExactQuery("a", InetAddress.getByName("1.2.3.5"))));
 
-    q = InetAddressPoint.newSetQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.5"));
-    assertEquals(q, InetAddressPoint.newSetQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.5")));
-    assertFalse(q.equals(InetAddressPoint.newSetQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.7"))));
+    q1 = InetAddressPoint.newSetQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.5"));
+    q2 = InetAddressPoint.newSetQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.5"));
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(InetAddressPoint.newSetQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.7"))));
   }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d8c4e697/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPoint.java
----------------------------------------------------------------------
diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPoint.java b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPoint.java
index 61c6754..1b2d6b2 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPoint.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPoint.java
@@ -173,21 +173,27 @@ public class TestLatLonPoint extends LuceneTestCase {
   }
 
   public void testQueryEquals() throws Exception {
-    Query q = LatLonPoint.newBoxQuery("field", 50, 70, -40, 20);
-    assertEquals(q, LatLonPoint.newBoxQuery("field", 50, 70, -40, 20));
-    assertFalse(q.equals(LatLonPoint.newBoxQuery("field", 50, 70, -40, 10)));
-
-    q = LatLonPoint.newDistanceQuery("field", 50, 70, 10000);
-    assertEquals(q, LatLonPoint.newDistanceQuery("field", 50, 70, 10000));
-    assertFalse(q.equals(LatLonPoint.newDistanceQuery("field", 50, 70, 11000)));
-    assertFalse(q.equals(LatLonPoint.newDistanceQuery("field", 50, 60, 10000)));
+    Query q1 = LatLonPoint.newBoxQuery("field", 50, 70, -40, 20);
+    Query q2 = LatLonPoint.newBoxQuery("field", 50, 70, -40, 20);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(LatLonPoint.newBoxQuery("field", 50, 70, -40, 10)));
+
+    q1 = LatLonPoint.newDistanceQuery("field", 50, 70, 10000);
+    q2 = LatLonPoint.newDistanceQuery("field", 50, 70, 10000);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(LatLonPoint.newDistanceQuery("field", 50, 70, 11000)));
+    assertFalse(q1.equals(LatLonPoint.newDistanceQuery("field", 50, 60, 10000)));
 
                 
     double[] polyLats1 = new double[] {30, 40, 40, 30, 30};
     double[] polyLons1 = new double[] {90, 90, -40, -40, 90};
     double[] polyLats2 = new double[] {20, 40, 40, 20, 20};
-    q = LatLonPoint.newPolygonQuery("field", polyLats1, polyLons1);
-    assertEquals(q, LatLonPoint.newPolygonQuery("field", polyLats1, polyLons1));
-    assertFalse(q.equals(LatLonPoint.newPolygonQuery("field", polyLats2, polyLons1)));
+    q1 = LatLonPoint.newPolygonQuery("field", polyLats1, polyLons1);
+    q2 = LatLonPoint.newPolygonQuery("field", polyLats1, polyLons1);
+    assertEquals(q1, q2);
+    assertEquals(q1.hashCode(), q2.hashCode());
+    assertFalse(q1.equals(LatLonPoint.newPolygonQuery("field", polyLats2, polyLons1)));
   }     
 }