void testRangeSplit(int32_t precisionStep) {
     RandomPtr rnd = newLucene<Random>();
     String field = L"ascfield" + StringUtils::toString(precisionStep);
     // 50 random tests
     for (int32_t i = 0; i < 50; ++i) {
         int32_t lower = (int32_t)(rnd->nextDouble() * noDocs - noDocs / 2.0);
         int32_t upper = (int32_t)(rnd->nextDouble() * noDocs - noDocs / 2.0);
         if (lower > upper) {
             std::swap(lower, upper);
         }
         // test inclusive range
         QueryPtr tq = NumericRangeQuery::newIntRange(field, precisionStep, lower, upper, true, true);
         TopDocsPtr tTopDocs = searcher->search(tq, 1);
         EXPECT_EQ(upper - lower + 1, tTopDocs->totalHits);
         // test exclusive range
         tq = NumericRangeQuery::newIntRange(field, precisionStep, lower, upper, false, false);
         tTopDocs = searcher->search(tq, 1);
         EXPECT_EQ(std::max(upper - lower - 1, (int32_t)0), tTopDocs->totalHits);
         // test left exclusive range
         tq = NumericRangeQuery::newIntRange(field, precisionStep, lower, upper, false, true);
         tTopDocs = searcher->search(tq, 1);
         EXPECT_EQ(upper - lower, tTopDocs->totalHits);
         // test right exclusive range
         tq = NumericRangeQuery::newIntRange(field, precisionStep, lower, upper, true, false);
         tTopDocs = searcher->search(tq, 1);
         EXPECT_EQ(upper - lower, tTopDocs->totalHits);
     }
 }
 void testSorting(int32_t precisionStep) {
     RandomPtr rnd = newLucene<Random>();
     String field = L"field" + StringUtils::toString(precisionStep);
     // 10 random tests, the index order is ascending, so using a reverse sort field should return descending documents
     for (int32_t i = 0; i < 10; ++i) {
         int32_t lower = (int32_t)(rnd->nextDouble() * noDocs * distance) + startOffset;
         int32_t upper = (int32_t)(rnd->nextDouble() * noDocs * distance) + startOffset;
         if (lower > upper) {
             std::swap(lower, upper);
         }
         QueryPtr tq = NumericRangeQuery::newIntRange(field, precisionStep, lower, upper, true, true);
         TopDocsPtr topDocs = searcher->search(tq, FilterPtr(), noDocs, newLucene<Sort>(newLucene<SortField>(field, SortField::INT, true)));
         if (topDocs->totalHits == 0) {
             continue;
         }
         Collection<ScoreDocPtr> sd = topDocs->scoreDocs;
         EXPECT_TRUE(sd);
         int32_t last = StringUtils::toInt(searcher->doc(sd[0]->doc)->get(field));
         for (int32_t j = 1; j < sd.size(); ++j) {
             int32_t act = StringUtils::toInt(searcher->doc(sd[j]->doc)->get(field));
             EXPECT_TRUE(last > act);
             last = act;
         }
     }
 }
 void testRandomTrieAndClassicRangeQuery(int32_t precisionStep) {
     RandomPtr rnd = newLucene<Random>();
     String field = L"field" + StringUtils::toString(precisionStep);
     int32_t termCountT = 0;
     int32_t termCountC = 0;
     for (int32_t i = 0; i < 50; ++i) {
         int32_t lower = (int32_t)(rnd->nextDouble() * noDocs * distance) + startOffset;
         int32_t upper = (int32_t)(rnd->nextDouble() * noDocs * distance) + startOffset;
         if (lower > upper) {
             std::swap(lower, upper);
         }
         // test inclusive range
         NumericRangeQueryPtr tq = NumericRangeQuery::newIntRange(field, precisionStep, lower, upper, true, true);
         TermRangeQueryPtr cq = newLucene<TermRangeQuery>(field, NumericUtils::intToPrefixCoded(lower), NumericUtils::intToPrefixCoded(upper), true, true);
         TopDocsPtr tTopDocs = searcher->search(tq, 1);
         TopDocsPtr cTopDocs = searcher->search(cq, 1);
         EXPECT_EQ(cTopDocs->totalHits, tTopDocs->totalHits);
         termCountT += tq->getTotalNumberOfTerms();
         termCountC += cq->getTotalNumberOfTerms();
         // test exclusive range
         tq = NumericRangeQuery::newIntRange(field, precisionStep, lower, upper, false, false);
         cq = newLucene<TermRangeQuery>(field, NumericUtils::intToPrefixCoded(lower), NumericUtils::intToPrefixCoded(upper), false, false);
         tTopDocs = searcher->search(tq, 1);
         cTopDocs = searcher->search(cq, 1);
         EXPECT_EQ(cTopDocs->totalHits, tTopDocs->totalHits);
         termCountT += tq->getTotalNumberOfTerms();
         termCountC += cq->getTotalNumberOfTerms();
         // test left exclusive range
         tq = NumericRangeQuery::newIntRange(field, precisionStep, lower, upper, false, true);
         cq = newLucene<TermRangeQuery>(field, NumericUtils::intToPrefixCoded(lower), NumericUtils::intToPrefixCoded(upper), false, true);
         tTopDocs = searcher->search(tq, 1);
         cTopDocs = searcher->search(cq, 1);
         EXPECT_EQ(cTopDocs->totalHits, tTopDocs->totalHits);
         termCountT += tq->getTotalNumberOfTerms();
         termCountC += cq->getTotalNumberOfTerms();
         // test right exclusive range
         tq = NumericRangeQuery::newIntRange(field, precisionStep, lower, upper, true, false);
         cq = newLucene<TermRangeQuery>(field, NumericUtils::intToPrefixCoded(lower), NumericUtils::intToPrefixCoded(upper), true, false);
         tTopDocs = searcher->search(tq, 1);
         cTopDocs = searcher->search(cq, 1);
         EXPECT_EQ(cTopDocs->totalHits, tTopDocs->totalHits);
         termCountT += tq->getTotalNumberOfTerms();
         termCountC += cq->getTotalNumberOfTerms();
     }
     if (precisionStep == INT_MAX) {
         EXPECT_EQ(termCountT, termCountC);
     }
 }