You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ho...@apache.org on 2016/02/25 02:57:59 UTC

[39/50] [abbrv] lucene-solr git commit: LUCENE-7043: Add BigIntegerPoint and InetAddressPoint to sandbox.

LUCENE-7043: Add BigIntegerPoint and InetAddressPoint to sandbox.


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

Branch: refs/heads/jira/SOLR-445
Commit: 54216c6f650d34973a8eefa86343aad7b940a1c6
Parents: 9ce2d0d
Author: Robert Muir <rm...@apache.org>
Authored: Tue Feb 23 07:23:41 2016 -0500
Committer: Robert Muir <rm...@apache.org>
Committed: Tue Feb 23 07:24:38 2016 -0500

----------------------------------------------------------------------
 .../org/apache/lucene/document/DoublePoint.java |  20 ++
 .../org/apache/lucene/document/FloatPoint.java  |  20 ++
 .../org/apache/lucene/document/IntPoint.java    |  20 ++
 .../org/apache/lucene/document/LongPoint.java   |  20 ++
 .../apache/lucene/search/PointRangeQuery.java   |   7 +-
 .../org/apache/lucene/util/NumericUtils.java    |  29 ++-
 .../org/apache/lucene/document/TestField.java   | 184 ++++++++++++++++-
 .../org/apache/lucene/util/bkd/TestBKD.java     |   8 +-
 .../apache/lucene/document/BigIntegerPoint.java | 205 +++++++++++++++++++
 .../lucene/document/InetAddressPoint.java       | 202 ++++++++++++++++++
 .../lucene/document/TestBigIntegerPoint.java    |  87 ++++++++
 .../lucene/document/TestInetAddressPoint.java   |  87 ++++++++
 .../lucene/index/BasePointFormatTestCase.java   |   8 +-
 13 files changed, 868 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/54216c6f/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 9099cce..e21c639 100644
--- a/lucene/core/src/java/org/apache/lucene/document/DoublePoint.java
+++ b/lucene/core/src/java/org/apache/lucene/document/DoublePoint.java
@@ -88,6 +88,26 @@ public final class DoublePoint extends Field {
     super(name, pack(point), getType(point.length));
   }
   
+  @Override
+  public String toString() {
+    StringBuilder result = new StringBuilder();
+    result.append(type.toString());
+    result.append('<');
+    result.append(name);
+    result.append(':');
+
+    BytesRef bytes = (BytesRef) fieldsData;
+    for (int dim = 0; dim < type.pointDimensionCount(); dim++) {
+      if (dim > 0) {
+        result.append(',');
+      }
+      result.append(decodeDimension(bytes.bytes, bytes.offset + dim * Double.BYTES));
+    }
+
+    result.append('>');
+    return result.toString();
+  }
+  
   // public helper methods (e.g. for queries)
 
   /** Encode n-dimensional double point into binary encoding */

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/54216c6f/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 c47f4ae..c511603 100644
--- a/lucene/core/src/java/org/apache/lucene/document/FloatPoint.java
+++ b/lucene/core/src/java/org/apache/lucene/document/FloatPoint.java
@@ -88,6 +88,26 @@ public final class FloatPoint extends Field {
     super(name, pack(point), getType(point.length));
   }
   
+  @Override
+  public String toString() {
+    StringBuilder result = new StringBuilder();
+    result.append(type.toString());
+    result.append('<');
+    result.append(name);
+    result.append(':');
+
+    BytesRef bytes = (BytesRef) fieldsData;
+    for (int dim = 0; dim < type.pointDimensionCount(); dim++) {
+      if (dim > 0) {
+        result.append(',');
+      }
+      result.append(decodeDimension(bytes.bytes, bytes.offset + dim * Float.BYTES));
+    }
+
+    result.append('>');
+    return result.toString();
+  }
+  
   // public helper methods (e.g. for queries)
 
   /** Encode n-dimensional float values into binary encoding */

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/54216c6f/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 32d2b59..be91bfd 100644
--- a/lucene/core/src/java/org/apache/lucene/document/IntPoint.java
+++ b/lucene/core/src/java/org/apache/lucene/document/IntPoint.java
@@ -87,6 +87,26 @@ public final class IntPoint extends Field {
   public IntPoint(String name, int... point) {
     super(name, pack(point), getType(point.length));
   }
+  
+  @Override
+  public String toString() {
+    StringBuilder result = new StringBuilder();
+    result.append(type.toString());
+    result.append('<');
+    result.append(name);
+    result.append(':');
+
+    BytesRef bytes = (BytesRef) fieldsData;
+    for (int dim = 0; dim < type.pointDimensionCount(); dim++) {
+      if (dim > 0) {
+        result.append(',');
+      }
+      result.append(decodeDimension(bytes.bytes, bytes.offset + dim * Integer.BYTES));
+    }
+
+    result.append('>');
+    return result.toString();
+  }
 
   // public helper methods (e.g. for queries)
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/54216c6f/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 b2ec29b..38ff720 100644
--- a/lucene/core/src/java/org/apache/lucene/document/LongPoint.java
+++ b/lucene/core/src/java/org/apache/lucene/document/LongPoint.java
@@ -88,6 +88,26 @@ public final class LongPoint extends Field {
     super(name, pack(point), getType(point.length));
   }
   
+  @Override
+  public String toString() {
+    StringBuilder result = new StringBuilder();
+    result.append(type.toString());
+    result.append('<');
+    result.append(name);
+    result.append(':');
+
+    BytesRef bytes = (BytesRef) fieldsData;
+    for (int dim = 0; dim < type.pointDimensionCount(); dim++) {
+      if (dim > 0) {
+        result.append(',');
+      }
+      result.append(decodeDimension(bytes.bytes, bytes.offset + dim * Long.BYTES));
+    }
+
+    result.append('>');
+    return result.toString();
+  }
+  
   // public helper methods (e.g. for queries)
 
   /** Encode n-dimensional long values into binary encoding */

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/54216c6f/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 9fe2a8d..bf2b2ef 100644
--- a/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java
@@ -116,8 +116,11 @@ public class PointRangeQuery extends Query {
     }
   }
 
-  /** Check preconditions for all factory methods */
-  private static void checkArgs(String field, Object lowerPoint, Object upperPoint) {
+  /** 
+   * Check preconditions for all factory methods
+   * @throws IllegalArgumentException if {@code field}, {@code lowerPoint} or {@code upperPoint} are null.
+   */
+  public static void checkArgs(String field, Object lowerPoint, Object upperPoint) {
     if (field == null) {
       throw new IllegalArgumentException("field must not be null");
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/54216c6f/lucene/core/src/java/org/apache/lucene/util/NumericUtils.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/NumericUtils.java b/lucene/core/src/java/org/apache/lucene/util/NumericUtils.java
index 58e25f3..4863a88 100644
--- a/lucene/core/src/java/org/apache/lucene/util/NumericUtils.java
+++ b/lucene/core/src/java/org/apache/lucene/util/NumericUtils.java
@@ -218,37 +218,36 @@ public final class NumericUtils {
   }
 
   public static void sortableBigIntBytes(byte[] bytes) {
+    // Flip the sign bit so negative bigints sort before positive bigints:
     bytes[0] ^= 0x80;
-    for(int i=1;i<bytes.length;i++)  {
-      bytes[i] ^= 0;
-    }
   }
 
-  public static void bigIntToBytes(BigInteger bigInt, byte[] result, int dim, int numBytesPerDim) {
+  public static void bigIntToBytes(BigInteger bigInt, int bigIntSize, byte[] result, int offset) {
     byte[] bigIntBytes = bigInt.toByteArray();
     byte[] fullBigIntBytes;
 
-    if (bigIntBytes.length < numBytesPerDim) {
-      fullBigIntBytes = new byte[numBytesPerDim];
-      System.arraycopy(bigIntBytes, 0, fullBigIntBytes, numBytesPerDim-bigIntBytes.length, bigIntBytes.length);
+    if (bigIntBytes.length < bigIntSize) {
+      fullBigIntBytes = new byte[bigIntSize];
+      System.arraycopy(bigIntBytes, 0, fullBigIntBytes, bigIntSize-bigIntBytes.length, bigIntBytes.length);
       if ((bigIntBytes[0] & 0x80) != 0) {
         // sign extend
-        Arrays.fill(fullBigIntBytes, 0, numBytesPerDim-bigIntBytes.length, (byte) 0xff);
+        Arrays.fill(fullBigIntBytes, 0, bigIntSize-bigIntBytes.length, (byte) 0xff);
       }
-    } else {
-      assert bigIntBytes.length == numBytesPerDim;
+    } else if (bigIntBytes.length == bigIntSize) {
       fullBigIntBytes = bigIntBytes;
+    } else {
+      throw new IllegalArgumentException("BigInteger: " + bigInt + " requires more than " + bigIntSize + " bytes storage");
     }
     sortableBigIntBytes(fullBigIntBytes);
 
-    System.arraycopy(fullBigIntBytes, 0, result, dim * numBytesPerDim, numBytesPerDim);
+    System.arraycopy(fullBigIntBytes, 0, result, offset, bigIntSize);
 
-    assert bytesToBigInt(result, dim, numBytesPerDim).equals(bigInt): "bigInt=" + bigInt + " converted=" + bytesToBigInt(result, dim, numBytesPerDim);
+    assert bytesToBigInt(result, offset, bigIntSize).equals(bigInt): "bigInt=" + bigInt + " converted=" + bytesToBigInt(result, offset, bigIntSize);
   }
 
-  public static BigInteger bytesToBigInt(byte[] bytes, int dim, int numBytesPerDim) {
-    byte[] bigIntBytes = new byte[numBytesPerDim];
-    System.arraycopy(bytes, dim*numBytesPerDim, bigIntBytes, 0, numBytesPerDim);
+  public static BigInteger bytesToBigInt(byte[] bytes, int offset, int length) {
+    byte[] bigIntBytes = new byte[length];
+    System.arraycopy(bytes, offset, bigIntBytes, 0, length);
     sortableBigIntBytes(bigIntBytes);
     return new BigInteger(bigIntBytes);
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/54216c6f/lucene/core/src/test/org/apache/lucene/document/TestField.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/document/TestField.java b/lucene/core/src/test/org/apache/lucene/document/TestField.java
index 3ac7990..789678a 100644
--- a/lucene/core/src/test/org/apache/lucene/document/TestField.java
+++ b/lucene/core/src/test/org/apache/lucene/document/TestField.java
@@ -35,7 +35,51 @@ import org.apache.lucene.util.LuceneTestCase;
 // sanity check some basics of fields
 public class TestField extends LuceneTestCase {
   
-  public void testDoubleField() throws Exception {
+  public void testDoublePoint() throws Exception {
+    Field field = new DoublePoint("foo", 5d);
+
+    trySetBoost(field);
+    trySetByteValue(field);
+    trySetBytesValue(field);
+    trySetBytesRefValue(field);
+    field.setDoubleValue(6d); // ok
+    trySetIntValue(field);
+    trySetFloatValue(field);
+    trySetLongValue(field);
+    trySetReaderValue(field);
+    trySetShortValue(field);
+    trySetStringValue(field);
+    trySetTokenStreamValue(field);
+
+    assertEquals(6d, field.numericValue().doubleValue(), 0.0d);
+    assertEquals("<foo:6.0>", field.toString());
+  }
+  
+  public void testDoublePoint2D() throws Exception {
+    DoublePoint field = new DoublePoint("foo", 5d, 4d);
+
+    trySetBoost(field);
+    trySetByteValue(field);
+    trySetBytesValue(field);
+    trySetBytesRefValue(field);
+    trySetDoubleValue(field);
+    field.setDoubleValues(6d, 7d); // ok
+    trySetIntValue(field);
+    trySetFloatValue(field);
+    trySetLongValue(field);
+    trySetReaderValue(field);
+    trySetShortValue(field);
+    trySetStringValue(field);
+    trySetTokenStreamValue(field);
+
+    IllegalStateException expected = expectThrows(IllegalStateException.class, () -> {
+      field.numericValue();
+    });
+    assertTrue(expected.getMessage().contains("cannot convert to a single numeric value"));
+    assertEquals("<foo:6.0,7.0>", field.toString());
+  }
+  
+  public void testLegacyDoubleField() throws Exception {
     Field fields[] = new Field[] {
         new LegacyDoubleField("foo", 5d, Field.Store.NO),
         new LegacyDoubleField("foo", 5d, Field.Store.YES)
@@ -97,7 +141,51 @@ public class TestField extends LuceneTestCase {
     assertEquals(6f, Float.intBitsToFloat(field.numericValue().intValue()), 0.0f);
   }
   
-  public void testFloatField() throws Exception {
+  public void testFloatPoint() throws Exception {
+    Field field = new FloatPoint("foo", 5f);
+
+    trySetBoost(field);
+    trySetByteValue(field);
+    trySetBytesValue(field);
+    trySetBytesRefValue(field);
+    trySetDoubleValue(field);
+    trySetIntValue(field);
+    field.setFloatValue(6f); // ok
+    trySetLongValue(field);
+    trySetReaderValue(field);
+    trySetShortValue(field);
+    trySetStringValue(field);
+    trySetTokenStreamValue(field);
+
+    assertEquals(6f, field.numericValue().floatValue(), 0.0f);
+    assertEquals("<foo:6.0>", field.toString());
+  }
+  
+  public void testFloatPoint2D() throws Exception {
+    FloatPoint field = new FloatPoint("foo", 5f, 4f);
+
+    trySetBoost(field);
+    trySetByteValue(field);
+    trySetBytesValue(field);
+    trySetBytesRefValue(field);
+    trySetDoubleValue(field);
+    trySetIntValue(field);
+    trySetFloatValue(field);
+    field.setFloatValues(6f, 7f); // ok
+    trySetLongValue(field);
+    trySetReaderValue(field);
+    trySetShortValue(field);
+    trySetStringValue(field);
+    trySetTokenStreamValue(field);
+
+    IllegalStateException expected = expectThrows(IllegalStateException.class, () -> {
+      field.numericValue();
+    });
+    assertTrue(expected.getMessage().contains("cannot convert to a single numeric value"));
+    assertEquals("<foo:6.0,7.0>", field.toString());
+  }
+  
+  public void testLegacyFloatField() throws Exception {
     Field fields[] = new Field[] {
         new LegacyFloatField("foo", 5f, Field.Store.NO),
         new LegacyFloatField("foo", 5f, Field.Store.YES)
@@ -121,7 +209,51 @@ public class TestField extends LuceneTestCase {
     }
   }
   
-  public void testIntField() throws Exception {
+  public void testIntPoint() throws Exception {
+    Field field = new IntPoint("foo", 5);
+
+    trySetBoost(field);
+    trySetByteValue(field);
+    trySetBytesValue(field);
+    trySetBytesRefValue(field);
+    trySetDoubleValue(field);
+    field.setIntValue(6); // ok
+    trySetFloatValue(field);
+    trySetLongValue(field);
+    trySetReaderValue(field);
+    trySetShortValue(field);
+    trySetStringValue(field);
+    trySetTokenStreamValue(field);
+
+    assertEquals(6, field.numericValue().intValue());
+    assertEquals("<foo:6>", field.toString());
+  }
+  
+  public void testIntPoint2D() throws Exception {
+    IntPoint field = new IntPoint("foo", 5, 4);
+
+    trySetBoost(field);
+    trySetByteValue(field);
+    trySetBytesValue(field);
+    trySetBytesRefValue(field);
+    trySetDoubleValue(field);
+    trySetIntValue(field);
+    field.setIntValues(6, 7); // ok
+    trySetFloatValue(field);
+    trySetLongValue(field);
+    trySetReaderValue(field);
+    trySetShortValue(field);
+    trySetStringValue(field);
+    trySetTokenStreamValue(field);
+
+    IllegalStateException expected = expectThrows(IllegalStateException.class, () -> {
+      field.numericValue();
+    });
+    assertTrue(expected.getMessage().contains("cannot convert to a single numeric value"));
+    assertEquals("<foo:6,7>", field.toString());
+  }
+  
+  public void testLegacyIntField() throws Exception {
     Field fields[] = new Field[] {
         new LegacyIntField("foo", 5, Field.Store.NO),
         new LegacyIntField("foo", 5, Field.Store.YES)
@@ -164,7 +296,51 @@ public class TestField extends LuceneTestCase {
     assertEquals(6L, field.numericValue().longValue());
   }
   
-  public void testLongField() throws Exception {
+  public void testLongPoint() throws Exception {
+    Field field = new LongPoint("foo", 5);
+
+    trySetBoost(field);
+    trySetByteValue(field);
+    trySetBytesValue(field);
+    trySetBytesRefValue(field);
+    trySetDoubleValue(field);
+    trySetIntValue(field);
+    trySetFloatValue(field);
+    field.setLongValue(6); // ok
+    trySetReaderValue(field);
+    trySetShortValue(field);
+    trySetStringValue(field);
+    trySetTokenStreamValue(field);
+
+    assertEquals(6, field.numericValue().intValue());
+    assertEquals("<foo:6>", field.toString());
+  }
+  
+  public void testLongPoint2D() throws Exception {
+    LongPoint field = new LongPoint("foo", 5, 4);
+
+    trySetBoost(field);
+    trySetByteValue(field);
+    trySetBytesValue(field);
+    trySetBytesRefValue(field);
+    trySetDoubleValue(field);
+    trySetIntValue(field);
+    trySetFloatValue(field);
+    trySetLongValue(field);
+    field.setLongValues(6, 7); // ok
+    trySetReaderValue(field);
+    trySetShortValue(field);
+    trySetStringValue(field);
+    trySetTokenStreamValue(field);
+
+    IllegalStateException expected = expectThrows(IllegalStateException.class, () -> {
+      field.numericValue();
+    });
+    assertTrue(expected.getMessage().contains("cannot convert to a single numeric value"));
+    assertEquals("<foo:6,7>", field.toString());
+  }
+  
+  public void testLegacyLongField() throws Exception {
     Field fields[] = new Field[] {
         new LegacyLongField("foo", 5L, Field.Store.NO),
         new LegacyLongField("foo", 5L, Field.Store.YES)

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/54216c6f/lucene/core/src/test/org/apache/lucene/util/bkd/TestBKD.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/util/bkd/TestBKD.java b/lucene/core/src/test/org/apache/lucene/util/bkd/TestBKD.java
index e5ee46f..f24b805 100644
--- a/lucene/core/src/test/org/apache/lucene/util/bkd/TestBKD.java
+++ b/lucene/core/src/test/org/apache/lucene/util/bkd/TestBKD.java
@@ -268,7 +268,7 @@ public class TestBKD extends LuceneTestCase {
         }
         for(int dim=0;dim<numDims;dim++) {
           values[dim] = randomBigInt(numBytesPerDim);
-          NumericUtils.bigIntToBytes(values[dim], scratch, dim, numBytesPerDim);
+          NumericUtils.bigIntToBytes(values[dim], numBytesPerDim, scratch, dim * numBytesPerDim);
           if (VERBOSE) {
             System.out.println("    " + dim + " -> " + values[dim]);
           }
@@ -317,7 +317,7 @@ public class TestBKD extends LuceneTestCase {
             public void visit(int docID, byte[] packedValue) {
               //System.out.println("visit check docID=" + docID);
               for(int dim=0;dim<numDims;dim++) {
-                BigInteger x = NumericUtils.bytesToBigInt(packedValue, dim, numBytesPerDim);
+                BigInteger x = NumericUtils.bytesToBigInt(packedValue, dim * numBytesPerDim, numBytesPerDim);
                 if (x.compareTo(queryMin[dim]) < 0 || x.compareTo(queryMax[dim]) > 0) {
                   //System.out.println("  no");
                   return;
@@ -332,8 +332,8 @@ public class TestBKD extends LuceneTestCase {
             public Relation compare(byte[] minPacked, byte[] maxPacked) {
               boolean crosses = false;
               for(int dim=0;dim<numDims;dim++) {
-                BigInteger min = NumericUtils.bytesToBigInt(minPacked, dim, numBytesPerDim);
-                BigInteger max = NumericUtils.bytesToBigInt(maxPacked, dim, numBytesPerDim);
+                BigInteger min = NumericUtils.bytesToBigInt(minPacked, dim * numBytesPerDim, numBytesPerDim);
+                BigInteger max = NumericUtils.bytesToBigInt(maxPacked, dim * numBytesPerDim, numBytesPerDim);
                 assert max.compareTo(min) >= 0;
 
                 if (max.compareTo(queryMin[dim]) < 0 || min.compareTo(queryMax[dim]) > 0) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/54216c6f/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
new file mode 100644
index 0000000..f2e9f1d
--- /dev/null
+++ b/lucene/sandbox/src/java/org/apache/lucene/document/BigIntegerPoint.java
@@ -0,0 +1,205 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.document;
+
+import java.math.BigInteger;
+
+import org.apache.lucene.search.PointRangeQuery;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.NumericUtils;
+
+/** A 128-bit integer field that is indexed dimensionally such that finding
+ *  all documents within an N-dimensional shape or range at search time is
+ *  efficient.  Multiple values for the same field in one documents
+ *  is allowed. */
+public class BigIntegerPoint extends Field {
+
+  static final int BYTES = 16;
+
+  private static FieldType getType(int numDims) {
+    FieldType type = new FieldType();
+    type.setDimensions(numDims, BYTES);
+    type.freeze();
+    return type;
+  }
+
+  /** Change the values of this field */
+  public void setBigIntegerValues(BigInteger... point) {
+    if (type.pointDimensionCount() != point.length) {
+      throw new IllegalArgumentException("this field (name=" + name + ") uses " + type.pointDimensionCount() + " dimensions; cannot change to (incoming) " + point.length + " dimensions");
+    }
+    fieldsData = pack(point);
+  }
+
+  @Override
+  public void setBytesValue(BytesRef bytes) {
+    throw new IllegalArgumentException("cannot change value type from BigInteger to BytesRef");
+  }
+
+  @Override
+  public Number numericValue() {
+    if (type.pointDimensionCount() != 1) {
+      throw new IllegalStateException("this field (name=" + name + ") uses " + type.pointDimensionCount() + " dimensions; cannot convert to a single numeric value");
+    }
+    BytesRef bytes = (BytesRef) fieldsData;
+    assert bytes.length == BYTES;
+    return decodeDimension(bytes.bytes, bytes.offset);
+  }
+
+  private static BytesRef pack(BigInteger... point) {
+    if (point == null) {
+      throw new IllegalArgumentException("point cannot be null");
+    }
+    if (point.length == 0) {
+      throw new IllegalArgumentException("point cannot be 0 dimensions");
+    }
+    byte[] packed = new byte[point.length * BYTES];
+    
+    for (int dim = 0; dim < point.length; dim++) {
+      encodeDimension(point[dim], packed, dim * BYTES);
+    }
+
+    return new BytesRef(packed);
+  }
+
+  /** Creates a new BigIntegerPoint, indexing the
+   *  provided N-dimensional big integer point.
+   *
+   *  @param name field name
+   *  @param point BigInteger[] value
+   *  @throws IllegalArgumentException if the field name or value is null.
+   */
+  public BigIntegerPoint(String name, BigInteger... point) {
+    super(name, pack(point), getType(point.length));
+  }
+  
+  @Override
+  public String toString() {
+    StringBuilder result = new StringBuilder();
+    result.append(type.toString());
+    result.append('<');
+    result.append(name);
+    result.append(':');
+
+    BytesRef bytes = (BytesRef) fieldsData;
+    for (int dim = 0; dim < type.pointDimensionCount(); dim++) {
+      if (dim > 0) {
+        result.append(',');
+      }
+      result.append(decodeDimension(bytes.bytes, bytes.offset + dim * BYTES));
+    }
+
+    result.append('>');
+    return result.toString();
+  }
+  
+  // public helper methods (e.g. for queries)
+
+  /** Encode n-dimensional BigInteger values into binary encoding */
+  public static byte[][] encode(BigInteger value[]) {
+    byte[][] encoded = new byte[value.length][];
+    for (int i = 0; i < value.length; i++) {
+      if (value[i] != null) {
+        encoded[i] = new byte[BYTES];
+        encodeDimension(value[i], encoded[i], 0);
+      }
+    }
+    return encoded;
+  }
+  
+  /** Encode single BigInteger dimension */
+  public static void encodeDimension(BigInteger value, byte dest[], int offset) {
+    NumericUtils.bigIntToBytes(value, BYTES, dest, offset);
+  }
+  
+  /** Decode single BigInteger dimension */
+  public static BigInteger decodeDimension(byte value[], int offset) {
+    return NumericUtils.bytesToBigInt(value, offset, BYTES);
+  }
+
+  // static methods for generating queries
+
+  /** 
+   * Create a range query for matching an exact big integer value.
+   * <p>
+   * This is for simple one-dimension points, for multidimensional points use
+   * {@link #newMultiBigIntegerRange newMultiBigIntegerRange()} instead.
+   *
+   * @param field field name. must not be {@code null}.
+   * @param value exact value
+   * @throws IllegalArgumentException if {@code field} is null.
+   * @return a query matching documents with this exact value
+   */
+  public static PointRangeQuery newBigIntegerExact(String field, BigInteger value) {
+    return newBigIntegerRange(field, value, true, value, true);
+  }
+
+  /** 
+   * Create a range query for big integer values indexed with {@link BigIntegerPoint}.
+   * <p>
+   * This is for simple one-dimension ranges, for multidimensional ranges use
+   * {@link #newMultiBigIntegerRange newMultiBigIntegerRange()} instead.
+   * <p>
+   * You can have half-open ranges (which are in fact &lt;/&le; or &gt;/&ge; queries)
+   * by setting the {@code lowerValue} or {@code upperValue} to {@code null}. 
+   * <p>
+   * By setting inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
+   * match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
+   *
+   * @param field field name. must not be {@code null}.
+   * @param lowerValue lower portion of the range. {@code null} means "open".
+   * @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
+   * @param upperValue upper portion of the range. {@code null} means "open".
+   * @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
+   * @throws IllegalArgumentException if {@code field} is null.
+   * @return a query matching documents within this range.
+   */
+  public static PointRangeQuery newBigIntegerRange(String field, BigInteger lowerValue, boolean lowerInclusive, BigInteger upperValue, boolean upperInclusive) {
+    return newMultiBigIntegerRange(field, 
+                                   new BigInteger[] { lowerValue },
+                                   new boolean[] { lowerInclusive }, 
+                                   new BigInteger[] { upperValue },
+                                   new boolean[] { upperInclusive });
+  }
+
+  /** 
+   * Create a multidimensional range query for big integer values indexed with {@link BigIntegerPoint}.
+   * <p>
+   * You can have half-open ranges (which are in fact &lt;/&le; or &gt;/&ge; queries)
+   * by setting a {@code lowerValue} element or {@code upperValue} element to {@code null}. 
+   * <p>
+   * By setting a dimension's inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
+   * match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
+   *
+   * @param field field name. must not be {@code null}.
+   * @param lowerValue lower portion of the range. {@code null} values mean "open" for that dimension.
+   * @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
+   * @param upperValue upper portion of the range. {@code null} values mean "open" for that dimension.
+   * @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
+   * @throws IllegalArgumentException if {@code field} is null, or if {@code lowerValue.length != upperValue.length}
+   * @return a query matching documents within this range.
+   */
+  public static PointRangeQuery newMultiBigIntegerRange(String field, BigInteger[] lowerValue, boolean lowerInclusive[], BigInteger[] upperValue, boolean upperInclusive[]) {
+    PointRangeQuery.checkArgs(field, lowerValue, upperValue);
+    return new PointRangeQuery(field, BigIntegerPoint.encode(lowerValue), lowerInclusive, BigIntegerPoint.encode(upperValue), upperInclusive) {
+      @Override
+      protected String toString(byte[] value) {
+        return BigIntegerPoint.decodeDimension(value, 0).toString();
+      }
+    };
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/54216c6f/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
new file mode 100644
index 0000000..06a3ce4
--- /dev/null
+++ b/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.document;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.apache.lucene.search.PointRangeQuery;
+import org.apache.lucene.util.BytesRef;
+
+/** A field indexing {@link InetAddress} dimensionally such that finding
+ *  all documents within a range at search time is
+ *  efficient.  Multiple values for the same field in one document
+ *  is allowed. 
+ *  <p>
+ *  This field supports both IPv4 and IPv6 addresses: IPv4 addresses are converted
+ *  to <a href="https://tools.ietf.org/html/rfc4291#section-2.5.5">IPv4-Mapped IPv6 Addresses</a>:
+ *  indexing {@code 1.2.3.4} is the same as indexing {@code ::FFFF:1.2.3.4}.
+ */
+public class InetAddressPoint extends Field {
+
+  // implementation note: we convert all addresses to IPv6: we expect prefix compression of values,
+  // so its not wasteful, but allows one field to handle both IPv4 and IPv6.
+  static final int BYTES = 16;
+  
+  // rfc4291 prefix
+  static final byte[] IPV4_PREFIX = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1 }; 
+
+  private static final FieldType TYPE;
+  static {
+    TYPE = new FieldType();
+    TYPE.setDimensions(1, BYTES);
+    TYPE.freeze();
+  }
+
+  /** Change the values of this field */
+  public void setInetAddressValue(InetAddress value) {
+    if (value == null) {
+      throw new IllegalArgumentException("point cannot be null");
+    }
+    fieldsData = new BytesRef(encode(value));
+  }
+
+  @Override
+  public void setBytesValue(BytesRef bytes) {
+    throw new IllegalArgumentException("cannot change value type from InetAddress to BytesRef");
+  }
+
+  /** Creates a new InetAddressPoint, indexing the
+   *  provided address.
+   *
+   *  @param name field name
+   *  @param point InetAddress value
+   *  @throws IllegalArgumentException if the field name or value is null.
+   */
+  public InetAddressPoint(String name, InetAddress point) {
+    super(name, TYPE);
+    setInetAddressValue(point);
+  }
+  
+  @Override
+  public String toString() {
+    StringBuilder result = new StringBuilder();
+    result.append(type.toString());
+    result.append('<');
+    result.append(name);
+    result.append(':');
+
+    BytesRef bytes = (BytesRef) fieldsData;
+    result.append(decodeToString(BytesRef.deepCopyOf(bytes).bytes));
+
+    result.append('>');
+    return result.toString();
+  }
+  
+  // public helper methods (e.g. for queries)
+
+  /** Encode InetAddress value into binary encoding */
+  public static byte[] encode(InetAddress value) {
+    byte[] address = value.getAddress();
+    if (address.length == 4) {
+      byte[] mapped = new byte[16];
+      System.arraycopy(IPV4_PREFIX, 0, mapped, 0, IPV4_PREFIX.length);
+      System.arraycopy(address, 0, mapped, IPV4_PREFIX.length, address.length);
+      address = mapped;
+    } else if (address.length != 16) {
+      // more of an assertion, how did you create such an InetAddress :)
+      throw new UnsupportedOperationException("Only IPv4 and IPv6 addresses are supported");
+    }
+    return address;
+  }
+  
+  /** Decodes InetAddress value from binary encoding */
+  public static InetAddress decode(byte value[]) {
+    try {
+      return InetAddress.getByAddress(value);
+    } catch (UnknownHostException e) {
+      // this only happens if value.length != 4 or 16, strange exception class
+      throw new IllegalArgumentException("encoded bytes are of incorrect length", e);
+    }
+  }
+  
+  /** decodes from binary encoding to a friendly format: IPv6 addresses are bracketed, 
+   *  to not cause confusion with historic field:value representation, etc */
+  public static String decodeToString(byte value[]) {
+    InetAddress address = decode(value);
+    if (address.getAddress().length == 16) {
+      return "[" + address.getHostAddress() + "]";
+    } else {
+      return address.getHostAddress();
+    }
+  }
+
+  // static methods for generating queries
+
+  /** 
+   * Create a range query for matching an address.
+   *
+   * @param field field name. must not be {@code null}.
+   * @param value exact value
+   * @throws IllegalArgumentException if {@code field} is null.
+   * @return a query matching documents with this exact value
+   */
+  public static PointRangeQuery newInetAddressExact(String field, InetAddress value) {
+    return newInetAddressRange(field, value, true, value, true);
+  }
+  
+  /** 
+   * Create a range query for matching a CIDR network range.
+   *
+   * @param field field name. must not be {@code null}.
+   * @param value any host address
+   * @param prefixLength the network prefix length for this address. This is also known as the subnet mask in the context of IPv4 addresses.
+   * @throws IllegalArgumentException if {@code field} is null, or prefixLength is invalid.
+   * @return a query matching documents with addresses contained within this network
+   */
+  public static PointRangeQuery newInetAddressPrefix(String field, InetAddress value, int prefixLength) {
+    if (prefixLength < 0 || prefixLength > 8 * value.getAddress().length) {
+      throw new IllegalArgumentException("illegal prefixLength '" + prefixLength + "'. Must be 0-32 for IPv4 ranges, 0-128 for IPv6 ranges");
+    }
+    // create the lower value by zeroing out the host portion, upper value by filling it with all ones.
+    byte lower[] = value.getAddress();
+    byte upper[] = value.getAddress();
+    for (int i = prefixLength; i < 8 * lower.length; i++) {
+      lower[i >> 3] &= ~(1 << (i & 7));
+      upper[i >> 3] |= 1 << (i & 7);
+    }
+    try {
+      return newInetAddressRange(field, InetAddress.getByAddress(lower), true, InetAddress.getByAddress(upper), true);
+    } catch (UnknownHostException e) {
+      throw new AssertionError(e); // values are coming from InetAddress
+    }
+  }
+
+  /** 
+   * Create a range query for addresses indexed with {@link InetAddressPoint}.
+   * <p>
+   * You can have half-open ranges (which are in fact &lt;/&le; or &gt;/&ge; queries)
+   * by setting the {@code lowerValue} or {@code upperValue} to {@code null}. 
+   * <p>
+   * By setting inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
+   * match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
+   *
+   * @param field field name. must not be {@code null}.
+   * @param lowerValue lower portion of the range. {@code null} means "open".
+   * @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
+   * @param upperValue upper portion of the range. {@code null} means "open".
+   * @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
+   * @throws IllegalArgumentException if {@code field} is null.
+   * @return a query matching documents within this range.
+   */
+  public static PointRangeQuery newInetAddressRange(String field, InetAddress lowerValue, boolean lowerInclusive, InetAddress upperValue, boolean upperInclusive) {
+    byte[][] lowerBytes = new byte[1][];
+    if (lowerValue != null) {
+      lowerBytes[0] = InetAddressPoint.encode(lowerValue);
+    }
+    byte[][] upperBytes = new byte[1][];
+    if (upperValue != null) {
+      upperBytes[0] = InetAddressPoint.encode(upperValue);
+    }
+    return new PointRangeQuery(field, lowerBytes, new boolean[] { lowerInclusive }, upperBytes, new boolean[] { upperInclusive }) {
+      @Override
+      protected String toString(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/54216c6f/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
new file mode 100644
index 0000000..9009b53
--- /dev/null
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/TestBigIntegerPoint.java
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.document;
+
+import java.math.BigInteger;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.LuceneTestCase;
+
+/** Simple tests for {@link BigIntegerPoint} */
+public class TestBigIntegerPoint extends LuceneTestCase {
+
+  /** Add a single 1D point and search for it */
+  public void testBasics() throws Exception {
+    Directory dir = newDirectory();
+    RandomIndexWriter writer = new RandomIndexWriter(random(), dir);
+
+    // add a doc with a large biginteger value
+    Document document = new Document();
+    BigInteger large = BigInteger.valueOf(Long.MAX_VALUE).multiply(BigInteger.valueOf(64));
+    document.add(new BigIntegerPoint("field", large));
+    writer.addDocument(document);
+    
+    // search and verify we found our doc
+    IndexReader reader = writer.getReader();
+    IndexSearcher searcher = newSearcher(reader);
+    assertEquals(1, searcher.count(BigIntegerPoint.newBigIntegerExact("field", large)));
+    assertEquals(1, searcher.count(BigIntegerPoint.newBigIntegerRange("field", large.subtract(BigInteger.ONE), false, large.add(BigInteger.ONE), false)));
+
+    reader.close();
+    writer.close();
+    dir.close();
+  }
+  
+  /** Add a negative 1D point and search for it */
+  public void testNegative() throws Exception {
+    Directory dir = newDirectory();
+    RandomIndexWriter writer = new RandomIndexWriter(random(), dir);
+
+    // add a doc with a large biginteger value
+    Document document = new Document();
+    BigInteger negative = BigInteger.valueOf(Long.MAX_VALUE).multiply(BigInteger.valueOf(64)).negate();
+    document.add(new BigIntegerPoint("field", negative));
+    writer.addDocument(document);
+    
+    // search and verify we found our doc
+    IndexReader reader = writer.getReader();
+    IndexSearcher searcher = newSearcher(reader);
+    assertEquals(1, searcher.count(BigIntegerPoint.newBigIntegerExact("field", negative)));
+    assertEquals(1, searcher.count(BigIntegerPoint.newBigIntegerRange("field", negative.subtract(BigInteger.ONE), false, negative.add(BigInteger.ONE), false)));
+
+    reader.close();
+    writer.close();
+    dir.close();
+  }
+  
+  /** Test if we add a too-large value */
+  public void testTooLarge() throws Exception {
+    BigInteger tooLarge = BigInteger.ONE.shiftLeft(128);
+    IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
+      new BigIntegerPoint("field", tooLarge);
+    });
+    assertTrue(expected.getMessage().contains("requires more than 16 bytes storage"));
+  }
+  
+  public void testToString() throws Exception {
+    assertEquals("<field:1>", new BigIntegerPoint("field", BigInteger.ONE).toString());
+    assertEquals("<field:1,-2>", new BigIntegerPoint("field", BigInteger.ONE, BigInteger.valueOf(-2)).toString());
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/54216c6f/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
new file mode 100644
index 0000000..f256196
--- /dev/null
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/TestInetAddressPoint.java
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.document;
+
+import java.net.InetAddress;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.LuceneTestCase;
+
+/** Simple tests for {@link InetAddressPoint} */
+public class TestInetAddressPoint extends LuceneTestCase {
+
+  /** Add a single address and search for it */
+  public void testBasics() throws Exception {
+    Directory dir = newDirectory();
+    RandomIndexWriter writer = new RandomIndexWriter(random(), dir);
+
+    // add a doc with an address
+    Document document = new Document();
+    InetAddress address = InetAddress.getByName("1.2.3.4");
+    document.add(new InetAddressPoint("field", address));
+    writer.addDocument(document);
+    
+    // search and verify we found our doc
+    IndexReader reader = writer.getReader();
+    IndexSearcher searcher = newSearcher(reader);
+    assertEquals(1, searcher.count(InetAddressPoint.newInetAddressExact("field", address)));
+    assertEquals(1, searcher.count(InetAddressPoint.newInetAddressPrefix("field", address, 24)));
+    assertEquals(1, searcher.count(InetAddressPoint.newInetAddressRange("field", InetAddress.getByName("1.2.3.3"), false, InetAddress.getByName("1.2.3.5"), false)));
+
+    reader.close();
+    writer.close();
+    dir.close();
+  }
+  
+  /** Add a single address and search for it */
+  public void testBasicsV6() throws Exception {
+    Directory dir = newDirectory();
+    RandomIndexWriter writer = new RandomIndexWriter(random(), dir);
+
+    // add a doc with an address
+    Document document = new Document();
+    InetAddress address = InetAddress.getByName("fec0::f66d");
+    document.add(new InetAddressPoint("field", address));
+    writer.addDocument(document);
+    
+    // search and verify we found our doc
+    IndexReader reader = writer.getReader();
+    IndexSearcher searcher = newSearcher(reader);
+    assertEquals(1, searcher.count(InetAddressPoint.newInetAddressExact("field", address)));
+    assertEquals(1, searcher.count(InetAddressPoint.newInetAddressPrefix("field", address, 64)));
+    assertEquals(1, searcher.count(InetAddressPoint.newInetAddressRange("field", InetAddress.getByName("fec0::f66c"), false, InetAddress.getByName("fec0::f66e"), false)));
+
+    reader.close();
+    writer.close();
+    dir.close();
+  }
+    
+  public void testToString() throws Exception {
+    assertEquals("<field:1.2.3.4>", new InetAddressPoint("field", InetAddress.getByName("1.2.3.4")).toString());
+    assertEquals("<field:1.2.3.4>", new InetAddressPoint("field", InetAddress.getByName("::FFFF:1.2.3.4")).toString());
+    assertEquals("<field:[fdc8:57ed:f042:ad1:f66d:4ff:fe90:ce0c]>", new InetAddressPoint("field", InetAddress.getByName("fdc8:57ed:f042:0ad1:f66d:4ff:fe90:ce0c")).toString());
+    
+    assertEquals("field:[1.2.3.4 TO 1.2.3.4]", InetAddressPoint.newInetAddressExact("field", InetAddress.getByName("1.2.3.4")).toString());
+    assertEquals("field:[0:0:0:0:0:0:0:1 TO 0:0:0:0:0:0:0:1]", InetAddressPoint.newInetAddressExact("field", InetAddress.getByName("::1")).toString());
+    
+    assertEquals("field:[1.2.3.0 TO 1.2.3.255]", InetAddressPoint.newInetAddressPrefix("field", InetAddress.getByName("1.2.3.4"), 24).toString());
+    assertEquals("field:[fdc8:57ed:f042:ad1:0:0:0:0 TO fdc8:57ed:f042:ad1:ffff:ffff:ffff:ffff]", InetAddressPoint.newInetAddressPrefix("field", InetAddress.getByName("fdc8:57ed:f042:0ad1:f66d:4ff:fe90:ce0c"), 64).toString());
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/54216c6f/lucene/test-framework/src/java/org/apache/lucene/index/BasePointFormatTestCase.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/index/BasePointFormatTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/index/BasePointFormatTestCase.java
index 99f8f89..4b8eac2 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/index/BasePointFormatTestCase.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/index/BasePointFormatTestCase.java
@@ -348,7 +348,7 @@ public abstract class BasePointFormatTestCase extends BaseIndexFileFormatTestCas
         for(int dim=0;dim<numDims;dim++) {
           values[dim] = randomBigInt(numBytesPerDim);
           bytes[dim] = new byte[numBytesPerDim];
-          NumericUtils.bigIntToBytes(values[dim], bytes[dim], 0, numBytesPerDim);
+          NumericUtils.bigIntToBytes(values[dim], numBytesPerDim, bytes[dim], 0);
           if (VERBOSE) {
             System.out.println("    " + dim + " -> " + values[dim]);
           }
@@ -398,7 +398,7 @@ public abstract class BasePointFormatTestCase extends BaseIndexFileFormatTestCas
             public void visit(int docID, byte[] packedValue) {
               //System.out.println("visit check docID=" + docID);
               for(int dim=0;dim<numDims;dim++) {
-                BigInteger x = NumericUtils.bytesToBigInt(packedValue, dim, numBytesPerDim);
+                BigInteger x = NumericUtils.bytesToBigInt(packedValue, dim * numBytesPerDim, numBytesPerDim);
                 if (x.compareTo(queryMin[dim]) < 0 || x.compareTo(queryMax[dim]) > 0) {
                   //System.out.println("  no");
                   return;
@@ -413,8 +413,8 @@ public abstract class BasePointFormatTestCase extends BaseIndexFileFormatTestCas
             public Relation compare(byte[] minPacked, byte[] maxPacked) {
               boolean crosses = false;
               for(int dim=0;dim<numDims;dim++) {
-                BigInteger min = NumericUtils.bytesToBigInt(minPacked, dim, numBytesPerDim);
-                BigInteger max = NumericUtils.bytesToBigInt(maxPacked, dim, numBytesPerDim);
+                BigInteger min = NumericUtils.bytesToBigInt(minPacked, dim * numBytesPerDim, numBytesPerDim);
+                BigInteger max = NumericUtils.bytesToBigInt(maxPacked, dim * numBytesPerDim, numBytesPerDim);
                 assert max.compareTo(min) >= 0;
 
                 if (max.compareTo(queryMin[dim]) < 0 || min.compareTo(queryMax[dim]) > 0) {