private static boolean contains(GeoPoint point, List<GeoPoint> set, Distance precision) {
   for (GeoPoint r : set) {
     final double distance =
         GeoDistance.PLANE.calculate(
             point.getLat(), point.getLon(), r.getLat(), r.getLon(), DistanceUnit.METERS);
     if (new Distance(distance, DistanceUnit.METERS).compareTo(precision) <= 0) {
       return true;
     }
   }
   return false;
 }
 public void testSortModeSumIsRejectedInSetter() {
   GeoDistanceSortBuilder builder = new GeoDistanceSortBuilder("testname", -1, -1);
   GeoPoint point = RandomGeoGenerator.randomPoint(random());
   builder.point(point.getLat(), point.getLon());
   try {
     builder.sortMode(SortMode.SUM);
     fail("sort mode sum should not be supported");
   } catch (IllegalArgumentException e) {
     // all good
   }
 }
 @Override
 public BytesRef binaryValue() {
   final byte[] bytes = new byte[points.size() * 16];
   int off = 0;
   for (Iterator<ObjectCursor<GeoPoint>> it = points.iterator(); it.hasNext(); ) {
     final GeoPoint point = it.next().value;
     ByteUtils.writeDoubleLE(point.getLat(), bytes, off);
     ByteUtils.writeDoubleLE(point.getLon(), bytes, off + 8);
     off += 16;
   }
   return new BytesRef(bytes);
 }
  public static GeoDistanceSortBuilder randomGeoDistanceSortBuilder() {
    String fieldName = randomAsciiOfLengthBetween(1, 10);
    GeoDistanceSortBuilder result = null;

    int id = randomIntBetween(0, 2);
    switch (id) {
      case 0:
        int count = randomIntBetween(1, 10);
        String[] geohashes = new String[count];
        for (int i = 0; i < count; i++) {
          geohashes[i] = RandomGeoGenerator.randomPoint(random()).geohash();
        }

        result = new GeoDistanceSortBuilder(fieldName, geohashes);
        break;
      case 1:
        GeoPoint pt = RandomGeoGenerator.randomPoint(random());
        result = new GeoDistanceSortBuilder(fieldName, pt.getLat(), pt.getLon());
        break;
      case 2:
        result = new GeoDistanceSortBuilder(fieldName, points(new GeoPoint[0]));
        break;
      default:
        throw new IllegalStateException("one of three geo initialisation strategies must be used");
    }
    if (randomBoolean()) {
      result.geoDistance(geoDistance(result.geoDistance()));
    }
    if (randomBoolean()) {
      result.unit(randomValueOtherThan(result.unit(), () -> randomFrom(DistanceUnit.values())));
    }
    if (randomBoolean()) {
      result.order(randomFrom(SortOrder.values()));
    }
    if (randomBoolean()) {
      result.sortMode(randomValueOtherThan(SortMode.SUM, () -> randomFrom(SortMode.values())));
    }
    if (randomBoolean()) {
      result.setNestedFilter(randomNestedFilter());
    }
    if (randomBoolean()) {
      result.setNestedPath(
          randomValueOtherThan(result.getNestedPath(), () -> randomAsciiOfLengthBetween(1, 10)));
    }
    if (randomBoolean()) {
      result.validation(
          randomValueOtherThan(
              result.validation(), () -> randomFrom(GeoValidationMethod.values())));
    }

    return result;
  }
  private static void duelFieldDataGeoPoint(
      Random random,
      AtomicReaderContext context,
      IndexGeoPointFieldData left,
      IndexGeoPointFieldData right,
      Distance precision)
      throws Exception {
    AtomicGeoPointFieldData leftData =
        random.nextBoolean() ? left.load(context) : left.loadDirect(context);
    AtomicGeoPointFieldData rightData =
        random.nextBoolean() ? right.load(context) : right.loadDirect(context);

    int numDocs = context.reader().maxDoc();
    MultiGeoPointValues leftValues = leftData.getGeoPointValues();
    MultiGeoPointValues rightValues = rightData.getGeoPointValues();
    for (int i = 0; i < numDocs; ++i) {
      leftValues.setDocument(i);
      final int numValues = leftValues.count();
      rightValues.setDocument(i);
      ;
      assertEquals(numValues, rightValues.count());
      List<GeoPoint> leftPoints = Lists.newArrayList();
      List<GeoPoint> rightPoints = Lists.newArrayList();
      for (int j = 0; j < numValues; ++j) {
        GeoPoint l = leftValues.valueAt(j);
        leftPoints.add(new GeoPoint(l.getLat(), l.getLon()));
        GeoPoint r = rightValues.valueAt(j);
        rightPoints.add(new GeoPoint(r.getLat(), r.getLon()));
      }
      for (GeoPoint l : leftPoints) {
        assertTrue(
            "Couldn't find " + l + " among " + rightPoints, contains(l, rightPoints, precision));
      }
      for (GeoPoint r : rightPoints) {
        assertTrue(
            "Couldn't find " + r + " among " + leftPoints, contains(r, leftPoints, precision));
      }
    }
  }
 @Override
 protected GeoDistanceSortBuilder mutate(GeoDistanceSortBuilder original) throws IOException {
   GeoDistanceSortBuilder result = new GeoDistanceSortBuilder(original);
   int parameter = randomIntBetween(0, 8);
   switch (parameter) {
     case 0:
       while (Arrays.deepEquals(original.points(), result.points())) {
         GeoPoint pt = RandomGeoGenerator.randomPoint(random());
         result.point(pt.getLat(), pt.getLon());
       }
       break;
     case 1:
       result.points(points(original.points()));
       break;
     case 2:
       result.geoDistance(geoDistance(original.geoDistance()));
       break;
     case 3:
       result.unit(randomValueOtherThan(result.unit(), () -> randomFrom(DistanceUnit.values())));
       break;
     case 4:
       result.order(randomValueOtherThan(original.order(), () -> randomFrom(SortOrder.values())));
       break;
     case 5:
       result.sortMode(
           randomValueOtherThanMany(
               Arrays.asList(SortMode.SUM, result.sortMode())::contains,
               () -> randomFrom(SortMode.values())));
       break;
     case 6:
       result.setNestedFilter(
           randomValueOtherThan(original.getNestedFilter(), () -> randomNestedFilter()));
       break;
     case 7:
       result.setNestedPath(
           randomValueOtherThan(result.getNestedPath(), () -> randomAsciiOfLengthBetween(1, 10)));
       break;
     case 8:
       result.validation(
           randomValueOtherThan(
               result.validation(), () -> randomFrom(GeoValidationMethod.values())));
       break;
   }
   return result;
 }
 public GeoPoint(GeoPoint template) {
   this(template.getLat(), template.getLon());
 }