blob: 77674171c29621bcf17926f9936b077eb348ea33 [file] [log] [blame]
Index: lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextDocValuesReader.java
===================================================================
--- lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextDocValuesReader.java (revision 1591679)
+++ lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextDocValuesReader.java (working copy)
@@ -197,6 +197,10 @@
throw new RuntimeException(e);
}
}
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
@Override
public int length() {
@@ -254,6 +258,11 @@
return new Bits() {
@Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
+
+ @Override
public boolean get(int index) {
try {
in.seek(field.dataStartFilePointer + (9+field.pattern.length() + field.maxLength+2)*index);
Index: lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextLiveDocsFormat.java
===================================================================
--- lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextLiveDocsFormat.java (revision 1591679)
+++ lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextLiveDocsFormat.java (working copy)
@@ -161,8 +161,11 @@
public boolean get(int index) {
return bits.get(index);
}
-
@Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
+ @Override
public int length() {
return size;
}
Index: lucene/core/src/java/org/apache/lucene/codecs/lucene40/BitVector.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/codecs/lucene40/BitVector.java (revision 1591679)
+++ lucene/core/src/java/org/apache/lucene/codecs/lucene40/BitVector.java (working copy)
@@ -51,7 +51,10 @@
private int size;
private int count;
private int version;
-
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
/** Constructs a vector capable of holding <code>n</code> bits. */
public BitVector(int n) {
size = n;
Index: lucene/core/src/java/org/apache/lucene/codecs/lucene45/Lucene45DocValuesProducer.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/codecs/lucene45/Lucene45DocValuesProducer.java (revision 1591679)
+++ lucene/core/src/java/org/apache/lucene/codecs/lucene45/Lucene45DocValuesProducer.java (working copy)
@@ -624,6 +624,10 @@
throw new RuntimeException(e);
}
}
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
@Override
public int length() {
Index: lucene/core/src/java/org/apache/lucene/index/BitsSlice.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/index/BitsSlice.java (revision 1591679)
+++ lucene/core/src/java/org/apache/lucene/index/BitsSlice.java (working copy)
@@ -28,7 +28,10 @@
private final Bits parent;
private final int start;
private final int length;
-
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
// start is inclusive; end is exclusive (length = end-start)
public BitsSlice(Bits parent, ReaderSlice slice) {
this.parent = parent;
Index: lucene/core/src/java/org/apache/lucene/index/DocValues.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/index/DocValues.java (revision 1591679)
+++ lucene/core/src/java/org/apache/lucene/index/DocValues.java (working copy)
@@ -139,6 +139,11 @@
public int length() {
return maxDoc;
}
+
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
};
}
@@ -157,6 +162,11 @@
public int length() {
return maxDoc;
}
+
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
};
}
}
Index: lucene/core/src/java/org/apache/lucene/index/MultiBits.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/index/MultiBits.java (revision 1591679)
+++ lucene/core/src/java/org/apache/lucene/index/MultiBits.java (working copy)
@@ -47,8 +47,11 @@
assert doc - starts[reader] < length: "doc=" + doc + " reader=" + reader + " starts[reader]=" + starts[reader] + " length=" + length;
return true;
}
-
@Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
+ @Override
public boolean get(int doc) {
final int reader = ReaderUtil.subIndex(doc, starts);
assert reader != -1;
Index: lucene/core/src/java/org/apache/lucene/search/FieldCacheDocIdSet.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/FieldCacheDocIdSet.java (revision 1591679)
+++ lucene/core/src/java/org/apache/lucene/search/FieldCacheDocIdSet.java (working copy)
@@ -17,6 +17,7 @@
*/
import java.io.IOException;
+
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.FixedBitSet;
import org.apache.lucene.util.OpenBitSet;
@@ -61,8 +62,11 @@
public boolean get(int docid) {
return matchDoc(docid);
}
-
@Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
+ @Override
public int length() {
return maxDoc;
}
@@ -71,8 +75,11 @@
public boolean get(int docid) {
return matchDoc(docid) && acceptDocs.get(docid);
}
-
@Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
+ @Override
public int length() {
return maxDoc;
}
Index: lucene/core/src/java/org/apache/lucene/search/FieldCacheImpl.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/FieldCacheImpl.java (revision 1591679)
+++ lucene/core/src/java/org/apache/lucene/search/FieldCacheImpl.java (working copy)
@@ -1388,6 +1388,10 @@
public boolean get(int index) {
return offsetReader.get(index) != 0;
}
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
@Override
public int length() {
Index: lucene/core/src/java/org/apache/lucene/search/FilteredDocIdSet.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/FilteredDocIdSet.java (revision 1591679)
+++ lucene/core/src/java/org/apache/lucene/search/FilteredDocIdSet.java (working copy)
@@ -18,6 +18,7 @@
*/
import java.io.IOException;
+
import org.apache.lucene.util.Bits;
/**
@@ -64,8 +65,11 @@
public boolean get(int docid) {
return bits.get(docid) && FilteredDocIdSet.this.match(docid);
}
-
@Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
+ @Override
public int length() {
return bits.length();
}
Index: lucene/core/src/java/org/apache/lucene/search/FilteredQuery.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/FilteredQuery.java (revision 1591679)
+++ lucene/core/src/java/org/apache/lucene/search/FilteredQuery.java (working copy)
@@ -543,8 +543,7 @@
} else {
assert firstFilterDoc > -1;
// we are gonna advance() this scorer, so we set inorder=true/toplevel=false
- // we pass null as acceptDocs, as our filter has already respected acceptDocs, no need to do twice
- final Scorer scorer = weight.scorer(context, null);
+ final Scorer scorer = weight.scorer(context, filterAcceptDocs);
// TODO once we have way to figure out if we use RA or LeapFrog we can remove this scorer
return (scorer == null) ? null : new PrimaryAdvancedLeapFrogScorer(weight, firstFilterDoc, filterIter, scorer);
}
@@ -564,7 +563,7 @@
*/
protected boolean useRandomAccess(Bits bits, int firstFilterDoc) {
//TODO once we have a cost API on filters and scorers we should rethink this heuristic
- return firstFilterDoc < 100;
+ return firstFilterDoc < 100 && bits.providesConstantTimeAccess();
}
}
Index: lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java (revision 1591679)
+++ lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java (working copy)
@@ -18,6 +18,7 @@
*/
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
@@ -603,11 +604,18 @@
*/
protected void search(List<AtomicReaderContext> leaves, Weight weight, Collector collector)
throws IOException {
-
+
// TODO: should we make this
// threaded...? the Collector could be sync'd?
// always use single thread:
- for (AtomicReaderContext ctx : leaves) { // search each subreader
+ ArrayList<BulkScorer> scorers = new ArrayList<BulkScorer>();
+ for (AtomicReaderContext ctx : leaves) { // search each subreader
+ BulkScorer scorer = weight.bulkScorer(ctx, !collector.acceptsDocsOutOfOrder(), ctx.reader().getLiveDocs());
+ scorers.add(scorer);
+ }
+ for(int i = 0; i < leaves.size(); i++) {
+ BulkScorer scorer = scorers.get(i);
+ AtomicReaderContext ctx = leaves.get(i);
try {
collector.setNextReader(ctx);
} catch (CollectionTerminatedException e) {
@@ -615,7 +623,6 @@
// continue with the following leaf
continue;
}
- BulkScorer scorer = weight.bulkScorer(ctx, !collector.acceptsDocsOutOfOrder(), ctx.reader().getLiveDocs());
if (scorer != null) {
try {
scorer.score(collector);
@@ -624,7 +631,7 @@
// continue with the following leaf
}
}
- }
+ }
}
/** Expert: called to re-write queries into primitive queries.
Index: lucene/core/src/java/org/apache/lucene/util/Bits.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/util/Bits.java (revision 1591679)
+++ lucene/core/src/java/org/apache/lucene/util/Bits.java (working copy)
@@ -32,6 +32,9 @@
*/
public boolean get(int index);
+ /** Returns whether or not these bits provide constant-time access a.k.a. O(1) */
+ public boolean providesConstantTimeAccess();
+
/** Returns the number of bits in this set */
public int length();
@@ -56,6 +59,11 @@
public int length() {
return len;
}
+
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
}
/**
@@ -63,7 +71,10 @@
*/
public static class MatchNoBits implements Bits {
final int len;
-
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
public MatchNoBits( int len ) {
this.len = len;
}
Index: lucene/core/src/java/org/apache/lucene/util/DocIdBitSet.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/util/DocIdBitSet.java (revision 1591679)
+++ lucene/core/src/java/org/apache/lucene/util/DocIdBitSet.java (working copy)
@@ -40,7 +40,10 @@
public Bits bits() {
return this;
}
-
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
/** This DocIdSet implementation is cacheable. */
@Override
public boolean isCacheable() {
Index: lucene/core/src/java/org/apache/lucene/util/FixedBitSet.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/util/FixedBitSet.java (revision 1591679)
+++ lucene/core/src/java/org/apache/lucene/util/FixedBitSet.java (working copy)
@@ -606,4 +606,9 @@
// empty sets from returning 0, which is too common.
return (int) ((h>>32) ^ h) + 0x98761234;
}
+
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
}
Index: lucene/core/src/java/org/apache/lucene/util/OpenBitSet.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/util/OpenBitSet.java (revision 1591679)
+++ lucene/core/src/java/org/apache/lucene/util/OpenBitSet.java (working copy)
@@ -119,8 +119,11 @@
public DocIdSetIterator iterator() {
return new OpenBitSetIterator(bits, wlen);
}
-
@Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
+ @Override
public Bits bits() {
return this;
}
Index: lucene/core/src/test/org/apache/lucene/codecs/lucene41/TestBlockPostingsFormat3.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/codecs/lucene41/TestBlockPostingsFormat3.java (revision 1591679)
+++ lucene/core/src/test/org/apache/lucene/codecs/lucene41/TestBlockPostingsFormat3.java (working copy)
@@ -513,8 +513,11 @@
public boolean get(int index) {
return bits.get(index);
}
-
@Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
+ @Override
public int length() {
return bits.length();
}
Index: lucene/core/src/test/org/apache/lucene/search/TestFilteredQuery.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestFilteredQuery.java (revision 1591679)
+++ lucene/core/src/test/org/apache/lucene/search/TestFilteredQuery.java (working copy)
@@ -449,8 +449,11 @@
bitSet.get(index));
return bitSet.get(index);
}
-
@Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
+ @Override
public int length() {
return bitSet.length();
}
Index: lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRange.java
===================================================================
--- lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRange.java (revision 1591679)
+++ lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRange.java (working copy)
@@ -151,6 +151,10 @@
}
return accept(values.doubleVal(docID));
}
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
@Override
public int length() {
Index: lucene/facet/src/java/org/apache/lucene/facet/range/LongRange.java
===================================================================
--- lucene/facet/src/java/org/apache/lucene/facet/range/LongRange.java (revision 1591679)
+++ lucene/facet/src/java/org/apache/lucene/facet/range/LongRange.java (working copy)
@@ -143,6 +143,10 @@
}
return accept(values.longVal(docID));
}
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
@Override
public int length() {
Index: lucene/misc/src/java/org/apache/lucene/index/sorter/SortingAtomicReader.java
===================================================================
--- lucene/misc/src/java/org/apache/lucene/index/sorter/SortingAtomicReader.java (revision 1591679)
+++ lucene/misc/src/java/org/apache/lucene/index/sorter/SortingAtomicReader.java (working copy)
@@ -133,6 +133,10 @@
public boolean get(int index) {
return liveDocs.get(docMap.oldToNew(index));
}
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
@Override
public int length() {
@@ -236,6 +240,10 @@
public boolean get(int index) {
return in.get(docMap.newToOld(index));
}
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
@Override
public int length() {
Index: lucene/queries/src/java/org/apache/lucene/queries/function/FunctionQuery.java
===================================================================
--- lucene/queries/src/java/org/apache/lucene/queries/function/FunctionQuery.java (revision 1591679)
+++ lucene/queries/src/java/org/apache/lucene/queries/function/FunctionQuery.java (working copy)
@@ -23,6 +23,7 @@
import org.apache.lucene.search.*;
import org.apache.lucene.index.MultiFields;
import org.apache.lucene.util.Bits;
+import org.apache.lucene.util.LazyIteratorBackedBits;
import java.io.IOException;
import java.util.Set;
@@ -116,6 +117,7 @@
this.reader = context.reader();
this.maxDoc = reader.maxDoc();
this.acceptDocs = acceptDocs;
+ func.setBitsForFiltering(acceptDocs);
vals = func.getValues(weight.context, context);
}
@@ -135,7 +137,7 @@
if (doc>=maxDoc) {
return doc=NO_MORE_DOCS;
}
- if (acceptDocs != null && !acceptDocs.get(doc)) continue;
+ if (acceptDocs != null && acceptDocs.providesConstantTimeAccess() && !acceptDocs.get(doc)) continue;
return doc;
}
}
Index: lucene/queries/src/java/org/apache/lucene/queries/function/ValueSource.java
===================================================================
--- lucene/queries/src/java/org/apache/lucene/queries/function/ValueSource.java (revision 1591679)
+++ lucene/queries/src/java/org/apache/lucene/queries/function/ValueSource.java (working copy)
@@ -22,6 +22,7 @@
import org.apache.lucene.search.FieldComparatorSource;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.SortField;
+import org.apache.lucene.util.Bits;
import java.io.IOException;
import java.util.IdentityHashMap;
@@ -42,6 +43,9 @@
*/
public abstract FunctionValues getValues(Map context, AtomicReaderContext readerContext) throws IOException;
+ public void setBitsForFiltering(Bits acceptedDocs) {
+ }
+
@Override
public abstract boolean equals(Object o);
Index: lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/ScaleFloatFunction.java
===================================================================
--- lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/ScaleFloatFunction.java (revision 1591679)
+++ lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/ScaleFloatFunction.java (working copy)
@@ -17,121 +17,176 @@
package org.apache.lucene.queries.function.valuesource;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.index.IndexReaderContext;
import org.apache.lucene.index.ReaderUtil;
+import org.apache.lucene.index.SlowCompositeReaderWrapper;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.docvalues.FloatDocValues;
import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.util.Bits;
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
/**
* Scales values to be between min and max.
- * <p>This implementation currently traverses all of the source values to obtain
- * their min and max.
- * <p>This implementation currently cannot distinguish when documents have been
- * deleted or documents that have no value, and 0.0 values will be used for
- * these cases. This means that if values are normally all greater than 0.0, one can
- * still end up with 0.0 as the min value to map from. In these cases, an
- * appropriate map() function could be used as a workaround to change 0.0
- * to a value in the real range.
*/
-public class ScaleFloatFunction extends ValueSource {
+public class ScaleFloatFunction extends ValueSource{
protected final ValueSource source;
protected final float min;
protected final float max;
-
+ private Bits acceptedDocuments = null;
+
public ScaleFloatFunction(ValueSource source, float min, float max) {
this.source = source;
this.min = min;
this.max = max;
}
-
+
@Override
public String description() {
return "scale(" + source.description() + "," + min + "," + max + ")";
}
-
+
+ @Override
+ public void setBitsForFiltering(Bits acceptedDocs) {
+ this.acceptedDocuments = acceptedDocs;
+ }
+
private static class ScaleInfo {
- float minVal;
- float maxVal;
+ public float minimumValueToScaleTo;
+ public float maximumValueToScaleTo;
+ private float maxObservedValue = Float.NEGATIVE_INFINITY;
+ private float minObservedValue = Float.POSITIVE_INFINITY;
+ private float scaleConstant = 0;
+
+ public float getMaxObservedValue() {
+ return maxObservedValue;
+ }
+ public float getMinObservedValue() {
+ return minObservedValue;
+ }
+ public void setMinObservedValue(float min) {
+ this.minObservedValue = min;
+ recalculateScaleConstant();
+ }
+ public void setMaxObservedValue(float max) {
+ this.maxObservedValue = max;
+ recalculateScaleConstant();
+ }
+ private void recalculateScaleConstant() {
+ this.scaleConstant = (this.maxObservedValue - this.minObservedValue ==0) ? 0 : (this.maximumValueToScaleTo-this.minimumValueToScaleTo)/(this.maxObservedValue-this.minObservedValue);
+ }
}
-
- private ScaleInfo createScaleInfo(Map context, AtomicReaderContext readerContext) throws IOException {
- final List<AtomicReaderContext> leaves = ReaderUtil.getTopLevelContext(readerContext).leaves();
-
- float minVal = Float.POSITIVE_INFINITY;
- float maxVal = Float.NEGATIVE_INFINITY;
-
- for (AtomicReaderContext leaf : leaves) {
- int maxDoc = leaf.reader().maxDoc();
- FunctionValues vals = source.getValues(context, leaf);
- for (int i=0; i<maxDoc; i++) {
-
- float val = vals.floatVal(i);
- if ((Float.floatToRawIntBits(val) & (0xff<<23)) == 0xff<<23) {
- // if the exponent in the float is all ones, then this is +Inf, -Inf or NaN
- // which don't make sense to factor into the scale function
- continue;
+
+ private ScaleInfo updateScaleInfo(Map context, AtomicReaderContext readerContext) throws IOException {
+ ScaleInfo scaleInfo = this.retrieveScaleInfoFromContext(context);
+ float minVal = scaleInfo.getMinObservedValue();
+ float maxVal = scaleInfo.getMaxObservedValue();
+
+ //find the first legitimate value to initialize our min/max and avoid having to check values against both later on
+ if(leafHasDocuments(readerContext) && minVal == Float.POSITIVE_INFINITY && maxVal == Float.NEGATIVE_INFINITY) {
+ FunctionValues vals = source.getValues(context, readerContext);
+
+ float firstLegitimateValue = Float.POSITIVE_INFINITY;
+ for(int i =0; i < readerContext.reader().maxDoc(); i++) {
+ if(docIsInBits(this.acceptedDocuments, i)) {
+ float currentValue = vals.floatVal(i);
+ if(!(this.valueIsPositiveOrNegativeInfinityOrNotANumber(currentValue))) {
+ firstLegitimateValue = currentValue;
+ break;
+ }
+ }
}
- if (val < minVal) {
- minVal = val;
+ if(!(this.valueIsPositiveOrNegativeInfinityOrNotANumber(firstLegitimateValue))) {
+ minVal = maxVal = firstLegitimateValue;
}
- if (val > maxVal) {
- maxVal = val;
+ }
+
+ if(leafHasDocuments(readerContext)) {
+ int maxDoc = readerContext.reader().maxDoc();
+ FunctionValues vals = source.getValues(context, readerContext);
+ for (int i=0; i<maxDoc; i++) {
+ if(docIsInBits(this.acceptedDocuments, i)) {
+ float val = vals.floatVal(i);
+ if (val < minVal && !(valueIsPositiveOrNegativeInfinityOrNotANumber(val))) { // if the exponent in the float is all ones, then this is +Inf, -Inf or NaN which don't make sense to factor into the scale function
+ minVal = val;
+ }
+ else if (val > maxVal && !(valueIsPositiveOrNegativeInfinityOrNotANumber(val))) { // if the exponent in the float is all ones, then this is +Inf, -Inf or NaN which don't make sense to factor into the scale function
+ maxVal = val;
+ }
+ }
}
}
- }
-
- if (minVal == Float.POSITIVE_INFINITY) {
- // must have been an empty index
+
+ if (minVal == Float.POSITIVE_INFINITY) { // must have been an empty index
minVal = maxVal = 0;
}
-
- ScaleInfo scaleInfo = new ScaleInfo();
- scaleInfo.minVal = minVal;
- scaleInfo.maxVal = maxVal;
+
+ scaleInfo.setMinObservedValue(minVal);
+ scaleInfo.setMaxObservedValue(maxVal);
context.put(ScaleFloatFunction.this, scaleInfo);
return scaleInfo;
}
-
+
+ private ScaleInfo retrieveScaleInfoFromContext(Map context) {
+ ScaleInfo returnValue = (ScaleInfo)context.get(ScaleFloatFunction.this);
+ if(returnValue == null) {
+ returnValue = new ScaleInfo();
+ returnValue.minimumValueToScaleTo = this.min;
+ returnValue.maximumValueToScaleTo = this.max;
+ }
+ return returnValue;
+ }
+
+ private boolean docIsInBits(Bits bitsToCheck, int docID) {
+ if(bitsToCheck == null) return true;
+ else return bitsToCheck.get(docID);
+ }
+
+ private boolean leafHasDocuments(AtomicReaderContext leaf) {
+ return leaf.reader().maxDoc() > 0;
+ }
+
+ private boolean valueIsPositiveOrNegativeInfinityOrNotANumber(float value) {
+ // if the exponent in the float is all ones, then this is +Inf, -Inf or NaN which don't make sense to factor into the scale function
+ return ((Float.floatToRawIntBits(value) & (0xff<<23)) == 0xff<<23);
+ }
+
@Override
public FunctionValues getValues(Map context, AtomicReaderContext readerContext) throws IOException {
-
- ScaleInfo scaleInfo = (ScaleInfo)context.get(ScaleFloatFunction.this);
- if (scaleInfo == null) {
- scaleInfo = createScaleInfo(context, readerContext);
- }
-
- final float scale = (scaleInfo.maxVal-scaleInfo.minVal==0) ? 0 : (max-min)/(scaleInfo.maxVal-scaleInfo.minVal);
- final float minSource = scaleInfo.minVal;
- final float maxSource = scaleInfo.maxVal;
-
+
+ ScaleInfo scaleInfo = updateScaleInfo(context, readerContext);
+ final ScaleInfo persistedScaleInfo = scaleInfo;
final FunctionValues vals = source.getValues(context, readerContext);
-
+
return new FloatDocValues(this) {
@Override
public float floatVal(int doc) {
- return (vals.floatVal(doc) - minSource) * scale + min;
+ float scale = persistedScaleInfo.scaleConstant;
+ float docScore = vals.floatVal(doc);
+ return (docScore - persistedScaleInfo.getMinObservedValue()) * scale + min;
}
@Override
public String toString(int doc) {
- return "scale(" + vals.toString(doc) + ",toMin=" + min + ",toMax=" + max
- + ",fromMin=" + minSource
- + ",fromMax=" + maxSource
- + ")";
- }
+ return "scale(" + Float.toString(vals.floatVal(doc)) + ",toMin=" + min + ",toMax=" + max
+ + ",fromMin=" + persistedScaleInfo.minObservedValue
+ + ",fromMax=" + persistedScaleInfo.maxObservedValue
+ + ")";
+ }
};
}
-
+
@Override
public void createWeight(Map context, IndexSearcher searcher) throws IOException {
source.createWeight(context, searcher);
}
-
+
@Override
public int hashCode() {
int h = Float.floatToIntBits(min);
@@ -141,13 +196,13 @@
h += source.hashCode();
return h;
}
-
+
@Override
public boolean equals(Object o) {
if (ScaleFloatFunction.class != o.getClass()) return false;
ScaleFloatFunction other = (ScaleFloatFunction)o;
return this.min == other.min
- && this.max == other.max
- && this.source.equals(other.source);
+ && this.max == other.max
+ && this.source.equals(other.source);
}
}
Index: lucene/spatial/src/java/org/apache/lucene/spatial/prefix/ContainsPrefixTreeFilter.java
===================================================================
--- lucene/spatial/src/java/org/apache/lucene/spatial/prefix/ContainsPrefixTreeFilter.java (revision 1591679)
+++ lucene/spatial/src/java/org/apache/lucene/spatial/prefix/ContainsPrefixTreeFilter.java (working copy)
@@ -19,6 +19,7 @@
import com.spatial4j.core.shape.Shape;
import com.spatial4j.core.shape.SpatialRelation;
+
import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.index.DocsEnum;
import org.apache.lucene.search.DocIdSet;
@@ -188,6 +189,10 @@
/** A hash based mutable set of docIds. If this were Solr code then we might
* use a combination of HashDocSet and SortedIntDocSet instead. */
private static class SmallDocSet extends DocIdSet implements Bits {
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
private final SentinelIntSet intSet;
private int maxInt = 0;
Index: lucene/spatial/src/java/org/apache/lucene/spatial/serialized/SerializedDVStrategy.java
===================================================================
--- lucene/spatial/src/java/org/apache/lucene/spatial/serialized/SerializedDVStrategy.java (revision 1591679)
+++ lucene/spatial/src/java/org/apache/lucene/spatial/serialized/SerializedDVStrategy.java (working copy)
@@ -21,6 +21,7 @@
import com.spatial4j.core.io.BinaryCodec;
import com.spatial4j.core.shape.Point;
import com.spatial4j.core.shape.Shape;
+
import org.apache.lucene.document.BinaryDocValuesField;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.AtomicReaderContext;
@@ -163,6 +164,10 @@
return false;
return predFuncValues.boolVal(index);
}
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
@Override
public int length() {
Index: lucene/test-framework/src/java/org/apache/lucene/index/AssertingAtomicReader.java
===================================================================
--- lucene/test-framework/src/java/org/apache/lucene/index/AssertingAtomicReader.java (revision 1591679)
+++ lucene/test-framework/src/java/org/apache/lucene/index/AssertingAtomicReader.java (working copy)
@@ -611,7 +611,11 @@
/** Wraps a Bits but with additional asserts */
public static class AssertingBits implements Bits {
final Bits in;
-
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
+
public AssertingBits(Bits in) {
this.in = in;
}
Index: lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java
===================================================================
--- lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java (revision 1591679)
+++ lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java (working copy)
@@ -1675,6 +1675,10 @@
public boolean get(int index) {
return bits.get(index);
}
+ @Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
@Override
public int length() {
Index: solr/core/src/java/org/apache/solr/search/BitDocSet.java
===================================================================
--- solr/core/src/java/org/apache/solr/search/BitDocSet.java (revision 1591679)
+++ solr/core/src/java/org/apache/solr/search/BitDocSet.java (working copy)
@@ -304,7 +304,6 @@
return adjustedDoc = (pos >= 0 && pos < max) ? pos - base : NO_MORE_DOCS;
}
}
-
@Override
public int advance(int target) {
if (target == NO_MORE_DOCS) return adjustedDoc = NO_MORE_DOCS;
@@ -342,8 +341,11 @@
public boolean get(int index) {
return bs.get(index + base);
}
-
@Override
+ public boolean providesConstantTimeAccess() {
+ return true;
+ }
+ @Override
public int length() {
return maxDoc;
}
Index: solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
===================================================================
--- solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java (revision 1591679)
+++ solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java (working copy)
@@ -88,6 +88,7 @@
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.FixedBitSet;
+import org.apache.lucene.util.LazyIteratorBackedBits;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.params.ModifiableSolrParams;
@@ -2458,6 +2459,8 @@
private class FilterSet extends DocIdSet {
DocIdSet docIdSet;
AtomicReaderContext context;
+ private boolean bitsHaveBeenGenerated = false;
+ private Bits lazyLoadedBits = null;
public FilterSet(DocIdSet docIdSet, AtomicReaderContext context) {
this.docIdSet = docIdSet;
@@ -2485,8 +2488,21 @@
@Override
public Bits bits() throws IOException {
- return null; // don't use random access
+ if(bitsHaveBeenGenerated) {
+ return lazyLoadedBits;
+ }
+ else {
+ lazyLoadedBits = generateBits();
+ bitsHaveBeenGenerated = true;
+ return lazyLoadedBits;
+ }
}
+
+ private Bits generateBits() throws IOException {
+ DocIdSetIterator iter = this.iterator();
+ LazyIteratorBackedBits myBits = new LazyIteratorBackedBits(65536,iter);
+ return myBits;
+ }
}
private static class FilterIterator extends DocIdSetIterator {