mirror of https://github.com/apache/lucene.git
LUCENE-8658: Fix illegal assertion in WANDScorer.
This commit is contained in:
parent
c317119654
commit
ef47582fd5
|
@ -52,7 +52,7 @@ final class WANDScorer extends Scorer {
|
||||||
*/
|
*/
|
||||||
static int scalingFactor(float f) {
|
static int scalingFactor(float f) {
|
||||||
if (f < 0) {
|
if (f < 0) {
|
||||||
throw new IllegalArgumentException("");
|
throw new IllegalArgumentException("Scores must be positive or null");
|
||||||
} else if (f == 0) {
|
} else if (f == 0) {
|
||||||
return scalingFactor(Float.MIN_VALUE) - 1;
|
return scalingFactor(Float.MIN_VALUE) - 1;
|
||||||
} else if (Float.isInfinite(f)) {
|
} else if (Float.isInfinite(f)) {
|
||||||
|
@ -76,14 +76,18 @@ final class WANDScorer extends Scorer {
|
||||||
assert Float.isNaN(maxScore) == false;
|
assert Float.isNaN(maxScore) == false;
|
||||||
assert maxScore >= 0;
|
assert maxScore >= 0;
|
||||||
|
|
||||||
if (Float.isInfinite(maxScore)) {
|
|
||||||
return (1L << 32) - 1; // means +Infinity in practice for this scorer
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: because doubles have more amplitude than floats for the
|
// NOTE: because doubles have more amplitude than floats for the
|
||||||
// exponent, the scalb call produces an accurate value.
|
// exponent, the scalb call produces an accurate value.
|
||||||
double scaled = Math.scalb((double) maxScore, scalingFactor);
|
double scaled = Math.scalb((double) maxScore, scalingFactor);
|
||||||
assert scaled <= 1 << 16 : scaled + " " + maxScore; // regular values of max_score go into 0..2^16
|
|
||||||
|
if (scaled > 1 << 16) {
|
||||||
|
// This happens if either maxScore is +Infty, or we have a scorer that
|
||||||
|
// returned +Infty as its maximum score over the whole range of doc IDs
|
||||||
|
// when computing the scaling factor in the constructor, and now returned
|
||||||
|
// a finite maximum score for a smaller range of doc IDs.
|
||||||
|
return (1L << 32) - 1; // means +Infinity in practice for this scorer
|
||||||
|
}
|
||||||
|
|
||||||
return (long) Math.ceil(scaled); // round up, cast is accurate since value is <= 2^16
|
return (long) Math.ceil(scaled); // round up, cast is accurate since value is <= 2^16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -270,7 +270,7 @@ public class TestWANDScorer extends LuceneTestCase {
|
||||||
for (int i = 0; i < numClauses; ++i) {
|
for (int i = 0; i < numClauses; ++i) {
|
||||||
Query query = new TermQuery(new Term("foo", Integer.toString(start + i)));
|
Query query = new TermQuery(new Term("foo", Integer.toString(start + i)));
|
||||||
if (random().nextBoolean()) {
|
if (random().nextBoolean()) {
|
||||||
query = new InfiniteMaxScoreWrapperQuery(query);
|
query = new InfiniteMaxScoreWrapperQuery(query, numDocs / TestUtil.nextInt(random(), 1, 100));
|
||||||
}
|
}
|
||||||
builder.add(query, Occur.SHOULD);
|
builder.add(query, Occur.SHOULD);
|
||||||
}
|
}
|
||||||
|
@ -292,13 +292,26 @@ public class TestWANDScorer extends LuceneTestCase {
|
||||||
|
|
||||||
private static class InfiniteMaxScoreWrapperScorer extends FilterScorer {
|
private static class InfiniteMaxScoreWrapperScorer extends FilterScorer {
|
||||||
|
|
||||||
InfiniteMaxScoreWrapperScorer(Scorer scorer) {
|
private final int maxRange;
|
||||||
|
private int lastShallowTarget = -1;
|
||||||
|
|
||||||
|
InfiniteMaxScoreWrapperScorer(Scorer scorer, int maxRange) {
|
||||||
super(scorer);
|
super(scorer);
|
||||||
|
this.maxRange = maxRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int advanceShallow(int target) throws IOException {
|
||||||
|
lastShallowTarget = target;
|
||||||
|
return in.advanceShallow(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getMaxScore(int upTo) throws IOException {
|
public float getMaxScore(int upTo) throws IOException {
|
||||||
return Float.POSITIVE_INFINITY;
|
if (upTo - Math.max(docID(), lastShallowTarget) >= maxRange) {
|
||||||
|
return Float.POSITIVE_INFINITY;
|
||||||
|
}
|
||||||
|
return in.getMaxScore(upTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -306,9 +319,15 @@ public class TestWANDScorer extends LuceneTestCase {
|
||||||
private static class InfiniteMaxScoreWrapperQuery extends Query {
|
private static class InfiniteMaxScoreWrapperQuery extends Query {
|
||||||
|
|
||||||
private final Query query;
|
private final Query query;
|
||||||
|
private final int maxRange;
|
||||||
|
|
||||||
InfiniteMaxScoreWrapperQuery(Query query) {
|
/**
|
||||||
|
* If asked for the maximum score over a range of doc IDs that is greater
|
||||||
|
* than or equal to maxRange, this query will return a maximum score of +Infty
|
||||||
|
*/
|
||||||
|
InfiniteMaxScoreWrapperQuery(Query query, int maxRange) {
|
||||||
this.query = query;
|
this.query = query;
|
||||||
|
this.maxRange = maxRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -330,7 +349,7 @@ public class TestWANDScorer extends LuceneTestCase {
|
||||||
public Query rewrite(IndexReader reader) throws IOException {
|
public Query rewrite(IndexReader reader) throws IOException {
|
||||||
Query rewritten = query.rewrite(reader);
|
Query rewritten = query.rewrite(reader);
|
||||||
if (rewritten != query) {
|
if (rewritten != query) {
|
||||||
return new InfiniteMaxScoreWrapperQuery(rewritten);
|
return new InfiniteMaxScoreWrapperQuery(rewritten, maxRange);
|
||||||
}
|
}
|
||||||
return super.rewrite(reader);
|
return super.rewrite(reader);
|
||||||
}
|
}
|
||||||
|
@ -344,7 +363,7 @@ public class TestWANDScorer extends LuceneTestCase {
|
||||||
if (scorer == null) {
|
if (scorer == null) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return new InfiniteMaxScoreWrapperScorer(scorer);
|
return new InfiniteMaxScoreWrapperScorer(scorer, maxRange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,7 +377,7 @@ public class TestWANDScorer extends LuceneTestCase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Scorer get(long leadCost) throws IOException {
|
public Scorer get(long leadCost) throws IOException {
|
||||||
return new InfiniteMaxScoreWrapperScorer(supplier.get(leadCost));
|
return new InfiniteMaxScoreWrapperScorer(supplier.get(leadCost), maxRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue