

diff -ruN -x .svn -x build lucene-clean-trunk/lucene/CHANGES.txt lucene-flexscoring/lucene/CHANGES.txt
--- lucene-clean-trunk/lucene/CHANGES.txt	2011-09-08 17:01:39.556036271 -0400
+++ lucene-flexscoring/lucene/CHANGES.txt	2011-09-09 12:32:55.906062206 -0400
@@ -487,6 +487,34 @@
 * LUCENE-3376: ReusableAnalyzerBase has been moved from modules/analysis/common
   into lucene/src/java/org/apache/lucene/analysis (Chris Male)
 
+* LUCENE-2959: Added a variety of different relevance ranking systems to Lucene.
+
+  - Added Okapi BM25, Language Models, Divergence from Randomness, and 
+    Information-Based Models. The models are pluggable, support all of lucene's 
+    features (boosts, slops, explanations, etc) and queries (spans, etc).
+
+  - All models default to the same index-time norm encoding as DefaultSimilarity: 
+    so you can easily try these out/switch back and forth/run experiments and 
+    comparisons without reindexing. Note: most of the models do rely upon index
+    statistics that are new in Lucene 4.0, so for existing 3.x indexes its a good
+    idea to upgrade your index to the new format with IndexUpgrader first.
+
+  - Added a new subclass SimilarityBase which provides a simplified API 
+    for plugging in new ranking algorithms without dealing with all of the
+    nuances and implementation details of Lucene. 
+
+  - Added a new helper class BasicSimilarityProvider that just applies one
+    scoring algorithm to all fields, with queryNorm() and coord() returning 1.
+    In general, it is recommended to disable coord() when using the new models.
+    For example, to use BM25 for all fields: 
+     searcher.setSimilarityProvider(new BasicSimilarityProvider(new BM25Similarity()));
+
+    If you instead want to apply different similarities (e.g. ones with different
+    parameter values or different algorithms entirely) to different fields, implement
+    SimilarityProvider with your per-field logic.
+
+  (David Mark Nemeskey via Robert Muir)
+
 Optimizations
 
 * LUCENE-2588: Don't store unnecessary suffixes when writing the terms


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexWriter.java lucene-flexscoring/lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexWriter.java
--- lucene-clean-trunk/lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexWriter.java	2011-08-29 12:22:46.151459551 -0400
+++ lucene-flexscoring/lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexWriter.java	2011-08-29 13:41:01.901459544 -0400
@@ -43,7 +43,7 @@
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermVectorOffsetInfo;
 import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.SimilarityProvider;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.CollectionUtil;
 import org.apache.lucene.util.AttributeImpl;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java lucene-flexscoring/lucene/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java
--- lucene-clean-trunk/lucene/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java	2011-08-29 12:22:46.181459551 -0400
+++ lucene-flexscoring/lucene/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java	2011-08-29 13:41:08.641459544 -0400
@@ -57,8 +57,8 @@
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.Scorer;
-import org.apache.lucene.search.Similarity;
-import org.apache.lucene.search.SimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.RAMDirectory; // for javadocs
 import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.Bits;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/contrib/misc/src/java/org/apache/lucene/index/FieldNormModifier.java lucene-flexscoring/lucene/contrib/misc/src/java/org/apache/lucene/index/FieldNormModifier.java
--- lucene-clean-trunk/lucene/contrib/misc/src/java/org/apache/lucene/index/FieldNormModifier.java	2011-08-29 12:22:46.221459551 -0400
+++ lucene-flexscoring/lucene/contrib/misc/src/java/org/apache/lucene/index/FieldNormModifier.java	2011-08-29 13:41:22.121459544 -0400
@@ -22,9 +22,9 @@
 import java.util.List;
 import java.util.ArrayList;
 
-import org.apache.lucene.search.DefaultSimilarity;
-import org.apache.lucene.search.Similarity;
-import org.apache.lucene.search.SimilarityProvider;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.FSDirectory;
 import org.apache.lucene.util.Bits;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/contrib/misc/src/java/org/apache/lucene/misc/SweetSpotSimilarity.java lucene-flexscoring/lucene/contrib/misc/src/java/org/apache/lucene/misc/SweetSpotSimilarity.java
--- lucene-clean-trunk/lucene/contrib/misc/src/java/org/apache/lucene/misc/SweetSpotSimilarity.java	2011-07-08 01:31:28.311820268 -0400
+++ lucene-flexscoring/lucene/contrib/misc/src/java/org/apache/lucene/misc/SweetSpotSimilarity.java	2011-08-23 08:43:39.601460295 -0400
@@ -17,7 +17,7 @@
 
 package org.apache.lucene.misc;
 
-import org.apache.lucene.search.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
 import org.apache.lucene.index.FieldInvertState;
 
 /**


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/contrib/misc/src/test/org/apache/lucene/index/TestFieldNormModifier.java lucene-flexscoring/lucene/contrib/misc/src/test/org/apache/lucene/index/TestFieldNormModifier.java
--- lucene-clean-trunk/lucene/contrib/misc/src/test/org/apache/lucene/index/TestFieldNormModifier.java	2011-08-29 12:22:46.211459551 -0400
+++ lucene-flexscoring/lucene/contrib/misc/src/test/org/apache/lucene/index/TestFieldNormModifier.java	2011-08-29 13:41:16.181459544 -0400
@@ -26,13 +26,13 @@
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.search.Collector;
-import org.apache.lucene.search.DefaultSimilarity;
-import org.apache.lucene.search.DefaultSimilarityProvider;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Scorer;
-import org.apache.lucene.search.Similarity;
-import org.apache.lucene.search.SimilarityProvider;
 import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/contrib/misc/src/test/org/apache/lucene/misc/SweetSpotSimilarityTest.java lucene-flexscoring/lucene/contrib/misc/src/test/org/apache/lucene/misc/SweetSpotSimilarityTest.java
--- lucene-clean-trunk/lucene/contrib/misc/src/test/org/apache/lucene/misc/SweetSpotSimilarityTest.java	2011-07-08 01:31:28.301820268 -0400
+++ lucene-flexscoring/lucene/contrib/misc/src/test/org/apache/lucene/misc/SweetSpotSimilarityTest.java	2011-08-23 08:43:39.601460295 -0400
@@ -18,11 +18,11 @@
 
 package org.apache.lucene.misc;
 
-import org.apache.lucene.search.DefaultSimilarity;
-import org.apache.lucene.search.DefaultSimilarityProvider;
-import org.apache.lucene.search.Similarity;
-import org.apache.lucene.search.TFIDFSimilarity;
-import org.apache.lucene.search.SimilarityProvider;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
+import org.apache.lucene.search.similarities.TFIDFSimilarity;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.index.FieldInvertState;
 


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/contrib/misc/src/test/org/apache/lucene/misc/TestLengthNormModifier.java lucene-flexscoring/lucene/contrib/misc/src/test/org/apache/lucene/misc/TestLengthNormModifier.java
--- lucene-clean-trunk/lucene/contrib/misc/src/test/org/apache/lucene/misc/TestLengthNormModifier.java	2011-08-29 12:22:46.211459551 -0400
+++ lucene-flexscoring/lucene/contrib/misc/src/test/org/apache/lucene/misc/TestLengthNormModifier.java	2011-08-29 13:41:18.961459544 -0400
@@ -31,13 +31,13 @@
 import org.apache.lucene.index.MultiNorms;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.Collector;
-import org.apache.lucene.search.DefaultSimilarity;
-import org.apache.lucene.search.DefaultSimilarityProvider;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Scorer;
-import org.apache.lucene.search.Similarity;
-import org.apache.lucene.search.SimilarityProvider;
 import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/contrib/sandbox/src/java/org/apache/lucene/sandbox/queries/FuzzyLikeThisQuery.java lucene-flexscoring/lucene/contrib/sandbox/src/java/org/apache/lucene/sandbox/queries/FuzzyLikeThisQuery.java
--- lucene-clean-trunk/lucene/contrib/sandbox/src/java/org/apache/lucene/sandbox/queries/FuzzyLikeThisQuery.java	2011-08-22 08:20:00.981460417 -0400
+++ lucene-flexscoring/lucene/contrib/sandbox/src/java/org/apache/lucene/sandbox/queries/FuzzyLikeThisQuery.java	2011-08-23 09:54:53.951460289 -0400
@@ -31,6 +31,8 @@
 import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.*;
+import org.apache.lucene.search.similarities.TFIDFSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
 import org.apache.lucene.util.AttributeSource;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.PriorityQueue;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/document/Field.java lucene-flexscoring/lucene/src/java/org/apache/lucene/document/Field.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/document/Field.java	2011-08-30 13:37:26.731459424 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/document/Field.java	2011-08-30 13:52:29.611459423 -0400
@@ -226,14 +226,14 @@
    * document.
    *
    * <p>The boost is used to compute the norm factor for the field.  By
-   * default, in the {@link org.apache.lucene.search.Similarity#computeNorm(FieldInvertState)} method, 
+   * default, in the {@link org.apache.lucene.search.similarities.Similarity#computeNorm(FieldInvertState)} method, 
    * the boost value is multiplied by the length normalization factor and then
-   * rounded by {@link org.apache.lucene.search.DefaultSimilarity#encodeNormValue(float)} before it is stored in the
+   * rounded by {@link org.apache.lucene.search.similarities.DefaultSimilarity#encodeNormValue(float)} before it is stored in the
    * index.  One should attempt to ensure that this product does not overflow
    * the range of that encoding.
    *
-   * @see org.apache.lucene.search.Similarity#computeNorm(FieldInvertState)
-   * @see org.apache.lucene.search.DefaultSimilarity#encodeNormValue(float)
+   * @see org.apache.lucene.search.similarities.Similarity#computeNorm(FieldInvertState)
+   * @see org.apache.lucene.search.similarities.DefaultSimilarity#encodeNormValue(float)
    */
   public void setBoost(float boost) {
     this.boost = boost;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/index/DocumentsWriter.java lucene-flexscoring/lucene/src/java/org/apache/lucene/index/DocumentsWriter.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/index/DocumentsWriter.java	2011-08-29 12:22:46.861459551 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/index/DocumentsWriter.java	2011-08-29 13:45:06.071459544 -0400
@@ -32,7 +32,7 @@
 import org.apache.lucene.index.DocumentsWriterPerThreadPool.ThreadState;
 import org.apache.lucene.index.FieldInfos.FieldNumberBiMap;
 import org.apache.lucene.search.Query;
-import org.apache.lucene.search.SimilarityProvider;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.AlreadyClosedException;
 import org.apache.lucene.store.Directory;
 


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/index/DocumentsWriterPerThread.java lucene-flexscoring/lucene/src/java/org/apache/lucene/index/DocumentsWriterPerThread.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/index/DocumentsWriterPerThread.java	2011-09-08 17:01:39.526036271 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/index/DocumentsWriterPerThread.java	2011-09-08 12:56:47.666030849 -0400
@@ -26,7 +26,7 @@
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.index.DocumentsWriterDeleteQueue.DeleteSlice;
-import org.apache.lucene.search.SimilarityProvider;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.FlushInfo;
 import org.apache.lucene.store.IOContext;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/index/IndexReader.java lucene-flexscoring/lucene/src/java/org/apache/lucene/index/IndexReader.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/index/IndexReader.java	2011-09-08 17:01:39.526036271 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/index/IndexReader.java	2011-09-08 12:56:57.076030851 -0400
@@ -32,7 +32,7 @@
 import org.apache.lucene.index.codecs.PerDocValues;
 import org.apache.lucene.index.values.IndexDocValues;
 import org.apache.lucene.search.FieldCache; // javadocs
-import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.store.*;
 import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.Bits;
@@ -1012,7 +1012,7 @@
    *
    * @see #norms(String)
    * @see Similarity#computeNorm(FieldInvertState)
-   * @see org.apache.lucene.search.DefaultSimilarity#decodeNormValue(byte)
+   * @see org.apache.lucene.search.similarities.DefaultSimilarity#decodeNormValue(byte)
    * @throws StaleReaderException if the index has changed
    *  since this reader was opened
    * @throws CorruptIndexException if the index is corrupt


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/index/IndexWriterConfig.java lucene-flexscoring/lucene/src/java/org/apache/lucene/index/IndexWriterConfig.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/index/IndexWriterConfig.java	2011-07-27 00:16:39.302328617 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/index/IndexWriterConfig.java	2011-08-23 09:45:29.771460290 -0400
@@ -22,7 +22,7 @@
 import org.apache.lucene.index.IndexWriter.IndexReaderWarmer;
 import org.apache.lucene.index.codecs.CodecProvider;
 import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.SimilarityProvider;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.util.Version;
 
 /**


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/index/NormsWriterPerField.java lucene-flexscoring/lucene/src/java/org/apache/lucene/index/NormsWriterPerField.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/index/NormsWriterPerField.java	2011-07-08 01:31:28.421820268 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/index/NormsWriterPerField.java	2011-08-23 08:43:39.621460295 -0400
@@ -17,7 +17,7 @@
  * limitations under the License.
  */
 
-import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.util.ArrayUtil;
 
 /** Taps into DocInverter, as an InvertedDocEndConsumer,


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/BooleanQuery.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/BooleanQuery.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/BooleanQuery.java	2011-07-24 19:00:25.772328885 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/BooleanQuery.java	2011-08-23 09:52:56.061460289 -0400
@@ -24,7 +24,8 @@
 import org.apache.lucene.util.ToStringUtils;
 import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.search.ConjunctionTermScorer.DocsAndFreqs;
-import org.apache.lucene.search.Similarity.ExactDocScorer;
+import org.apache.lucene.search.similarities.SimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity.ExactDocScorer;
 import org.apache.lucene.search.TermQuery.TermWeight;
 
 import java.io.IOException;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/BooleanScorer2.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/BooleanScorer2.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/BooleanScorer2.java	2011-08-17 23:39:13.791460945 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/BooleanScorer2.java	2011-08-23 09:53:45.661460289 -0400
@@ -24,6 +24,7 @@
 
 import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.search.BooleanQuery.BooleanWeight;
+import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.search.Scorer.ChildScorer;
 
 /* See the description in BooleanScorer.java, comparing


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/ConjunctionTermScorer.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/ConjunctionTermScorer.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/ConjunctionTermScorer.java	2011-07-24 19:00:25.772328885 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/ConjunctionTermScorer.java	2011-08-23 09:53:19.801460289 -0400
@@ -18,7 +18,7 @@
  */
 
 import org.apache.lucene.index.DocsEnum;
-import org.apache.lucene.search.Similarity.ExactDocScorer;
+import org.apache.lucene.search.similarities.Similarity.ExactDocScorer;
 import org.apache.lucene.util.ArrayUtil;
 import java.io.IOException;
 import java.util.Comparator;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/DefaultSimilarity.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/DefaultSimilarity.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/DefaultSimilarity.java	2011-07-17 06:27:33.748948135 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/DefaultSimilarity.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,88 +0,0 @@
-package org.apache.lucene.search;
-
-import org.apache.lucene.index.FieldInvertState;
-import org.apache.lucene.util.BytesRef;
-
-/**
- * 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.
- */
-
-/** Expert: Default scoring implementation. */
-public class DefaultSimilarity extends TFIDFSimilarity {
-
-  /** Implemented as
-   *  <code>state.getBoost()*lengthNorm(numTerms)</code>, where
-   *  <code>numTerms</code> is {@link FieldInvertState#getLength()} if {@link
-   *  #setDiscountOverlaps} is false, else it's {@link
-   *  FieldInvertState#getLength()} - {@link
-   *  FieldInvertState#getNumOverlap()}.
-   *
-   *  @lucene.experimental */
-  @Override
-  public byte computeNorm(FieldInvertState state) {
-    final int numTerms;
-    if (discountOverlaps)
-      numTerms = state.getLength() - state.getNumOverlap();
-    else
-      numTerms = state.getLength();
-    return encodeNormValue(state.getBoost() * ((float) (1.0 / Math.sqrt(numTerms))));
-  }
-
-  /** Implemented as <code>sqrt(freq)</code>. */
-  @Override
-  public float tf(float freq) {
-    return (float)Math.sqrt(freq);
-  }
-    
-  /** Implemented as <code>1 / (distance + 1)</code>. */
-  @Override
-  public float sloppyFreq(int distance) {
-    return 1.0f / (distance + 1);
-  }
-  
-  /** The default implementation returns <code>1</code> */
-  @Override
-  public float scorePayload(int doc, int start, int end, BytesRef payload) {
-    return 1;
-  }
-
-  /** Implemented as <code>log(numDocs/(docFreq+1)) + 1</code>. */
-  @Override
-  public float idf(int docFreq, int numDocs) {
-    return (float)(Math.log(numDocs/(double)(docFreq+1)) + 1.0);
-  }
-    
-  // Default true
-  protected boolean discountOverlaps = true;
-
-  /** Determines whether overlap tokens (Tokens with
-   *  0 position increment) are ignored when computing
-   *  norm.  By default this is true, meaning overlap
-   *  tokens do not count when computing norms.
-   *
-   *  @lucene.experimental
-   *
-   *  @see #computeNorm
-   */
-  public void setDiscountOverlaps(boolean v) {
-    discountOverlaps = v;
-  }
-
-  /** @see #setDiscountOverlaps */
-  public boolean getDiscountOverlaps() {
-    return discountOverlaps;
-  }
-}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/DefaultSimilarityProvider.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/DefaultSimilarityProvider.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/DefaultSimilarityProvider.java	2011-05-08 10:52:19.350078710 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/DefaultSimilarityProvider.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-package org.apache.lucene.search;
-
-/**
- * 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.
- */
-
-/** 
- * Expert: Default scoring provider. 
- * <p>
- * Returns {@link DefaultSimilarity} for every field
- */
-public class DefaultSimilarityProvider implements SimilarityProvider {
-  private static final Similarity impl = new DefaultSimilarity();
-  
-  /** Implemented as <code>overlap / maxOverlap</code>. */
-  public float coord(int overlap, int maxOverlap) {
-    return overlap / (float)maxOverlap;
-  }
-
-  /** Implemented as <code>1/sqrt(sumOfSquaredWeights)</code>. */
-  public float queryNorm(float sumOfSquaredWeights) {
-    return (float)(1.0 / Math.sqrt(sumOfSquaredWeights));
-  }
-
-  public Similarity get(String field) {
-    return impl;
-  }
-}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/ExactPhraseScorer.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/ExactPhraseScorer.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/ExactPhraseScorer.java	2011-07-08 01:31:28.421820268 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/ExactPhraseScorer.java	2011-08-23 08:43:39.661460295 -0400
@@ -21,6 +21,7 @@
 import java.util.Arrays;
 
 import org.apache.lucene.index.*;
+import org.apache.lucene.search.similarities.Similarity;
 
 final class ExactPhraseScorer extends Scorer {
   private final int endMinus1;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/IndexSearcher.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/IndexSearcher.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/IndexSearcher.java	2011-08-29 12:22:46.711459551 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/IndexSearcher.java	2011-08-29 13:44:26.011459544 -0400
@@ -38,6 +38,8 @@
 import org.apache.lucene.index.StoredFieldVisitor;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.Weight.ScorerContext;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.NIOFSDirectory;    // javadoc
 import org.apache.lucene.util.ReaderUtil;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/MultiPhraseQuery.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/MultiPhraseQuery.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/MultiPhraseQuery.java	2011-07-20 07:05:53.828132695 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/MultiPhraseQuery.java	2011-08-30 00:42:46.261459489 -0400
@@ -26,7 +26,8 @@
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.DocsAndPositionsEnum;
-import org.apache.lucene.search.Similarity.SloppyDocScorer;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.Similarity.SloppyDocScorer;
 import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.TermContext;
@@ -164,8 +165,7 @@
 
     @Override
     public Scorer scorer(AtomicReaderContext context, ScorerContext scorerContext) throws IOException {
-      if (termArrays.size() == 0)                  // optimize zero-term case
-        return null;
+      assert !termArrays.isEmpty();
       final IndexReader reader = context.reader;
       final Bits liveDocs = reader.getLiveDocs();
       
@@ -249,7 +249,11 @@
 
   @Override
   public Query rewrite(IndexReader reader) {
-    if (termArrays.size() == 1) {                 // optimize one-term case
+    if (termArrays.isEmpty()) {
+      BooleanQuery bq = new BooleanQuery();
+      bq.setBoost(getBoost());
+      return bq;
+    } else if (termArrays.size() == 1) {                 // optimize one-term case
       Term[] terms = termArrays.get(0);
       BooleanQuery boq = new BooleanQuery(true);
       for (int i=0; i<terms.length; i++) {


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/payloads/PayloadNearQuery.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/payloads/PayloadNearQuery.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/payloads/PayloadNearQuery.java	2011-07-17 06:27:33.728948135 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/payloads/PayloadNearQuery.java	2011-08-23 08:43:39.721460295 -0400
@@ -22,10 +22,10 @@
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.Scorer;
 import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.Similarity;
-import org.apache.lucene.search.DefaultSimilarity; // javadocs only
 import org.apache.lucene.search.Weight;
-import org.apache.lucene.search.Similarity.SloppyDocScorer;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.Similarity.SloppyDocScorer;
 import org.apache.lucene.search.spans.NearSpansOrdered;
 import org.apache.lucene.search.spans.NearSpansUnordered;
 import org.apache.lucene.search.spans.SpanNearQuery;
@@ -52,7 +52,7 @@
  * <p/>
  * Payload scores are aggregated using a pluggable {@link PayloadFunction}.
  * 
- * @see org.apache.lucene.search.Similarity.SloppyDocScorer#computePayloadFactor(int, int, int, BytesRef)
+ * @see org.apache.lucene.search.similarities.Similarity.SloppyDocScorer#computePayloadFactor(int, int, int, BytesRef)
  */
 public class PayloadNearQuery extends SpanNearQuery {
   protected String fieldName;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java	2011-09-08 17:01:39.466036272 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java	2011-09-08 12:56:46.156030847 -0400
@@ -20,16 +20,16 @@
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.DocsAndPositionsEnum;
-import org.apache.lucene.search.DefaultSimilarity; // javadocs only
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Scorer;
 import org.apache.lucene.search.Weight;
-import org.apache.lucene.search.Similarity;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.ComplexExplanation;
-import org.apache.lucene.search.Similarity.SloppyDocScorer;
 import org.apache.lucene.search.Weight.ScorerContext;
 import org.apache.lucene.search.payloads.PayloadNearQuery.PayloadNearSpanScorer;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.Similarity.SloppyDocScorer;
 import org.apache.lucene.search.spans.TermSpans;
 import org.apache.lucene.search.spans.SpanTermQuery;
 import org.apache.lucene.search.spans.SpanWeight;
@@ -49,7 +49,7 @@
  * which returns 1 by default.
  * <p/>
  * Payload scores are aggregated using a pluggable {@link PayloadFunction}.
- * @see org.apache.lucene.search.Similarity.SloppyDocScorer#computePayloadFactor(int, int, int, BytesRef)
+ * @see org.apache.lucene.search.similarities.Similarity.SloppyDocScorer#computePayloadFactor(int, int, int, BytesRef)
  **/
 public class PayloadTermQuery extends SpanTermQuery {
   protected PayloadFunction function;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/PhraseQuery.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/PhraseQuery.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/PhraseQuery.java	2011-07-17 06:27:33.748948135 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/PhraseQuery.java	2011-08-30 00:41:19.101459489 -0400
@@ -29,7 +29,8 @@
 import org.apache.lucene.index.TermState;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
-import org.apache.lucene.search.Similarity.SloppyDocScorer;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.Similarity.SloppyDocScorer;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.TermContext;
 import org.apache.lucene.util.ToStringUtils;
@@ -119,7 +120,11 @@
 
   @Override
   public Query rewrite(IndexReader reader) throws IOException {
-    if (terms.size() == 1) {
+    if (terms.isEmpty()) {
+      BooleanQuery bq = new BooleanQuery();
+      bq.setBoost(getBoost());
+      return bq;
+    } else if (terms.size() == 1) {
       TermQuery tq = new TermQuery(terms.get(0));
       tq.setBoost(getBoost());
       return tq;
@@ -208,8 +213,7 @@
 
     @Override
     public Scorer scorer(AtomicReaderContext context, ScorerContext scorerContext) throws IOException {
-      if (terms.size() == 0)			  // optimize zero-term case
-        return null;
+      assert !terms.isEmpty();
       final IndexReader reader = context.reader;
       final Bits liveDocs = reader.getLiveDocs();
       PostingsAndFreq[] postingsFreqs = new PostingsAndFreq[terms.size()];
@@ -285,12 +289,6 @@
 
   @Override
   public Weight createWeight(IndexSearcher searcher) throws IOException {
-    if (terms.size() == 1) {			  // optimize one-term case
-      Term term = terms.get(0);
-      Query termQuery = new TermQuery(term);
-      termQuery.setBoost(getBoost());
-      return termQuery.createWeight(searcher);
-    }
     return new PhraseWeight(searcher);
   }
 


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/PhraseScorer.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/PhraseScorer.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/PhraseScorer.java	2011-07-08 01:31:28.411820268 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/PhraseScorer.java	2011-08-23 08:43:39.661460295 -0400
@@ -19,6 +19,8 @@
 
 import java.io.IOException;
 
+import org.apache.lucene.search.similarities.Similarity;
+
 /** Expert: Scoring functionality for phrase queries.
  * <br>A document is considered matching if it contains the phrase-query terms  
  * at "valid" positions. What "valid positions" are


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/AfterEffectB.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/AfterEffectB.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/AfterEffectB.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/AfterEffectB.java	2011-09-01 18:14:15.325814680 -0400
@@ -0,0 +1,49 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.Explanation;
+
+/**
+ * Model of the information gain based on the ratio of two Bernoulli processes.
+ * @lucene.experimental
+ */
+public class AfterEffectB extends AfterEffect {
+  @Override
+  public final float score(BasicStats stats, float tfn) {
+    long F = stats.getTotalTermFreq();
+    int n = stats.getDocFreq();
+    return (F + 1) / (n * (tfn + 1));
+  }
+  
+  @Override
+  public final Explanation explain(BasicStats stats, float tfn) {
+    Explanation result = new Explanation();
+    result.setDescription(getClass().getSimpleName() + ", computed from: ");
+    result.setValue(score(stats, tfn));
+    result.addDetail(new Explanation(tfn, "tfn"));
+    result.addDetail(new Explanation(stats.getTotalTermFreq(), "totalTermFreq"));
+    result.addDetail(new Explanation(stats.getDocFreq(), "docFreq"));
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "B";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/AfterEffect.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/AfterEffect.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/AfterEffect.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/AfterEffect.java	2011-08-23 09:16:32.701460292 -0400
@@ -0,0 +1,63 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.Explanation;
+
+/**
+ * This class acts as the base class for the implementations of the <em>first
+ * normalization of the informative content</em> in the DFR framework. This
+ * component is also called the <em>after effect</em> and is defined by the
+ * formula <em>Inf<sub>2</sub> = 1 - Prob<sub>2</sub></em>, where
+ * <em>Prob<sub>2</sub></em> measures the <em>information gain</em>.
+ * 
+ * @see DFRSimilarity
+ * @lucene.experimental
+ */
+public abstract class AfterEffect {
+  /** Returns the aftereffect score. */
+  public abstract float score(BasicStats stats, float tfn);
+  
+  /** Returns an explanation for the score. */
+  public abstract Explanation explain(BasicStats stats, float tfn);
+
+  /** Implementation used when there is no aftereffect. */
+  public static final class NoAfterEffect extends AfterEffect {
+    @Override
+    public final float score(BasicStats stats, float tfn) {
+      return 1f;
+    }
+
+    @Override
+    public final Explanation explain(BasicStats stats, float tfn) {
+      return new Explanation(1, "no aftereffect");
+    }
+    
+    @Override
+    public String toString() {
+      return "";
+    }
+  }
+  
+  /**
+   * Subclasses must override this method to return the code of the
+   * after effect formula. Refer to the original paper for the list. 
+   */
+  @Override
+  public abstract String toString();
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/AfterEffectL.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/AfterEffectL.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/AfterEffectL.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/AfterEffectL.java	2011-08-30 12:16:50.911459431 -0400
@@ -0,0 +1,45 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.Explanation;
+
+/**
+ * Model of the information gain based on Laplace's law of succession.
+ * @lucene.experimental
+ */
+public class AfterEffectL extends AfterEffect {
+  @Override
+  public final float score(BasicStats stats, float tfn) {
+    return 1 / (tfn + 1);
+  }
+  
+  @Override
+  public final Explanation explain(BasicStats stats, float tfn) {
+    Explanation result = new Explanation();
+    result.setDescription(getClass().getSimpleName() + ", computed from: ");
+    result.setValue(score(stats, tfn));
+    result.addDetail(new Explanation(tfn, "tfn"));
+    return result;
+  }
+  
+  @Override
+  public String toString() {
+    return "L";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicModelBE.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicModelBE.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicModelBE.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicModelBE.java	2011-09-07 01:05:14.205983206 -0400
@@ -0,0 +1,47 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import static org.apache.lucene.search.similarities.SimilarityBase.log2;
+
+/**
+ * Limiting form of the Bose-Einstein model. The formula used in Lucene differs
+ * slightly from the one in the original paper: {@code F} is increased by {@code tfn}
+ * and {@code N} is increased by {@code F} 
+ * @lucene.experimental
+ */
+public class BasicModelBE extends BasicModel {
+  @Override
+  public final float score(BasicStats stats, float tfn) {
+    double F = stats.getTotalTermFreq() + tfn;
+    // approximation only holds true when F << N, so we use N += F
+    double N = F + stats.getNumberOfDocuments();
+    return (float)(-log2((N - 1) * Math.E)
+        + f(N + F - 1, N + F - tfn - 2) - f(F, F - tfn));
+  }
+  
+  /** The <em>f</em> helper function defined for <em>B<sub>E</sub></em>. */
+  private final double f(double n, double m) {
+    return (m + 0.5) * log2(n / m) + (n - m) * log2(n);
+  }
+  
+  @Override
+  public String toString() {
+    return "Be";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicModelD.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicModelD.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicModelD.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicModelD.java	2011-09-07 00:10:59.365982005 -0400
@@ -0,0 +1,52 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import static org.apache.lucene.search.similarities.SimilarityBase.log2;
+
+/**
+ * Implements the approximation of the binomial model with the divergence
+ * for DFR. The formula used in Lucene differs slightly from the one in the
+ * original paper: to avoid underflow for small values of {@code N} and
+ * {@code F}, {@code N} is increased by {@code 1} and
+ * {@code F} is always increased by {@code tfn}.
+ * <p>
+ * WARNING: for terms that do not meet the expected random distribution
+ * (e.g. stopwords), this model may give poor performance, such as
+ * abnormally high scores for low tf values.
+ * @lucene.experimental
+ */
+public class BasicModelD extends BasicModel {
+  @Override
+  public final float score(BasicStats stats, float tfn) {
+    // we have to ensure phi is always < 1 for tiny TTF values, otherwise nphi can go negative,
+    // resulting in NaN. cleanest way is to unconditionally always add tfn to totalTermFreq
+    // to create a 'normalized' F.
+    double F = stats.getTotalTermFreq() + tfn;
+    double phi = (double)tfn / F;
+    double nphi = 1 - phi;
+    double p = 1.0 / (stats.getNumberOfDocuments() + 1);
+    double D = phi * log2(phi / p) + nphi * log2(nphi / (1 - p));
+    return (float)(D * F + 0.5 * log2(1 + 2 * Math.PI * tfn * nphi));
+  }
+  
+  @Override
+  public String toString() {
+    return "D";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicModelG.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicModelG.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicModelG.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicModelG.java	2011-09-07 00:13:13.635982055 -0400
@@ -0,0 +1,41 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import static org.apache.lucene.search.similarities.SimilarityBase.log2;
+
+/**
+ * Geometric as limiting form of the Bose-Einstein model.  The formula used in Lucene differs
+ * slightly from the one in the original paper: {@code F} is increased by {@code tfn}
+ * and {@code N} is increased by {@code F}.
+ * @lucene.experimental
+ */
+public class BasicModelG extends BasicModel {
+  @Override
+  public final float score(BasicStats stats, float tfn) {
+    // just like in BE, approximation only holds true when F << N, so we use lambda = F / (N + F)
+    double lambda = stats.getTotalTermFreq() / (double) (stats.getNumberOfDocuments() + stats.getTotalTermFreq());
+    // -log(1 / (lambda + 1)) -> log(lambda + 1)
+    return (float)(log2(lambda + 1) + tfn * log2((1 + lambda) / lambda));
+  }
+
+  @Override
+  public String toString() {
+    return "G";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicModelIF.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicModelIF.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicModelIF.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicModelIF.java	2011-08-23 09:16:32.701460292 -0400
@@ -0,0 +1,38 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import static org.apache.lucene.search.similarities.SimilarityBase.log2;
+
+/**
+ * An approximation of the <em>I(n<sub>e</sub>)</em> model.
+ * @lucene.experimental
+ */ 
+public class BasicModelIF extends BasicModel {
+  @Override
+  public final float score(BasicStats stats, float tfn) {
+    int N = stats.getNumberOfDocuments();
+    long F = stats.getTotalTermFreq();
+    return tfn * (float)(log2(1 + (N + 1) / (F + 0.5)));
+  }
+
+  @Override
+  public String toString() {
+    return "I(F)";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicModelIne.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicModelIne.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicModelIne.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicModelIne.java	2011-08-23 09:16:32.701460292 -0400
@@ -0,0 +1,40 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import static org.apache.lucene.search.similarities.SimilarityBase.log2;
+
+/**
+ * Tf-idf model of randomness, based on a mixture of Poisson and inverse
+ * document frequency.
+ * @lucene.experimental
+ */ 
+public class BasicModelIne extends BasicModel {
+  @Override
+  public final float score(BasicStats stats, float tfn) {
+    int N = stats.getNumberOfDocuments();
+    long F = stats.getTotalTermFreq();
+    double ne = N * (1 - Math.pow((N - 1) / (double)N, F));
+    return tfn * (float)(log2((N + 1) / (ne + 0.5)));
+  }
+
+  @Override
+  public String toString() {
+    return "I(ne)";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicModelIn.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicModelIn.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicModelIn.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicModelIn.java	2011-08-23 09:16:32.701460292 -0400
@@ -0,0 +1,52 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.Explanation;
+import static org.apache.lucene.search.similarities.SimilarityBase.log2;
+
+/**
+ * The basic tf-idf model of randomness.
+ * @lucene.experimental
+ */ 
+public class BasicModelIn extends BasicModel {
+  @Override
+  public final float score(BasicStats stats, float tfn) {
+    int N = stats.getNumberOfDocuments();
+    int n = stats.getDocFreq();
+    return tfn * (float)(log2((N + 1) / (n + 0.5)));
+  }
+  
+  @Override
+  public final Explanation explain(BasicStats stats, float tfn) {
+    Explanation result = new Explanation();
+    result.setDescription(getClass().getSimpleName() + ", computed from: ");
+    result.setValue(score(stats, tfn));
+    result.addDetail(new Explanation(tfn, "tfn"));
+    result.addDetail(
+        new Explanation(stats.getNumberOfDocuments(), "numberOfDocuments"));
+    result.addDetail(
+        new Explanation(stats.getDocFreq(), "docFreq"));
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "I(n)";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicModel.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicModel.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicModel.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicModel.java	2011-08-23 09:16:32.701460292 -0400
@@ -0,0 +1,60 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.Explanation;
+
+/**
+ * This class acts as the base class for the specific <em>basic model</em>
+ * implementations in the DFR framework. Basic models compute the
+ * <em>informative content Inf<sub>1</sub> = -log<sub>2</sub>Prob<sub>1</sub>
+ * </em>.
+ * 
+ * @see DFRSimilarity
+ * @lucene.experimental
+ */
+public abstract class BasicModel {
+  /** Returns the informative content score. */
+  public abstract float score(BasicStats stats, float tfn);
+  
+  /**
+   * Returns an explanation for the score.
+   * <p>Most basic models use the number of documents and the total term
+   * frequency to compute Inf<sub>1</sub>. This method provides a generic
+   * explanation for such models. Subclasses that use other statistics must
+   * override this method.</p>
+   */
+  public Explanation explain(BasicStats stats, float tfn) {
+    Explanation result = new Explanation();
+    result.setDescription(getClass().getSimpleName() + ", computed from: ");
+    result.setValue(score(stats, tfn));
+    result.addDetail(new Explanation(tfn, "tfn"));
+    result.addDetail(
+        new Explanation(stats.getNumberOfDocuments(), "numberOfDocuments"));
+    result.addDetail(
+        new Explanation(stats.getTotalTermFreq(), "totalTermFreq"));
+    return result;
+  }
+  
+  /**
+   * Subclasses must override this method to return the code of the
+   * basic model formula. Refer to the original paper for the list. 
+   */
+  @Override
+  public abstract String toString();
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicModelP.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicModelP.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicModelP.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicModelP.java	2011-09-07 00:10:39.015981997 -0400
@@ -0,0 +1,46 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import static org.apache.lucene.search.similarities.SimilarityBase.log2;
+
+/**
+ * Implements the Poisson approximation for the binomial model for DFR.
+ * @lucene.experimental
+ * <p>
+ * WARNING: for terms that do not meet the expected random distribution
+ * (e.g. stopwords), this model may give poor performance, such as
+ * abnormally high scores for low tf values.
+ */
+public class BasicModelP extends BasicModel {
+  /** {@code log2(Math.E)}, precomputed. */
+  protected static double LOG2_E = log2(Math.E);
+  
+  @Override
+  public final float score(BasicStats stats, float tfn) {
+    float lambda = (float)stats.getTotalTermFreq() / stats.getNumberOfDocuments();
+    return (float)(tfn * log2(tfn / lambda)
+        + (lambda + 1 / (12 * tfn) - tfn) * LOG2_E
+        + 0.5 * log2(2 * Math.PI * tfn));
+  }
+
+  @Override
+  public String toString() {
+    return "P";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicSimilarityProvider.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicSimilarityProvider.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicSimilarityProvider.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicSimilarityProvider.java	2011-08-30 09:11:26.321459446 -0400
@@ -0,0 +1,53 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+/**
+ * A simple {@link Similarity} provider that returns in
+ * {@code get(String field)} the object passed to its constructor. This class
+ * is aimed at non-VSM models, and therefore both the {@link #coord} and
+ * {@link #queryNorm} methods return {@code 1}. Use
+ * {@link DefaultSimilarityProvider} for {@link DefaultSimilarity}.
+ */
+public class BasicSimilarityProvider implements SimilarityProvider {
+  private final Similarity sim;
+  
+  public BasicSimilarityProvider(Similarity sim) {
+    this.sim = sim;
+  }
+  
+  @Override
+  public float coord(int overlap, int maxOverlap) {
+    return 1f;
+  }
+
+  @Override
+  public float queryNorm(float sumOfSquaredWeights) {
+    return 1f;
+  }
+
+  @Override
+  public Similarity get(String field) {
+    return sim;
+  }
+
+  @Override
+  public String toString() {
+    return "BasicSimilarityProvider(" + sim + ")";
+  }
+}
\ No newline at end of file


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicStats.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicStats.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BasicStats.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BasicStats.java	2011-08-23 09:16:32.711460292 -0400
@@ -0,0 +1,144 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.Terms;
+
+/**
+ * Stores all statistics commonly used ranking methods.
+ * @lucene.experimental
+ */
+public class BasicStats extends Similarity.Stats {
+  /** The number of documents. */
+  protected int numberOfDocuments;
+  /** The total number of tokens in the field. */
+  protected long numberOfFieldTokens;
+  /** The average field length. */
+  protected float avgFieldLength;
+  /** The document frequency. */
+  protected int docFreq;
+  /** The total number of occurrences of this term across all documents. */
+  protected long totalTermFreq;
+  
+  // -------------------------- Boost-related stuff --------------------------
+  
+  /** Query's inner boost. */
+  protected final float queryBoost;
+  /** Any outer query's boost. */
+  protected float topLevelBoost;
+  /** For most Similarities, the immediate and the top level query boosts are
+   * not handled differently. Hence, this field is just the product of the
+   * other two. */
+  protected float totalBoost;
+  
+  /** Constructor. Sets the query boost. */
+  public BasicStats(float queryBoost) {
+    this.queryBoost = queryBoost;
+    this.totalBoost = queryBoost;
+  }
+  
+  // ------------------------- Getter/setter methods -------------------------
+  
+  /** Returns the number of documents. */
+  public int getNumberOfDocuments() {
+    return numberOfDocuments;
+  }
+  
+  /** Sets the number of documents. */
+  public void setNumberOfDocuments(int numberOfDocuments) {
+    this.numberOfDocuments = numberOfDocuments;
+  }
+  
+  /**
+   * Returns the total number of tokens in the field.
+   * @see Terms#getSumTotalTermFreq()
+   */
+  public long getNumberOfFieldTokens() {
+    return numberOfFieldTokens;
+  }
+  
+  /**
+   * Sets the total number of tokens in the field.
+   * @see Terms#getSumTotalTermFreq()
+   */
+  public void setNumberOfFieldTokens(long numberOfFieldTokens) {
+    this.numberOfFieldTokens = numberOfFieldTokens;
+  }
+  
+  /** Returns the average field length. */
+  public float getAvgFieldLength() {
+    return avgFieldLength;
+  }
+  
+  /** Sets the average field length. */
+  public void setAvgFieldLength(float avgFieldLength) {
+    this.avgFieldLength = avgFieldLength;
+  }
+  
+  /** Returns the document frequency. */
+  public int getDocFreq() {
+    return docFreq;
+  }
+  
+  /** Sets the document frequency. */
+  public void setDocFreq(int docFreq) {
+    this.docFreq = docFreq;
+  }
+  
+  /** Returns the total number of occurrences of this term across all documents. */
+  public long getTotalTermFreq() {
+    return totalTermFreq;
+  }
+  
+  /** Sets the total number of occurrences of this term across all documents. */
+  public void setTotalTermFreq(long totalTermFreq) {
+    this.totalTermFreq = totalTermFreq;
+  }
+  
+  // -------------------------- Boost-related stuff --------------------------
+  
+  /** The square of the raw normalization value.
+   * @see #rawNormalizationValue() */
+  @Override
+  public float getValueForNormalization() {
+    float rawValue = rawNormalizationValue();
+    return rawValue * rawValue;
+  }
+  
+  /** Computes the raw normalization value. This basic implementation returns
+   * the query boost. Subclasses may override this method to include other
+   * factors (such as idf), or to save the value for inclusion in
+   * {@link #normalize(float, float)}, etc.
+   */
+  protected float rawNormalizationValue() {
+    return queryBoost;
+  }
+  
+  /** No normalization is done. {@code topLevelBoost} is saved in the object,
+   * however. */
+  @Override
+  public void normalize(float queryNorm, float topLevelBoost) {
+    this.topLevelBoost = topLevelBoost;
+    totalBoost = queryBoost * topLevelBoost;
+  }
+  
+  /** Returns the total boost. */
+  public float getTotalBoost() {
+    return totalBoost;
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BM25Similarity.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BM25Similarity.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/BM25Similarity.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/BM25Similarity.java	2011-09-09 11:38:26.186060999 -0400
@@ -0,0 +1,338 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+
+import org.apache.lucene.index.FieldInvertState;
+import org.apache.lucene.index.MultiFields;
+import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.index.Terms;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.SmallFloat;
+import org.apache.lucene.util.TermContext;
+
+/**
+ * BM25 Similarity. Introduced in Stephen E. Robertson, Steve Walker,
+ * Susan Jones, Micheline Hancock-Beaulieu, and Mike Gatford. Okapi at TREC-3.
+ * In Proceedings of the Third Text REtrieval Conference (TREC 1994).
+ * Gaithersburg, USA, November 1994.
+ */
+public class BM25Similarity extends Similarity {
+  private final float k1;
+  private final float b;
+  // TODO: should we add a delta like sifaka.cs.uiuc.edu/~ylv2/pub/sigir11-bm25l.pdf ?
+
+  public BM25Similarity(float k1, float b) {
+    this.k1 = k1;
+    this.b  = b;
+  }
+  
+  /** BM25 with these default values:
+   * <ul>
+   *   <li>{@code k1 = 1.2},
+   *   <li>{@code b = 0.75}.</li>
+   * </ul>
+   */
+  public BM25Similarity() {
+    this.k1 = 1.2f;
+    this.b  = 0.75f;
+  }
+  
+  /** Implemented as <code>log(1 + (numDocs - docFreq + 0.5)/(docFreq + 0.5))</code>. */
+  protected float idf(int docFreq, int numDocs) {
+    return (float) Math.log(1 + (numDocs - docFreq + 0.5D)/(docFreq + 0.5D));
+  }
+  
+  /** Implemented as <code>1 / (distance + 1)</code>. */
+  protected float sloppyFreq(int distance) {
+    return 1.0f / (distance + 1);
+  }
+  
+  /** The default implementation returns <code>1</code> */
+  protected float scorePayload(int doc, int start, int end, BytesRef payload) {
+    return 1;
+  }
+  
+  /** The default implementation computes the average as <code>sumTotalTermFreq / maxDoc</code>,
+   * or returns <code>1</code> if the index does not store sumTotalTermFreq (Lucene 3.x indexes
+   * or any field that omits frequency information). */
+  protected float avgFieldLength(IndexSearcher searcher, String field) throws IOException {
+    Terms terms = MultiFields.getTerms(searcher.getIndexReader(), field);
+    if (terms == null) {
+      // field does not exist;
+      return 1f;
+    }
+    long sumTotalTermFreq = terms.getSumTotalTermFreq();
+    long maxdoc = searcher.maxDoc();
+    return sumTotalTermFreq == -1 ? 1f : (float) (sumTotalTermFreq / (double) maxdoc);
+  }
+  
+  /** The default implementation encodes <code>boost / sqrt(length)</code>
+   * with {@link SmallFloat#floatToByte315(float)}.  This is compatible with 
+   * Lucene's default implementation.  If you change this, then you should 
+   * change {@link #decodeNormValue(byte)} to match. */
+  protected byte encodeNormValue(float boost, int fieldLength) {
+    return SmallFloat.floatToByte315(boost / (float) Math.sqrt(fieldLength));
+  }
+
+  /** The default implementation returns <code>1 / f<sup>2</sup></code>
+   * where <code>f</code> is {@link SmallFloat#byte315ToFloat(byte)}. */
+  protected float decodeNormValue(byte b) {
+    return NORM_TABLE[b & 0xFF];
+  }
+  
+  // Default true
+  protected boolean discountOverlaps = true;
+
+  /** Determines whether overlap tokens (Tokens with 0 position increment) are 
+   *  ignored when computing norm.  By default this is true, meaning overlap
+   *  tokens do not count when computing norms. */
+  public void setDiscountOverlaps(boolean v) {
+    discountOverlaps = v;
+  }
+
+  /** @see #setDiscountOverlaps */
+  public boolean getDiscountOverlaps() {
+    return discountOverlaps;
+  }
+  
+  /** Cache of decoded bytes. */
+  private static final float[] NORM_TABLE = new float[256];
+
+  static {
+    for (int i = 0; i < 256; i++) {
+      float f = SmallFloat.byte315ToFloat((byte)i);
+      NORM_TABLE[i] = 1.0f / (f*f);
+    }
+  }
+
+  @Override
+  public final byte computeNorm(FieldInvertState state) {
+    final int numTerms = discountOverlaps ? state.getLength() - state.getNumOverlap() : state.getLength();
+    return encodeNormValue(state.getBoost(), numTerms);
+  }
+
+  public Explanation idfExplain(TermContext stats, final IndexSearcher searcher) throws IOException {
+    final int df = stats.docFreq();
+    final int max = searcher.maxDoc();
+    final float idf = idf(df, max);
+    return new Explanation(idf, "idf(docFreq=" + df + ", maxDocs=" + max + ")");
+  }
+
+  public Explanation idfExplain(final TermContext stats[], IndexSearcher searcher) throws IOException {
+    final int max = searcher.maxDoc();
+    float idf = 0.0f;
+    final Explanation exp = new Explanation();
+    exp.setDescription("idf(), sum of:");
+    for (final TermContext stat : stats ) {
+      final int df = stat.docFreq();
+      final float termIdf = idf(df, max);
+      exp.addDetail(new Explanation(termIdf, "idf(docFreq=" + df + ", maxDocs=" + max + ")"));
+      idf += termIdf;
+    }
+    exp.setValue(idf);
+    return exp;
+  }
+
+  @Override
+  public final Stats computeStats(IndexSearcher searcher, String fieldName, float queryBoost, TermContext... termStats) throws IOException {
+    Explanation idf = termStats.length == 1 ? idfExplain(termStats[0], searcher) : idfExplain(termStats, searcher);
+
+    float avgdl = avgFieldLength(searcher, fieldName);
+
+    // compute freq-independent part of bm25 equation across all norm values
+    float cache[] = new float[256];
+    for (int i = 0; i < cache.length; i++) {
+      cache[i] = k1 * ((1 - b) + b * decodeNormValue((byte)i) / avgdl);
+    }
+    return new BM25Stats(idf, queryBoost, avgdl, cache);
+  }
+
+  @Override
+  public final ExactDocScorer exactDocScorer(Stats stats, String fieldName, AtomicReaderContext context) throws IOException {
+    final byte[] norms = context.reader.norms(fieldName);
+    return norms == null 
+      ? new ExactBM25DocScorerNoNorms((BM25Stats)stats)
+      : new ExactBM25DocScorer((BM25Stats)stats, norms);
+  }
+
+  @Override
+  public final SloppyDocScorer sloppyDocScorer(Stats stats, String fieldName, AtomicReaderContext context) throws IOException {
+    return new SloppyBM25DocScorer((BM25Stats) stats, context.reader.norms(fieldName));
+  }
+  
+  private class ExactBM25DocScorer extends ExactDocScorer {
+    private final BM25Stats stats;
+    private final float weightValue;
+    private final byte[] norms;
+    private final float[] cache;
+    
+    ExactBM25DocScorer(BM25Stats stats, byte norms[]) {
+      assert norms != null;
+      this.stats = stats;
+      this.weightValue = stats.weight * (k1 + 1); // boost * idf * (k1 + 1)
+      this.cache = stats.cache;
+      this.norms = norms;
+    }
+    
+    @Override
+    public float score(int doc, int freq) {
+      return weightValue * freq / (freq + cache[norms[doc] & 0xFF]);
+    }
+    
+    @Override
+    public Explanation explain(int doc, Explanation freq) {
+      return explainScore(doc, freq, stats, norms);
+    }
+  }
+  
+  /** there are no norms, we act as if b=0 */
+  private class ExactBM25DocScorerNoNorms extends ExactDocScorer {
+    private final BM25Stats stats;
+    private final float weightValue;
+    private static final int SCORE_CACHE_SIZE = 32;
+    private float[] scoreCache = new float[SCORE_CACHE_SIZE];
+
+    ExactBM25DocScorerNoNorms(BM25Stats stats) {
+      this.stats = stats;
+      this.weightValue = stats.weight * (k1 + 1); // boost * idf * (k1 + 1)
+      for (int i = 0; i < SCORE_CACHE_SIZE; i++)
+        scoreCache[i] = weightValue * i / (i + k1);
+    }
+    
+    @Override
+    public float score(int doc, int freq) {
+      // TODO: maybe score cache is more trouble than its worth?
+      return freq < SCORE_CACHE_SIZE        // check cache
+        ? scoreCache[freq]                  // cache hit
+        : weightValue * freq / (freq + k1); // cache miss
+    }
+    
+    @Override
+    public Explanation explain(int doc, Explanation freq) {
+      return explainScore(doc, freq, stats, null);
+    }
+  }
+  
+  private class SloppyBM25DocScorer extends SloppyDocScorer {
+    private final BM25Stats stats;
+    private final float weightValue; // boost * idf * (k1 + 1)
+    private final byte[] norms;
+    private final float[] cache;
+    
+    SloppyBM25DocScorer(BM25Stats stats, byte norms[]) {
+      this.stats = stats;
+      this.weightValue = stats.weight * (k1 + 1);
+      this.cache = stats.cache;
+      this.norms = norms;
+    }
+    
+    @Override
+    public float score(int doc, float freq) {
+      // if there are no norms, we act as if b=0
+      float norm = norms == null ? k1 : cache[norms[doc] & 0xFF];
+      return weightValue * freq / (freq + norm);
+    }
+    
+    @Override
+    public Explanation explain(int doc, Explanation freq) {
+      return explainScore(doc, freq, stats, norms);
+    }
+
+    @Override
+    public float computeSlopFactor(int distance) {
+      return sloppyFreq(distance);
+    }
+
+    @Override
+    public float computePayloadFactor(int doc, int start, int end, BytesRef payload) {
+      return scorePayload(doc, start, end, payload);
+    }
+  }
+  
+  /** Collection statistics for the BM25 model. */
+  private static class BM25Stats extends Stats {
+    /** BM25's idf */
+    private final Explanation idf;
+    /** The average document length. */
+    private final float avgdl;
+    /** query's inner boost */
+    private final float queryBoost;
+    /** weight (idf * boost) */
+    private float weight;
+    /** precomputed norm[256] with k1 * ((1 - b) + b * dl / avgdl) */
+    private final float cache[];
+
+    BM25Stats(Explanation idf, float queryBoost, float avgdl, float cache[]) {
+      this.idf = idf;
+      this.queryBoost = queryBoost;
+      this.avgdl = avgdl;
+      this.cache = cache;
+    }
+
+    @Override
+    public float getValueForNormalization() {
+      // we return a TF-IDF like normalization to be nice, but we don't actually normalize ourselves.
+      final float queryWeight = idf.getValue() * queryBoost;
+      return queryWeight * queryWeight;
+    }
+
+    @Override
+    public void normalize(float queryNorm, float topLevelBoost) {
+      // we don't normalize with queryNorm at all, we just capture the top-level boost
+      this.weight = idf.getValue() * queryBoost * topLevelBoost;
+    } 
+  }
+  
+  private Explanation explainScore(int doc, Explanation freq, BM25Stats stats, byte[] norms) {
+    Explanation result = new Explanation();
+    result.setDescription("score(doc="+doc+",freq="+freq+"), product of:");
+    
+    Explanation boostExpl = new Explanation(stats.queryBoost, "boost");
+    if (stats.queryBoost != 1.0f)
+      result.addDetail(boostExpl);
+    
+    result.addDetail(stats.idf);
+
+    Explanation tfNormExpl = new Explanation();
+    tfNormExpl.setDescription("tfNorm, computed from:");
+    tfNormExpl.addDetail(freq);
+    tfNormExpl.addDetail(new Explanation(k1, "parameter k1"));
+    if (norms == null) {
+      tfNormExpl.addDetail(new Explanation(0, "parameter b (norms omitted for field)"));
+      tfNormExpl.setValue((freq.getValue() * (k1 + 1)) / (freq.getValue() + k1));
+    } else {
+      float doclen = decodeNormValue(norms[doc]);
+      tfNormExpl.addDetail(new Explanation(b, "parameter b"));
+      tfNormExpl.addDetail(new Explanation(stats.avgdl, "avgFieldLength"));
+      tfNormExpl.addDetail(new Explanation(doclen, "fieldLength"));
+      tfNormExpl.setValue((freq.getValue() * (k1 + 1)) / (freq.getValue() + k1 * (1 - b + b * doclen/stats.avgdl)));
+    }
+    result.addDetail(tfNormExpl);
+    result.setValue(boostExpl.getValue() * stats.idf.getValue() * tfNormExpl.getValue());
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "BM25(k1=" + k1 + ",b=" + b + ")";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/DefaultSimilarity.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/DefaultSimilarity.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/DefaultSimilarity.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/DefaultSimilarity.java	2011-08-30 01:01:01.231459487 -0400
@@ -0,0 +1,93 @@
+package org.apache.lucene.search.similarities;
+
+import org.apache.lucene.index.FieldInvertState;
+import org.apache.lucene.util.BytesRef;
+
+/**
+ * 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.
+ */
+
+/** Expert: Default scoring implementation. */
+public class DefaultSimilarity extends TFIDFSimilarity {
+
+  /** Implemented as
+   *  <code>state.getBoost()*lengthNorm(numTerms)</code>, where
+   *  <code>numTerms</code> is {@link FieldInvertState#getLength()} if {@link
+   *  #setDiscountOverlaps} is false, else it's {@link
+   *  FieldInvertState#getLength()} - {@link
+   *  FieldInvertState#getNumOverlap()}.
+   *
+   *  @lucene.experimental */
+  @Override
+  public byte computeNorm(FieldInvertState state) {
+    final int numTerms;
+    if (discountOverlaps)
+      numTerms = state.getLength() - state.getNumOverlap();
+    else
+      numTerms = state.getLength();
+    return encodeNormValue(state.getBoost() * ((float) (1.0 / Math.sqrt(numTerms))));
+  }
+
+  /** Implemented as <code>sqrt(freq)</code>. */
+  @Override
+  public float tf(float freq) {
+    return (float)Math.sqrt(freq);
+  }
+    
+  /** Implemented as <code>1 / (distance + 1)</code>. */
+  @Override
+  public float sloppyFreq(int distance) {
+    return 1.0f / (distance + 1);
+  }
+  
+  /** The default implementation returns <code>1</code> */
+  @Override
+  public float scorePayload(int doc, int start, int end, BytesRef payload) {
+    return 1;
+  }
+
+  /** Implemented as <code>log(numDocs/(docFreq+1)) + 1</code>. */
+  @Override
+  public float idf(int docFreq, int numDocs) {
+    return (float)(Math.log(numDocs/(double)(docFreq+1)) + 1.0);
+  }
+    
+  // Default true
+  protected boolean discountOverlaps = true;
+
+  /** Determines whether overlap tokens (Tokens with
+   *  0 position increment) are ignored when computing
+   *  norm.  By default this is true, meaning overlap
+   *  tokens do not count when computing norms.
+   *
+   *  @lucene.experimental
+   *
+   *  @see #computeNorm
+   */
+  public void setDiscountOverlaps(boolean v) {
+    discountOverlaps = v;
+  }
+
+  /** @see #setDiscountOverlaps */
+  public boolean getDiscountOverlaps() {
+    return discountOverlaps;
+  }
+
+  @Override
+  public String toString() {
+    return "DefaultSimilarity";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/DefaultSimilarityProvider.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/DefaultSimilarityProvider.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/DefaultSimilarityProvider.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/DefaultSimilarityProvider.java	2011-08-23 08:43:39.731460295 -0400
@@ -0,0 +1,42 @@
+package org.apache.lucene.search.similarities;
+
+
+/**
+ * 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.
+ */
+
+/** 
+ * Expert: Default scoring provider. 
+ * <p>
+ * Returns {@link DefaultSimilarity} for every field
+ */
+public class DefaultSimilarityProvider implements SimilarityProvider {
+  private static final Similarity impl = new DefaultSimilarity();
+  
+  /** Implemented as <code>overlap / maxOverlap</code>. */
+  public float coord(int overlap, int maxOverlap) {
+    return overlap / (float)maxOverlap;
+  }
+
+  /** Implemented as <code>1/sqrt(sumOfSquaredWeights)</code>. */
+  public float queryNorm(float sumOfSquaredWeights) {
+    return (float)(1.0 / Math.sqrt(sumOfSquaredWeights));
+  }
+
+  public Similarity get(String field) {
+    return impl;
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/DFRSimilarity.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/DFRSimilarity.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/DFRSimilarity.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/DFRSimilarity.java	2011-09-01 14:52:10.165810203 -0400
@@ -0,0 +1,86 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.Explanation;
+
+/**
+ * Implements the <em>divergence from randomness (DFR)</em> framework
+ * introduced in Gianni Amati and Cornelis Joost Van Rijsbergen. 2002.
+ * Probabilistic models of information retrieval based on measuring the
+ * divergence from randomness. ACM Trans. Inf. Syst. 20, 4 (October 2002),
+ * 357-389.
+ * <p>The DFR scoring formula is composed of three separate components: the
+ * <em>basic model</em>, the <em>aftereffect</em> and an additional
+ * <em>normalization</em> component, represented by the classes
+ * {@code BasicModel}, {@code AfterEffect} and {@code Normalization},
+ * respectively. The names of these classes were chosen to match the names of
+ * their counterparts in the Terrier IR engine.</p>
+ * <p>Note that <em>qtf</em>, the multiplicity of term-occurrence in the query,
+ * is not handled by this implementation.</p>
+ * @see BasicModel
+ * @see AfterEffect
+ * @see Normalization
+ * @lucene.experimental
+ */
+public class DFRSimilarity extends SimilarityBase {
+  /** The basic model for information content. */
+  protected final BasicModel basicModel;
+  /** The first normalization of the information content. */
+  protected final AfterEffect afterEffect;
+  /** The term frequency normalization. */
+  protected final Normalization normalization;
+  
+  public DFRSimilarity(BasicModel basicModel,
+                       AfterEffect afterEffect,
+                       Normalization normalization) {
+    if (basicModel == null || afterEffect == null || normalization == null) {
+      throw new NullPointerException("null parameters not allowed.");
+    }
+    this.basicModel = basicModel;
+    this.afterEffect = afterEffect;
+    this.normalization = normalization;
+  }
+
+  @Override
+  protected float score(BasicStats stats, float freq, float docLen) {
+    float tfn = normalization.tfn(stats, freq, docLen);
+    return stats.getTotalBoost() *
+        basicModel.score(stats, tfn) * afterEffect.score(stats, tfn);
+  }
+  
+  @Override
+  protected void explain(Explanation expl,
+      BasicStats stats, int doc, float freq, float docLen) {
+    if (stats.getTotalBoost() != 1.0f) {
+      expl.addDetail(new Explanation(stats.getTotalBoost(), "boost"));
+    }
+    
+    Explanation normExpl = normalization.explain(stats, freq, docLen);
+    float tfn = normExpl.getValue();
+    expl.addDetail(normExpl);
+    expl.addDetail(basicModel.explain(stats, tfn));
+    expl.addDetail(afterEffect.explain(stats, tfn));
+  }
+
+  @Override
+  public String toString() {
+    return "DFR " + basicModel.toString() + afterEffect.toString()
+                  + normalization.toString();
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/Distribution.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/Distribution.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/Distribution.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/Distribution.java	2011-08-23 09:16:32.711460292 -0400
@@ -0,0 +1,45 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.Explanation;
+
+/**
+ * The probabilistic distribution used to model term occurrence
+ * in information-based models.
+ * @see IBSimilarity
+ * @lucene.experimental
+ */
+public abstract class Distribution {
+  /** Computes the score. */
+  public abstract float score(BasicStats stats, float tfn, float lambda);
+  
+  /** Explains the score. Returns the name of the model only, since
+   * both {@code tfn} and {@code lambda} are explained elsewhere. */
+  public Explanation explain(BasicStats stats, float tfn, float lambda) {
+    return new Explanation(
+        score(stats, tfn, lambda), getClass().getSimpleName());
+  }
+  
+  /**
+   * Subclasses must override this method to return the name of the
+   * distribution. 
+   */
+  @Override
+  public abstract String toString();
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/DistributionLL.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/DistributionLL.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/DistributionLL.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/DistributionLL.java	2011-08-23 09:16:32.711460292 -0400
@@ -0,0 +1,37 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+/**
+ * Log-logistic distribution.
+ * <p>Unlike for DFR, the natural logarithm is used, as
+ * it is faster to compute and the original paper does not express any
+ * preference to a specific base.</p>
+ * @lucene.experimental
+ */
+public class DistributionLL extends Distribution {
+  @Override
+  public final float score(BasicStats stats, float tfn, float lambda) {
+    return (float)-Math.log(lambda / (tfn + lambda));
+  }
+  
+  @Override
+  public String toString() {
+    return "LL";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/DistributionSPL.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/DistributionSPL.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/DistributionSPL.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/DistributionSPL.java	2011-08-23 09:16:32.711460292 -0400
@@ -0,0 +1,42 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+/**
+ * The smoothed power-law (SPL) distribution for the information-based framework
+ * that is described in the original paper.
+ * <p>Unlike for DFR, the natural logarithm is used, as
+ * it is faster to compute and the original paper does not express any
+ * preference to a specific base.</p>
+ * @lucene.experimental
+ */
+public class DistributionSPL extends Distribution {
+  @Override
+  public final float score(BasicStats stats, float tfn, float lambda) {
+    if (lambda == 1f) {
+      lambda = 0.99f;
+    }
+    return (float)-Math.log(
+        (Math.pow(lambda, (tfn / (tfn + 1))) - lambda) / (1 - lambda));
+  }
+  
+  @Override
+  public String toString() {
+    return "SPL";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/IBSimilarity.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/IBSimilarity.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/IBSimilarity.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/IBSimilarity.java	2011-08-30 10:20:35.671459440 -0400
@@ -0,0 +1,94 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.Explanation;
+
+/**
+ * Provides a framework for the family of information-based models, as described
+ * in St&eacute;phane Clinchant and Eric Gaussier. 2010. Information-based
+ * models for ad hoc IR. In Proceeding of the 33rd international ACM SIGIR
+ * conference on Research and development in information retrieval (SIGIR '10).
+ * ACM, New York, NY, USA, 234-241.
+ * <p>The retrieval function is of the form <em>RSV(q, d) = &sum;
+ * -x<sup>q</sup><sub>w</sub> log Prob(X<sub>w</sub> &ge;
+ * t<sup>d</sup><sub>w</sub> | &lambda;<sub>w</sub>)</em>, where
+ * <ul>
+ *   <li><em>x<sup>q</sup><sub>w</sub></em> is the query boost;</li>
+ *   <li><em>X<sub>w</sub></em> is a random variable that counts the occurrences
+ *   of word <em>w</em>;</li>
+ *   <li><em>t<sup>d</sup><sub>w</sub></em> is the normalized term frequency;</li>
+ *   <li><em>&lambda;<sub>w</sub></em> is a parameter.</li>
+ * </ul>
+ * </p>
+ * <p>The framework described in the paper has many similarities to the DFR
+ * framework (see {@link DFRSimilarity}). It is possible that the two
+ * Similarities will be merged at one point.</p>
+ * @lucene.experimental 
+ */
+public class IBSimilarity extends SimilarityBase {
+  /** The probabilistic distribution used to model term occurrence. */
+  protected final Distribution distribution;
+  /** The <em>lambda (&lambda;<sub>w</sub>)</em> parameter. */
+  protected final Lambda lambda;
+  /** The term frequency normalization. */
+  protected final Normalization normalization;
+  
+  public IBSimilarity(Distribution distribution,
+                      Lambda lambda,
+                      Normalization normalization) {
+    this.distribution = distribution;
+    this.lambda = lambda;
+    this.normalization = normalization;
+  }
+  
+  @Override
+  protected float score(BasicStats stats, float freq, float docLen) {
+    return stats.getTotalBoost() *
+        distribution.score(
+            stats,
+            normalization.tfn(stats, freq, docLen),
+            lambda.lambda(stats));
+  }
+
+  @Override
+  protected void explain(
+      Explanation expl, BasicStats stats, int doc, float freq, float docLen) {
+    if (stats.getTotalBoost() != 1.0f) {
+      expl.addDetail(new Explanation(stats.getTotalBoost(), "boost"));
+    }
+    Explanation normExpl = normalization.explain(stats, freq, docLen);
+    Explanation lambdaExpl = lambda.explain(stats);
+    expl.addDetail(normExpl);
+    expl.addDetail(lambdaExpl);
+    expl.addDetail(distribution.explain(
+        stats, normExpl.getValue(), lambdaExpl.getValue()));
+  }
+  
+  /**
+   * The name of IB methods follow the pattern
+   * {@code IB <distribution> <lambda><normalization>}. The name of the
+   * distribution is the same as in the original paper; for the names of lambda
+   * parameters, refer to the javadoc of the {@link Lambda} classes.
+   */
+  @Override
+  public String toString() {
+    return "IB " + distribution.toString() + "-" + lambda.toString()
+                 + normalization.toString();
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/LambdaDF.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/LambdaDF.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/LambdaDF.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/LambdaDF.java	2011-09-01 13:31:45.125808423 -0400
@@ -0,0 +1,48 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.Explanation;
+
+/**
+ * Computes lambda as {@code totalTermFreq / numberOfDocuments}.
+ * @lucene.experimental
+ */
+public class LambdaDF extends Lambda {
+  @Override
+  public final float lambda(BasicStats stats) {
+    return (float)stats.getDocFreq() / stats.getNumberOfDocuments();
+  }
+  
+  @Override
+  public final Explanation explain(BasicStats stats) {
+    Explanation result = new Explanation();
+    result.setDescription(getClass().getSimpleName() + ", computed from: ");
+    result.setValue(lambda(stats));
+    result.addDetail(
+        new Explanation(stats.getDocFreq(), "docFreq"));
+    result.addDetail(
+        new Explanation(stats.getNumberOfDocuments(), "numberOfDocuments"));
+    return result;
+  }
+  
+  @Override
+  public String toString() {
+    return "D";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/Lambda.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/Lambda.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/Lambda.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/Lambda.java	2011-08-23 09:16:32.741460292 -0400
@@ -0,0 +1,42 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.Explanation;
+
+/**
+ * The <em>lambda (&lambda;<sub>w</sub>)</em> parameter in information-based
+ * models.
+ * @see IBSimilarity
+ * @lucene.experimental
+ */
+public abstract class Lambda {
+  /** Computes the lambda parameter. */
+  public abstract float lambda(BasicStats stats);
+  /** Explains the lambda parameter. */
+  public abstract Explanation explain(BasicStats stats);
+  
+  /**
+   * Subclasses must override this method to return the code of the lambda
+   * formula. Since the original paper is not very clear on this matter, and
+   * also uses the DFR naming scheme incorrectly, the codes here were chosen
+   * arbitrarily.
+   */
+  @Override
+  public abstract String toString();
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/LambdaTTF.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/LambdaTTF.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/LambdaTTF.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/LambdaTTF.java	2011-09-01 13:30:56.285808405 -0400
@@ -0,0 +1,48 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.Explanation;
+
+/**
+ * Computes lambda as {@code docFreq / numberOfDocuments}.
+ * @lucene.experimental
+ */
+public class LambdaTTF extends Lambda {  
+  @Override
+  public final float lambda(BasicStats stats) {
+    return (float)stats.getTotalTermFreq() / stats.getNumberOfDocuments();
+  }
+
+  @Override
+  public final Explanation explain(BasicStats stats) {
+    Explanation result = new Explanation();
+    result.setDescription(getClass().getSimpleName() + ", computed from: ");
+    result.setValue(lambda(stats));
+    result.addDetail(
+        new Explanation(stats.getTotalTermFreq(), "totalTermFreq"));
+    result.addDetail(
+        new Explanation(stats.getNumberOfDocuments(), "numberOfDocuments"));
+    return result;
+  }
+  
+  @Override
+  public String toString() {
+    return "L";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/LMDirichletSimilarity.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/LMDirichletSimilarity.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/LMDirichletSimilarity.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/LMDirichletSimilarity.java	2011-08-23 09:16:32.741460292 -0400
@@ -0,0 +1,97 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.Explanation;
+
+/**
+ * Bayesian smoothing using Dirichlet priors. From Chengxiang Zhai and John
+ * Lafferty. 2001. A study of smoothing methods for language models applied to
+ * Ad Hoc information retrieval. In Proceedings of the 24th annual international
+ * ACM SIGIR conference on Research and development in information retrieval
+ * (SIGIR '01). ACM, New York, NY, USA, 334-342.
+ * <p>
+ * The formula as defined the paper assigns a negative score to documents that
+ * contain the term, but with fewer occurrences than predicted by the collection
+ * language model. The Lucene implementation returns {@code 0} for such
+ * documents.
+ * </p>
+ * 
+ * @lucene.experimental
+ */
+public class LMDirichletSimilarity extends LMSimilarity {
+  /** The &mu; parameter. */
+  private final float mu;
+  
+  /** @param mu the &mu; parameter. */
+  public LMDirichletSimilarity(CollectionModel collectionModel, float mu) {
+    super(collectionModel);
+    this.mu = mu;
+  }
+  
+  /** @param mu the &mu; parameter. */
+  public LMDirichletSimilarity(float mu) {
+    this.mu = mu;
+  }
+
+  /** Instantiates the similarity with the default &mu; value of 2000. */
+  public LMDirichletSimilarity(CollectionModel collectionModel) {
+    this(collectionModel, 2000);
+  }
+  
+  /** Instantiates the similarity with the default &mu; value of 2000. */
+  public LMDirichletSimilarity() {
+    this(2000);
+  }
+  
+  @Override
+  protected float score(BasicStats stats, float freq, float docLen) {
+    float score = stats.getTotalBoost() * (float)(Math.log(1 + freq /
+        (mu * ((LMStats)stats).getCollectionProbability())) +
+        Math.log(mu / (docLen + mu)));
+    return score > 0.0f ? score : 0.0f;
+  }
+  
+  @Override
+  protected void explain(Explanation expl, BasicStats stats, int doc,
+      float freq, float docLen) {
+    if (stats.getTotalBoost() != 1.0f) {
+      expl.addDetail(new Explanation(stats.getTotalBoost(), "boost"));
+    }
+
+    expl.addDetail(new Explanation(mu, "mu"));
+    Explanation weightExpl = new Explanation();
+    weightExpl.setValue((float)Math.log(1 + freq /
+        (mu * ((LMStats)stats).getCollectionProbability())));
+    weightExpl.setDescription("term weight");
+    expl.addDetail(weightExpl);
+    expl.addDetail(new Explanation(
+        (float)Math.log(mu / (docLen + mu)), "document norm"));
+    super.explain(expl, stats, doc, freq, docLen);
+  }
+
+  /** Returns the &mu; parameter. */
+  public float getMu() {
+    return mu;
+  }
+  
+  @Override
+  public String getName() {
+    return String.format("Dirichlet(%f)", getMu());
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/LMJelinekMercerSimilarity.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/LMJelinekMercerSimilarity.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/LMJelinekMercerSimilarity.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/LMJelinekMercerSimilarity.java	2011-08-23 09:16:32.741460292 -0400
@@ -0,0 +1,77 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.Explanation;
+
+/**
+ * Language model based on the Jelinek-Mercer smoothing method. From Chengxiang
+ * Zhai and John Lafferty. 2001. A study of smoothing methods for language
+ * models applied to Ad Hoc information retrieval. In Proceedings of the 24th
+ * annual international ACM SIGIR conference on Research and development in
+ * information retrieval (SIGIR '01). ACM, New York, NY, USA, 334-342.
+ * <p>The model has a single parameter, &lambda;. According to said paper, the
+ * optimal value depends on both the collection and the query. The optimal value
+ * is around {@code 0.1} for title queries and {@code 0.7} for long queries.</p>
+ *
+ * @lucene.experimental
+ */
+public class LMJelinekMercerSimilarity extends LMSimilarity {
+  /** The &lambda; parameter. */
+  private final float lambda;
+  
+  /** @param lambda the &lambda; parameter. */
+  public LMJelinekMercerSimilarity(
+      CollectionModel collectionModel, float lambda) {
+    super(collectionModel);
+    this.lambda = lambda;
+  }
+
+  /** @param lambda the &lambda; parameter. */
+  public LMJelinekMercerSimilarity(float lambda) {
+    this.lambda = lambda;
+  }
+  
+  @Override
+  protected float score(BasicStats stats, float freq, float docLen) {
+    return stats.getTotalBoost() *
+        (float)Math.log(1 +
+            ((1 - lambda) * freq / docLen) /
+            (lambda * ((LMStats)stats).getCollectionProbability()));
+  }
+  
+  @Override
+  protected void explain(Explanation expl, BasicStats stats, int doc,
+      float freq, float docLen) {
+    if (stats.getTotalBoost() != 1.0f) {
+      expl.addDetail(new Explanation(stats.getTotalBoost(), "boost"));
+    }
+    expl.addDetail(new Explanation(lambda, "lambda"));
+    super.explain(expl, stats, doc, freq, docLen);
+  }
+
+  /** Returns the &lambda; parameter. */
+  public float getLambda() {
+    return lambda;
+  }
+
+  @Override
+  public String getName() {
+    return String.format("Jelinek-Mercer(%f)", getLambda());
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/LMSimilarity.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/LMSimilarity.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/LMSimilarity.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/LMSimilarity.java	2011-09-07 00:50:54.785982890 -0400
@@ -0,0 +1,155 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.util.TermContext;
+
+/**
+ * Abstract superclass for language modeling Similarities. The following inner
+ * types are introduced:
+ * <ul>
+ *   <li>{@link LMStats}, which defines a new statistic, the probability that
+ *   the collection language model generates the current term;</li>
+ *   <li>{@link CollectionModel}, which is a strategy interface for object that
+ *   compute the collection language model {@code p(w|C)};</li>
+ *   <li>{@link DefaultCollectionModel}, an implementation of the former, that
+ *   computes the term probability as the number of occurrences of the term in the
+ *   collection, divided by the total number of tokens.</li>
+ * </ul> 
+ * 
+ * @lucene.experimental
+ */
+public abstract class LMSimilarity extends SimilarityBase {
+  /** The collection model. */
+  protected final CollectionModel collectionModel;
+  
+  /** Creates a new instance with the specified collection language model. */
+  public LMSimilarity(CollectionModel collectionModel) {
+    this.collectionModel = collectionModel;
+  }
+  
+  /** Creates a new instance with the default collection language model. */
+  public LMSimilarity() {
+    this(new DefaultCollectionModel());
+  }
+  
+  @Override
+  protected BasicStats newStats(float queryBoost) {
+    return new LMStats(queryBoost);
+  }
+
+  /**
+   * Computes the collection probability of the current term in addition to the
+   * usual statistics.
+   */
+  @Override
+  protected void fillBasicStats(BasicStats stats, IndexSearcher searcher, String fieldName, TermContext termContext) throws IOException {
+    super.fillBasicStats(stats, searcher, fieldName, termContext);
+    LMStats lmStats = (LMStats) stats;
+    lmStats.setCollectionProbability(collectionModel.computeProbability(stats));
+  }
+
+  @Override
+  protected void explain(Explanation expl, BasicStats stats, int doc,
+      float freq, float docLen) {
+    expl.addDetail(new Explanation(collectionModel.computeProbability(stats),
+                                   "collection probability"));
+  }
+  
+  /**
+   * Returns the name of the LM method. The values of the parameters should be
+   * included as well.
+   * <p>Used in {@link #toString()}</p>.
+   */
+  public abstract String getName();
+  
+  /**
+   * Returns the name of the LM method. If a custom collection model strategy is
+   * used, its name is included as well.
+   * @see #getName()
+   * @see CollectionModel#getName()
+   * @see DefaultCollectionModel 
+   */
+  @Override
+  public String toString() {
+    String coll = collectionModel.getName();
+    if (coll != null) {
+      return String.format("LM %s - %s", getName(), coll);
+    } else {
+      return String.format("LM %s", getName());
+    }
+  }
+
+  /** Stores the collection distribution of the current term. */
+  public static class LMStats extends BasicStats {
+    /** The probability that the current term is generated by the collection. */
+    private float collectionProbability;
+    
+    public LMStats(float queryBoost) {
+      super(queryBoost);
+    }
+    
+    /**
+     * Returns the probability that the current term is generated by the
+     * collection.
+     */
+    public final float getCollectionProbability() {
+      return collectionProbability;
+    }
+    
+    /**
+     * Sets the probability that the current term is generated by the
+     * collection.
+     */
+    public final void setCollectionProbability(float collectionProbability) {
+      this.collectionProbability = collectionProbability;
+    } 
+  }
+  
+  /** A strategy for computing the collection language model. */
+  public static interface CollectionModel {
+    /**
+     * Computes the probability {@code p(w|C)} according to the language model
+     * strategy for the current term.
+     */
+    public float computeProbability(BasicStats stats);
+    
+    /** The name of the collection model strategy. */
+    public String getName();
+  }
+  
+  /**
+   * Models {@code p(w|C)} as the number of occurrences of the term in the
+   * collection, divided by the total number of tokens {@code + 1}.
+   */
+  public static class DefaultCollectionModel implements CollectionModel {
+    @Override
+    public float computeProbability(BasicStats stats) {
+      return (float)stats.getTotalTermFreq() / (stats.getNumberOfFieldTokens() +1);
+    }
+    
+    @Override
+    public String getName() {
+      return null;
+    }
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/MultiSimilarity.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/MultiSimilarity.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/MultiSimilarity.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/MultiSimilarity.java	2011-09-07 00:42:53.735982712 -0400
@@ -0,0 +1,159 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+
+import org.apache.lucene.index.FieldInvertState;
+import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.TermContext;
+
+/**
+ * Implements the CombSUM method for combining evidence from multiple
+ * similarity values described in: Joseph A. Shaw, Edward A. Fox. 
+ * In Text REtrieval Conference (1993), pp. 243-252
+ * @lucene.experimental
+ */
+public class MultiSimilarity extends Similarity {
+  protected final Similarity sims[];
+  
+  public MultiSimilarity(Similarity sims[]) {
+    this.sims = sims;
+  }
+  
+  @Override
+  public byte computeNorm(FieldInvertState state) {
+    return sims[0].computeNorm(state);
+  }
+
+  @Override
+  public Stats computeStats(IndexSearcher searcher, String fieldName, float queryBoost, TermContext... termContexts) throws IOException {
+    Stats subStats[] = new Stats[sims.length];
+    for (int i = 0; i < subStats.length; i++) {
+      subStats[i] = sims[i].computeStats(searcher, fieldName, queryBoost, termContexts);
+    }
+    return new MultiStats(subStats);
+  }
+
+  @Override
+  public ExactDocScorer exactDocScorer(Stats stats, String fieldName, AtomicReaderContext context) throws IOException {
+    ExactDocScorer subScorers[] = new ExactDocScorer[sims.length];
+    for (int i = 0; i < subScorers.length; i++) {
+      subScorers[i] = sims[i].exactDocScorer(((MultiStats)stats).subStats[i], fieldName, context);
+    }
+    return new MultiExactDocScorer(subScorers);
+  }
+
+  @Override
+  public SloppyDocScorer sloppyDocScorer(Stats stats, String fieldName, AtomicReaderContext context) throws IOException {
+    SloppyDocScorer subScorers[] = new SloppyDocScorer[sims.length];
+    for (int i = 0; i < subScorers.length; i++) {
+      subScorers[i] = sims[i].sloppyDocScorer(((MultiStats)stats).subStats[i], fieldName, context);
+    }
+    return new MultiSloppyDocScorer(subScorers);
+  }
+  
+  public static class MultiExactDocScorer extends ExactDocScorer {
+    private final ExactDocScorer subScorers[];
+    
+    MultiExactDocScorer(ExactDocScorer subScorers[]) {
+      this.subScorers = subScorers;
+    }
+    
+    @Override
+    public float score(int doc, int freq) {
+      float sum = 0.0f;
+      for (ExactDocScorer subScorer : subScorers) {
+        sum += subScorer.score(doc, freq);
+      }
+      return sum;
+    }
+
+    @Override
+    public Explanation explain(int doc, Explanation freq) {
+      Explanation expl = new Explanation(score(doc, (int)freq.getValue()), "sum of:");
+      for (ExactDocScorer subScorer : subScorers) {
+        expl.addDetail(subScorer.explain(doc, freq));
+      }
+      return expl;
+    }
+  }
+  
+  public static class MultiSloppyDocScorer extends SloppyDocScorer {
+    private final SloppyDocScorer subScorers[];
+    
+    MultiSloppyDocScorer(SloppyDocScorer subScorers[]) {
+      this.subScorers = subScorers;
+    }
+    
+    @Override
+    public float score(int doc, float freq) {
+      float sum = 0.0f;
+      for (SloppyDocScorer subScorer : subScorers) {
+        sum += subScorer.score(doc, freq);
+      }
+      return sum;
+    }
+
+    @Override
+    public Explanation explain(int doc, Explanation freq) {
+      Explanation expl = new Explanation(score(doc, freq.getValue()), "sum of:");
+      for (SloppyDocScorer subScorer : subScorers) {
+        expl.addDetail(subScorer.explain(doc, freq));
+      }
+      return expl;
+    }
+
+    @Override
+    public float computeSlopFactor(int distance) {
+      return subScorers[0].computeSlopFactor(distance);
+    }
+
+    @Override
+    public float computePayloadFactor(int doc, int start, int end, BytesRef payload) {
+      return subScorers[0].computePayloadFactor(doc, start, end, payload);
+    }
+  }
+
+  public static class MultiStats extends Stats {
+    final Stats subStats[];
+    
+    MultiStats(Stats subStats[]) {
+      this.subStats = subStats;
+    }
+    
+    @Override
+    public float getValueForNormalization() {
+      float sum = 0.0f;
+      for (Stats stat : subStats) {
+        sum += stat.getValueForNormalization();
+      }
+      return sum / subStats.length;
+    }
+
+    @Override
+    public void normalize(float queryNorm, float topLevelBoost) {
+      for (Stats stat : subStats) {
+        stat.normalize(queryNorm, topLevelBoost);
+      }
+    }
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/NormalizationH1.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/NormalizationH1.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/NormalizationH1.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/NormalizationH1.java	2011-08-30 11:57:25.601459432 -0400
@@ -0,0 +1,33 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+/**
+ * Normalization model that assumes a uniform distribution of the term frequency.
+ */
+public class NormalizationH1 extends Normalization {
+  @Override
+  public final float tfn(BasicStats stats, float tf, float len) {
+    return tf * stats.getAvgFieldLength() / len;
+  }
+
+  @Override
+  public String toString() {
+    return "1";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/NormalizationH2.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/NormalizationH2.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/NormalizationH2.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/NormalizationH2.java	2011-08-23 09:16:32.741460292 -0400
@@ -0,0 +1,36 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import static org.apache.lucene.search.similarities.SimilarityBase.log2;
+
+/**
+ * Normalization model in which the term frequency is inversely related to the
+ * length.
+ */
+public class NormalizationH2 extends Normalization {
+  @Override
+  public final float tfn(BasicStats stats, float tf, float len) {
+    return (float)(tf * log2(1 + stats.getAvgFieldLength() / len));
+  }
+
+  @Override
+  public String toString() {
+    return "2";
+  }
+}
\ No newline at end of file


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/NormalizationH3.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/NormalizationH3.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/NormalizationH3.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/NormalizationH3.java	2011-09-07 01:06:06.755983226 -0400
@@ -0,0 +1,43 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+/**
+ * Dirichlet Priors normalization
+ */
+public class NormalizationH3 extends Normalization {
+  private final float mu;
+  
+  public NormalizationH3() {
+    this(800F);
+  }
+  
+  public NormalizationH3(float mu) {
+    this.mu = mu;
+  }
+
+  @Override
+  public float tfn(BasicStats stats, float tf, float len) {
+    return (tf + mu * (stats.getTotalTermFreq() / (float)stats.getNumberOfFieldTokens())) / (len + mu) * mu;
+  }
+
+  @Override
+  public String toString() {
+    return "3(" + mu + ")";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/Normalization.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/Normalization.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/Normalization.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/Normalization.java	2011-08-23 09:16:32.741460292 -0400
@@ -0,0 +1,75 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.Explanation;
+
+/**
+ * This class acts as the base class for the implementations of the term
+ * frequency normalization methods in the DFR framework.
+ * 
+ * @see DFRSimilarity
+ * @lucene.experimental
+ */
+public abstract class Normalization {
+  /** Returns the normalized term frequency.
+   * @param len the field length. */
+  public abstract float tfn(BasicStats stats, float tf, float len);
+  
+  /** Returns an explanation for the normalized term frequency.
+   * <p>The default normalization methods use the field length of the document
+   * and the average field length to compute the normalized term frequency.
+   * This method provides a generic explanation for such methods.
+   * Subclasses that use other statistics must override this method.</p>
+   */
+  public Explanation explain(BasicStats stats, float tf, float len) {
+    Explanation result = new Explanation();
+    result.setDescription(getClass().getSimpleName() + ", computed from: ");
+    result.setValue(tfn(stats, tf, len));
+    result.addDetail(new Explanation(tf, "tf"));
+    result.addDetail(
+        new Explanation(stats.getAvgFieldLength(), "avgFieldLength"));
+    result.addDetail(new Explanation(len, "len"));
+    return result;
+  }
+
+  /** Implementation used when there is no normalization. */
+  public static final class NoNormalization extends Normalization {
+    @Override
+    public final float tfn(BasicStats stats, float tf, float len) {
+      return tf;
+    }
+
+    @Override
+    public final Explanation explain(BasicStats stats, float tf, float len) {
+      return new Explanation(1, "no normalization");
+    }
+    
+    @Override
+    public String toString() {
+      return "";
+    }
+  }
+  
+  /**
+   * Subclasses must override this method to return the code of the
+   * normalization formula. Refer to the original paper for the list. 
+   */
+  @Override
+  public abstract String toString();
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/NormalizationZ.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/NormalizationZ.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/NormalizationZ.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/NormalizationZ.java	2011-09-06 15:40:57.955970712 -0400
@@ -0,0 +1,43 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+/**
+ * Pareto-Zipf Normalization
+ */
+public class NormalizationZ extends Normalization {
+  final float z;
+
+  public NormalizationZ() {
+    this(0.30F);
+  }
+
+  public NormalizationZ(float z) {
+    this.z = z;
+  }
+  
+  @Override
+  public float tfn(BasicStats stats, float tf, float len) {
+    return (float)(tf * Math.pow(stats.avgFieldLength / len, z));
+  }
+
+  @Override
+  public String toString() {
+    return "Z(" + z + ")";
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/SimilarityBase.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/SimilarityBase.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/SimilarityBase.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/SimilarityBase.java	2011-09-09 12:08:45.116061670 -0400
@@ -0,0 +1,345 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+
+import org.apache.lucene.index.FieldInvertState;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.index.MultiFields;
+import org.apache.lucene.index.Terms;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.SmallFloat;
+import org.apache.lucene.util.TermContext;
+
+/**
+ * A subclass of {@code Similarity} that provides a simplified API for its
+ * descendants. Subclasses are only required to implement the {@link #score}
+ * and {@link #toString()} methods. Implementing
+ * {@link #explain(Explanation, BasicStats, int, float, float)} is optional,
+ * inasmuch as SimilarityBase already provides a basic explanation of the score
+ * and the term frequency. However, implementers of a subclass are encouraged to
+ * include as much detail about the scoring method as possible.
+ * <p>
+ * Note: multi-word queries such as phrase queries are scored in a different way
+ * than Lucene's default ranking algorithm: whereas it "fakes" an IDF value for
+ * the phrase as a whole (since it does not know it), this class instead scores
+ * phrases as a summation of the individual term scores.
+ * @lucene.experimental
+ */
+public abstract class SimilarityBase extends Similarity {
+  /** For {@link #log2(double)}. Precomputed for efficiency reasons. */
+  private static final double LOG_2 = Math.log(2);
+  
+  /** @see #setDiscountOverlaps */
+  protected boolean discountOverlaps = true;
+  
+  /** Determines whether overlap tokens (Tokens with
+   *  0 position increment) are ignored when computing
+   *  norm.  By default this is true, meaning overlap
+   *  tokens do not count when computing norms.
+   *
+   *  @lucene.experimental
+   *
+   *  @see #computeNorm
+   */
+  public void setDiscountOverlaps(boolean v) {
+    discountOverlaps = v;
+  }
+
+  /** @see #setDiscountOverlaps */
+  public boolean getDiscountOverlaps() {
+    return discountOverlaps;
+  }
+  
+  @Override
+  public final Stats computeStats(IndexSearcher searcher, String fieldName,
+      float queryBoost, TermContext... termContexts) throws IOException {
+    BasicStats stats[] = new BasicStats[termContexts.length];
+    for (int i = 0; i < termContexts.length; i++) {
+      stats[i] = newStats(queryBoost);
+      fillBasicStats(stats[i], searcher, fieldName, termContexts[i]);
+    }
+    return stats.length == 1 ? stats[0] : new MultiSimilarity.MultiStats(stats);
+  }
+  
+  /** Factory method to return a custom stats object */
+  protected BasicStats newStats(float queryBoost) {
+    return new BasicStats(queryBoost);
+  }
+  
+  /** Fills all member fields defined in {@code BasicStats} in {@code stats}. 
+   *  Subclasses can override this method to fill additional stats. */
+  protected void fillBasicStats(BasicStats stats, IndexSearcher searcher,
+      String fieldName, TermContext termContext) throws IOException {
+    IndexReader reader = searcher.getIndexReader();
+    int numberOfDocuments = reader.maxDoc();
+    
+    int docFreq = termContext.docFreq();
+    long totalTermFreq = termContext.totalTermFreq();
+
+    // codec does not supply totalTermFreq: substitute docFreq
+    if (totalTermFreq == -1) {
+      totalTermFreq = docFreq;
+    }
+
+    final long numberOfFieldTokens;
+    final float avgFieldLength;
+    
+    Terms terms = MultiFields.getTerms(searcher.getIndexReader(), fieldName);
+    if (terms == null) {
+      // field does not exist;
+      numberOfFieldTokens = 0;
+      avgFieldLength = 1;
+    } else {
+      long sumTotalTermFreq = terms.getSumTotalTermFreq();
+
+      // We have to provide something if codec doesnt supply these measures,
+      // or if someone omitted frequencies for the field... negative values cause
+      // NaN/Inf for some scorers.
+      if (sumTotalTermFreq == -1) {
+        numberOfFieldTokens = docFreq;
+        avgFieldLength = 1;
+      } else {
+        numberOfFieldTokens = sumTotalTermFreq;
+        avgFieldLength = (float)numberOfFieldTokens / numberOfDocuments;
+      }
+    }
+ 
+    // TODO: add sumDocFreq for field (numberOfFieldPostings)
+    stats.setNumberOfDocuments(numberOfDocuments);
+    stats.setNumberOfFieldTokens(numberOfFieldTokens);
+    stats.setAvgFieldLength(avgFieldLength);
+    stats.setDocFreq(docFreq);
+    stats.setTotalTermFreq(totalTermFreq);
+  }
+  
+  /**
+   * Scores the document {@code doc}.
+   * <p>Subclasses must apply their scoring formula in this class.</p>
+   * @param stats the corpus level statistics.
+   * @param freq the term frequency.
+   * @param docLen the document length.
+   * @return the score.
+   */
+  protected abstract float score(BasicStats stats, float freq, float docLen);
+  
+  /**
+   * Subclasses should implement this method to explain the score. {@code expl}
+   * already contains the score, the name of the class and the doc id, as well
+   * as the term frequency and its explanation; subclasses can add additional
+   * clauses to explain details of their scoring formulae.
+   * <p>The default implementation does nothing.</p>
+   * 
+   * @param expl the explanation to extend with details.
+   * @param stats the corpus level statistics.
+   * @param doc the document id.
+   * @param freq the term frequency.
+   * @param docLen the document length.
+   */
+  protected void explain(
+      Explanation expl, BasicStats stats, int doc, float freq, float docLen) {}
+  
+  /**
+   * Explains the score. The implementation here provides a basic explanation
+   * in the format <em>score(name-of-similarity, doc=doc-id,
+   * freq=term-frequency), computed from:</em>, and
+   * attaches the score (computed via the {@link #score(BasicStats, float, float)}
+   * method) and the explanation for the term frequency. Subclasses content with
+   * this format may add additional details in
+   * {@link #explain(Explanation, BasicStats, int, float, float)}.
+   *  
+   * @param stats the corpus level statistics.
+   * @param doc the document id.
+   * @param freq the term frequency and its explanation.
+   * @param docLen the document length.
+   * @return the explanation.
+   */
+  protected Explanation explain(
+      BasicStats stats, int doc, Explanation freq, float docLen) {
+    Explanation result = new Explanation(); 
+    result.setValue(score(stats, freq.getValue(), docLen));
+    result.setDescription("score(" + getClass().getSimpleName() +
+        ", doc=" + doc + ", freq=" + freq.getValue() +"), computed from:");
+    result.addDetail(freq);
+    
+    explain(result, stats, doc, freq.getValue(), docLen);
+    
+    return result;
+  }
+  
+  @Override
+  public ExactDocScorer exactDocScorer(Stats stats, String fieldName,
+      AtomicReaderContext context) throws IOException {
+    byte norms[] = context.reader.norms(fieldName);
+    
+    if (stats instanceof MultiSimilarity.MultiStats) {
+      // a multi term query (e.g. phrase). return the summation, 
+      // scoring almost as if it were boolean query
+      Stats subStats[] = ((MultiSimilarity.MultiStats) stats).subStats;
+      ExactDocScorer subScorers[] = new ExactDocScorer[subStats.length];
+      for (int i = 0; i < subScorers.length; i++) {
+        subScorers[i] = new BasicExactDocScorer((BasicStats)subStats[i], norms);
+      }
+      return new MultiSimilarity.MultiExactDocScorer(subScorers);
+    } else {
+      return new BasicExactDocScorer((BasicStats) stats, norms);
+    }
+  }
+  
+  @Override
+  public SloppyDocScorer sloppyDocScorer(Stats stats, String fieldName,
+      AtomicReaderContext context) throws IOException {
+    byte norms[] = context.reader.norms(fieldName);
+    
+    if (stats instanceof MultiSimilarity.MultiStats) {
+      // a multi term query (e.g. phrase). return the summation, 
+      // scoring almost as if it were boolean query
+      Stats subStats[] = ((MultiSimilarity.MultiStats) stats).subStats;
+      SloppyDocScorer subScorers[] = new SloppyDocScorer[subStats.length];
+      for (int i = 0; i < subScorers.length; i++) {
+        subScorers[i] = new BasicSloppyDocScorer((BasicStats)subStats[i], norms);
+      }
+      return new MultiSimilarity.MultiSloppyDocScorer(subScorers);
+    } else {
+      return new BasicSloppyDocScorer((BasicStats) stats, norms);
+    }
+  }
+  
+  /**
+   * Subclasses must override this method to return the name of the Similarity
+   * and preferably the values of parameters (if any) as well.
+   */
+  @Override
+  public abstract String toString();
+
+  // ------------------------------ Norm handling ------------------------------
+  
+  /** Norm -> document length map. */
+  private static final float[] NORM_TABLE = new float[256];
+
+  static {
+    for (int i = 0; i < 256; i++) {
+      float floatNorm = SmallFloat.byte315ToFloat((byte)i);
+      NORM_TABLE[i] = 1.0f / (floatNorm * floatNorm);
+    }
+  }
+
+  /** Encodes the document length in the same way as {@link TFIDFSimilarity}. */
+  @Override
+  public byte computeNorm(FieldInvertState state) {
+    final float numTerms;
+    if (discountOverlaps)
+      numTerms = state.getLength() - state.getNumOverlap();
+    else
+      numTerms = state.getLength() / state.getBoost();
+    return encodeNormValue(state.getBoost(), numTerms);
+  }
+  
+  /** Decodes a normalization factor (document length) stored in an index.
+   * @see #encodeNormValue(float,float)
+   */
+  protected float decodeNormValue(byte norm) {
+    return NORM_TABLE[norm & 0xFF];  // & 0xFF maps negative bytes to positive above 127
+  }
+  
+  /** Encodes the length to a byte via SmallFloat. */
+  protected byte encodeNormValue(float boost, float length) {
+    return SmallFloat.floatToByte315((boost / (float) Math.sqrt(length)));
+  }
+  
+  // ----------------------------- Static methods ------------------------------
+  
+  /** Returns the base two logarithm of {@code x}. */
+  public static double log2(double x) {
+    // Put this to a 'util' class if we need more of these.
+    return Math.log(x) / LOG_2;
+  }
+  
+  // --------------------------------- Classes ---------------------------------
+  
+  /** Delegates the {@link #score(int, int)} and
+   * {@link #explain(int, Explanation)} methods to
+   * {@link SimilarityBase#score(BasicStats, float, int)} and
+   * {@link SimilarityBase#explain(BasicStats, int, Explanation, int)},
+   * respectively.
+   */
+  private class BasicExactDocScorer extends ExactDocScorer {
+    private final BasicStats stats;
+    private final byte[] norms;
+    
+    BasicExactDocScorer(BasicStats stats, byte norms[]) {
+      this.stats = stats;
+      this.norms = norms;
+    }
+    
+    @Override
+    public float score(int doc, int freq) {
+      // We have to supply something in case norms are omitted
+      return SimilarityBase.this.score(stats, freq,
+          norms == null ? 1F : decodeNormValue(norms[doc]));
+    }
+    
+    @Override
+    public Explanation explain(int doc, Explanation freq) {
+      return SimilarityBase.this.explain(stats, doc, freq,
+          norms == null ? 1F : decodeNormValue(norms[doc]));
+    }
+  }
+  
+  /** Delegates the {@link #score(int, int)} and
+   * {@link #explain(int, Explanation)} methods to
+   * {@link SimilarityBase#score(BasicStats, float, int)} and
+   * {@link SimilarityBase#explain(BasicStats, int, Explanation, int)},
+   * respectively.
+   */
+  private class BasicSloppyDocScorer extends SloppyDocScorer {
+    private final BasicStats stats;
+    private final byte[] norms;
+    
+    BasicSloppyDocScorer(BasicStats stats, byte norms[]) {
+      this.stats = stats;
+      this.norms = norms;
+    }
+    
+    @Override
+    public float score(int doc, float freq) {
+      // We have to supply something in case norms are omitted
+      return SimilarityBase.this.score(stats, freq,
+          norms == null ? 1F : decodeNormValue(norms[doc]));
+    }
+    @Override
+    public Explanation explain(int doc, Explanation freq) {
+      return SimilarityBase.this.explain(stats, doc, freq,
+          norms == null ? 1F : decodeNormValue(norms[doc]));
+    }
+
+    @Override
+    public float computeSlopFactor(int distance) {
+      return 1.0f / (distance + 1);
+    }
+
+    @Override
+    public float computePayloadFactor(int doc, int start, int end, BytesRef payload) {
+      return 1f;
+    }
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/Similarity.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/Similarity.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/Similarity.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/Similarity.java	2011-09-07 00:16:40.515982131 -0400
@@ -0,0 +1,230 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+
+import java.io.IOException;
+
+import org.apache.lucene.document.IndexDocValuesField; // javadoc
+import org.apache.lucene.index.FieldInvertState;
+import org.apache.lucene.index.IndexReader; // javadoc
+import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.index.Terms; // javadoc
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.PhraseQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.spans.SpanQuery; // javadoc
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.SmallFloat; // javadoc
+import org.apache.lucene.util.TermContext;
+
+
+/** 
+ * Similarity defines the components of Lucene scoring.
+ * <p>
+ * Expert: Scoring API.
+ * <p>
+ * This is a low-level API, you should only extend this API if you want to implement 
+ * an information retrieval <i>model</i>.  If you are instead looking for a convenient way 
+ * to alter Lucene's scoring, consider extending a higher-level implementation
+ * such as {@link TFIDFSimilarity}, which implements the vector space model with this API, or 
+ * just tweaking the default implementation: {@link DefaultSimilarity}.
+ * <p>
+ * Similarity determines how Lucene weights terms, and Lucene interacts with
+ * this class at both <a href="#indextime">index-time</a> and 
+ * <a href="#querytime">query-time</a>.
+ * <p>
+ * <a name="indextime"/>
+ * At indexing time, the indexer calls {@link #computeNorm(FieldInvertState)}, allowing
+ * the Similarity implementation to return a per-document byte for the field that will 
+ * be later accessible via {@link IndexReader#norms(String)}.  Lucene makes no assumption
+ * about what is in this byte, but it is most useful for encoding length normalization 
+ * information.
+ * <p>
+ * Implementations should carefully consider how the normalization byte is encoded: while
+ * Lucene's classical {@link TFIDFSimilarity} encodes a combination of index-time boost
+ * and length normalization information with {@link SmallFloat}, this might not be suitable
+ * for all purposes.
+ * <p>
+ * Many formulas require the use of average document length, which can be computed via a 
+ * combination of {@link Terms#getSumTotalTermFreq()} and {@link IndexReader#maxDoc()},
+ * <p>
+ * Because index-time boost is handled entirely at the application level anyway,
+ * an application can alternatively store the index-time boost separately using an 
+ * {@link IndexDocValuesField}, and access this at query-time with 
+ * {@link IndexReader#docValues(String)}.
+ * <p>
+ * Finally, using index-time boosts (either via folding into the normalization byte or
+ * via IndexDocValues), is an inefficient way to boost the scores of different fields if the
+ * boost will be the same for every document, instead the Similarity can simply take a constant
+ * boost parameter <i>C</i>, and the SimilarityProvider can return different instances with
+ * different boosts depending upon field name.
+ * <p>
+ * <a name="querytime"/>
+ * At query-time, Queries interact with the Similarity via these steps:
+ * <ol>
+ *   <li>The {@link #computeStats(IndexSearcher, String, float, TermContext...)} method is called a single time,
+ *       allowing the implementation to compute any statistics (such as IDF, average document length, etc)
+ *       across <i>the entire collection</i>. The {@link TermContext}s passed in are already positioned
+ *       to the terms involved with the raw statistics involved, so a Similarity can freely use any combination
+ *       of term statistics without causing any additional I/O. Lucene makes no assumption about what is 
+ *       stored in the returned {@link Similarity.Stats} object.
+ *   <li>The query normalization process occurs a single time: {@link Similarity.Stats#getValueForNormalization()}
+ *       is called for each query leaf node, {@link SimilarityProvider#queryNorm(float)} is called for the top-level
+ *       query, and finally {@link Similarity.Stats#normalize(float, float)} passes down the normalization value
+ *       and any top-level boosts (e.g. from enclosing {@link BooleanQuery}s).
+ *   <li>For each segment in the index, the Query creates a {@link #exactDocScorer(Stats, String, IndexReader.AtomicReaderContext)}
+ *       (for queries with exact frequencies such as TermQuerys and exact PhraseQueries) or a 
+ *       {@link #sloppyDocScorer(Stats, String, IndexReader.AtomicReaderContext)} (for queries with sloppy frequencies such as
+ *       SpanQuerys and sloppy PhraseQueries). The score() method is called for each matching document.
+ * </ol>
+ * <p>
+ * <a name="explaintime"/>
+ * When {@link IndexSearcher#explain(Query, int)} is called, queries consult the Similarity's DocScorer for an 
+ * explanation of how it computed its score. The query passes in a the document id and an explanation of how the frequency
+ * was computed.
+ *
+ * @see org.apache.lucene.index.IndexWriterConfig#setSimilarityProvider(SimilarityProvider)
+ * @see IndexSearcher#setSimilarityProvider(SimilarityProvider)
+ * @lucene.experimental
+ */
+public abstract class Similarity {
+  /**
+   * Computes the normalization value for a field, given the accumulated
+   * state of term processing for this field (see {@link FieldInvertState}).
+   * 
+   * <p>Implementations should calculate a byte value based on the field
+   * state and then return that value.
+   *
+   * <p>Matches in longer fields are less precise, so implementations of this
+   * method usually return smaller values when <code>state.getLength()</code> is large,
+   * and larger values when <code>state.getLength()</code> is small.
+   * 
+   * @lucene.experimental
+   * 
+   * @param state current processing state for this field
+   * @return the calculated byte norm
+   */
+  public abstract byte computeNorm(FieldInvertState state);
+  
+  /**
+   * Compute any collection-level stats (e.g. IDF, average document length, etc) needed for scoring a query.
+   */
+  public abstract Stats computeStats(IndexSearcher searcher, String fieldName, float queryBoost, TermContext... termContexts) throws IOException;
+  
+  /**
+   * returns a new {@link Similarity.ExactDocScorer}.
+   */
+  public abstract ExactDocScorer exactDocScorer(Stats stats, String fieldName, AtomicReaderContext context) throws IOException;
+  
+  /**
+   * returns a new {@link Similarity.SloppyDocScorer}.
+   */
+  public abstract SloppyDocScorer sloppyDocScorer(Stats stats, String fieldName, AtomicReaderContext context) throws IOException;
+  
+  /**
+   * API for scoring exact queries such as {@link TermQuery} and 
+   * exact {@link PhraseQuery}.
+   * <p>
+   * Term frequencies are integers (the term or phrase's tf)
+   */
+  public static abstract class ExactDocScorer {
+    /**
+     * Score a single document
+     * @param doc document id
+     * @param freq term frequency
+     * @return document's score
+     */
+    public abstract float score(int doc, int freq);
+    
+    /**
+     * Explain the score for a single document
+     * @param doc document id
+     * @param freq Explanation of how the term frequency was computed
+     * @return document's score
+     */
+    public Explanation explain(int doc, Explanation freq) {
+      Explanation result = new Explanation(score(doc, (int)freq.getValue()), 
+          "score(doc=" + doc + ",freq=" + freq.getValue() +"), with freq of:");
+      result.addDetail(freq);
+      return result;
+    }
+  }
+  
+  /**
+   * API for scoring "sloppy" queries such as {@link SpanQuery} and 
+   * sloppy {@link PhraseQuery}.
+   * <p>
+   * Term frequencies are floating point values.
+   */
+  public static abstract class SloppyDocScorer {
+    /**
+     * Score a single document
+     * @param doc document id
+     * @param freq sloppy term frequency
+     * @return document's score
+     */
+    public abstract float score(int doc, float freq);
+
+    /** Computes the amount of a sloppy phrase match, based on an edit distance. */
+    public abstract float computeSlopFactor(int distance);
+    
+    /** Calculate a scoring factor based on the data in the payload. */
+    public abstract float computePayloadFactor(int doc, int start, int end, BytesRef payload);
+    
+    /**
+     * Explain the score for a single document
+     * @param doc document id
+     * @param freq Explanation of how the sloppy term frequency was computed
+     * @return document's score
+     */
+    public Explanation explain(int doc, Explanation freq) {
+      Explanation result = new Explanation(score(doc, freq.getValue()), 
+          "score(doc=" + doc + ",freq=" + freq.getValue() +"), with freq of:");
+      result.addDetail(freq);
+      return result;
+    }
+  }
+  
+  /** Stores the statistics for the indexed collection. This abstract
+   * implementation is empty; descendants of {@code Similarity} should
+   * subclass {@code Stats} and define the statistics they require in the
+   * subclass. Examples include idf, average field length, etc.
+   */
+  public static abstract class Stats {
+    
+    /** The value for normalization of contained query clauses (e.g. sum of squared weights).
+     * <p>
+     * NOTE: a Similarity implementation might not use any query normalization at all,
+     * its not required. However, if it wants to participate in query normalization,
+     * it can return a value here.
+     */
+    public abstract float getValueForNormalization();
+    
+    /** Assigns the query normalization factor and boost from parent queries to this.
+     * <p>
+     * NOTE: a Similarity implementation might not use this normalized value at all,
+     * its not required. However, its usually a good idea to at least incorporate 
+     * the topLevelBoost (e.g. from an outer BooleanQuery) into its score.
+     */
+    public abstract void normalize(float queryNorm, float topLevelBoost);
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/SimilarityProvider.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/SimilarityProvider.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/SimilarityProvider.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/SimilarityProvider.java	2011-08-23 08:43:39.731460295 -0400
@@ -0,0 +1,68 @@
+package org.apache.lucene.search.similarities;
+
+import org.apache.lucene.search.BooleanQuery;
+
+/**
+ * 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.
+ */
+
+/**
+ * Expert: Scoring API.
+ * 
+ * Provides top-level scoring functions that aren't specific to a field,
+ * and work across multi-field queries (such as {@link BooleanQuery}).
+ * 
+ * Field-specific scoring is accomplished through {@link Similarity}.
+ * 
+ * @lucene.experimental
+ */
+public interface SimilarityProvider {
+
+  /** Computes a score factor based on the fraction of all query terms that a
+   * document contains.  This value is multiplied into scores.
+   *
+   * <p>The presence of a large portion of the query terms indicates a better
+   * match with the query, so implementations of this method usually return
+   * larger values when the ratio between these parameters is large and smaller
+   * values when the ratio between them is small.
+   *
+   * @param overlap the number of query terms matched in the document
+   * @param maxOverlap the total number of terms in the query
+   * @return a score factor based on term overlap with the query
+   */
+  public abstract float coord(int overlap, int maxOverlap);
+  
+  /** Computes the normalization value for a query given the sum of the squared
+   * weights of each of the query terms.  This value is multiplied into the
+   * weight of each query term. While the classic query normalization factor is
+   * computed as 1/sqrt(sumOfSquaredWeights), other implementations might
+   * completely ignore sumOfSquaredWeights (ie return 1).
+   *
+   * <p>This does not affect ranking, but the default implementation does make scores
+   * from different queries more comparable than they would be by eliminating the
+   * magnitude of the Query vector as a factor in the score.
+   *
+   * @param sumOfSquaredWeights the sum of the squares of query term weights
+   * @return a normalization factor for query weights
+   */
+  public abstract float queryNorm(float sumOfSquaredWeights);
+  
+  /** Returns a {@link Similarity} for scoring a field
+   * @param field field name.
+   * @return a field-specific Similarity.
+   */
+  public abstract Similarity get(String field);
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/TFIDFSimilarity.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/TFIDFSimilarity.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/similarities/TFIDFSimilarity.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/similarities/TFIDFSimilarity.java	2011-08-29 18:59:31.331459518 -0400
@@ -0,0 +1,867 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+
+import java.io.IOException;
+
+import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.PhraseQuery;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.TermContext;
+import org.apache.lucene.util.SmallFloat;
+
+
+/**
+ * Implementation of {@link Similarity} with the Vector Space Model.
+ * <p>
+ * Expert: Scoring API.
+ * <p>TFIDFSimilarity defines the components of Lucene scoring.
+ * Overriding computation of these components is a convenient
+ * way to alter Lucene scoring.
+ *
+ * <p>Suggested reading:
+ * <a href="http://nlp.stanford.edu/IR-book/html/htmledition/queries-as-vectors-1.html">
+ * Introduction To Information Retrieval, Chapter 6</a>.
+ *
+ * <p>The following describes how Lucene scoring evolves from
+ * underlying information retrieval models to (efficient) implementation.
+ * We first brief on <i>VSM Score</i>, 
+ * then derive from it <i>Lucene's Conceptual Scoring Formula</i>,
+ * from which, finally, evolves <i>Lucene's Practical Scoring Function</i> 
+ * (the latter is connected directly with Lucene classes and methods).    
+ *
+ * <p>Lucene combines
+ * <a href="http://en.wikipedia.org/wiki/Standard_Boolean_model">
+ * Boolean model (BM) of Information Retrieval</a>
+ * with
+ * <a href="http://en.wikipedia.org/wiki/Vector_Space_Model">
+ * Vector Space Model (VSM) of Information Retrieval</a> -
+ * documents "approved" by BM are scored by VSM.
+ *
+ * <p>In VSM, documents and queries are represented as
+ * weighted vectors in a multi-dimensional space,
+ * where each distinct index term is a dimension,
+ * and weights are
+ * <a href="http://en.wikipedia.org/wiki/Tfidf">Tf-idf</a> values.
+ *
+ * <p>VSM does not require weights to be <i>Tf-idf</i> values,
+ * but <i>Tf-idf</i> values are believed to produce search results of high quality,
+ * and so Lucene is using <i>Tf-idf</i>.
+ * <i>Tf</i> and <i>Idf</i> are described in more detail below,
+ * but for now, for completion, let's just say that
+ * for given term <i>t</i> and document (or query) <i>x</i>,
+ * <i>Tf(t,x)</i> varies with the number of occurrences of term <i>t</i> in <i>x</i>
+ * (when one increases so does the other) and
+ * <i>idf(t)</i> similarly varies with the inverse of the
+ * number of index documents containing term <i>t</i>.
+ *
+ * <p><i>VSM score</i> of document <i>d</i> for query <i>q</i> is the
+ * <a href="http://en.wikipedia.org/wiki/Cosine_similarity">
+ * Cosine Similarity</a>
+ * of the weighted query vectors <i>V(q)</i> and <i>V(d)</i>:
+ *
+ *  <br>&nbsp;<br>
+ *  <table cellpadding="2" cellspacing="2" border="0" align="center">
+ *    <tr><td>
+ *    <table cellpadding="1" cellspacing="0" border="1" align="center">
+ *      <tr><td>
+ *      <table cellpadding="2" cellspacing="2" border="0" align="center">
+ *        <tr>
+ *          <td valign="middle" align="right" rowspan="1">
+ *            cosine-similarity(q,d) &nbsp; = &nbsp;
+ *          </td>
+ *          <td valign="middle" align="center">
+ *            <table>
+ *               <tr><td align="center"><small>V(q)&nbsp;&middot;&nbsp;V(d)</small></td></tr>
+ *               <tr><td align="center">&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;</td></tr>
+ *               <tr><td align="center"><small>|V(q)|&nbsp;|V(d)|</small></td></tr>
+ *            </table>
+ *          </td>
+ *        </tr>
+ *      </table>
+ *      </td></tr>
+ *    </table>
+ *    </td></tr>
+ *    <tr><td>
+ *    <center><font=-1><u>VSM Score</u></font></center>
+ *    </td></tr>
+ *  </table>
+ *  <br>&nbsp;<br>
+ *   
+ *
+ * Where <i>V(q)</i> &middot; <i>V(d)</i> is the
+ * <a href="http://en.wikipedia.org/wiki/Dot_product">dot product</a>
+ * of the weighted vectors,
+ * and <i>|V(q)|</i> and <i>|V(d)|</i> are their
+ * <a href="http://en.wikipedia.org/wiki/Euclidean_norm#Euclidean_norm">Euclidean norms</a>.
+ *
+ * <p>Note: the above equation can be viewed as the dot product of
+ * the normalized weighted vectors, in the sense that dividing
+ * <i>V(q)</i> by its euclidean norm is normalizing it to a unit vector.
+ *
+ * <p>Lucene refines <i>VSM score</i> for both search quality and usability:
+ * <ul>
+ *  <li>Normalizing <i>V(d)</i> to the unit vector is known to be problematic in that 
+ *  it removes all document length information. 
+ *  For some documents removing this info is probably ok, 
+ *  e.g. a document made by duplicating a certain paragraph <i>10</i> times,
+ *  especially if that paragraph is made of distinct terms. 
+ *  But for a document which contains no duplicated paragraphs, 
+ *  this might be wrong. 
+ *  To avoid this problem, a different document length normalization 
+ *  factor is used, which normalizes to a vector equal to or larger 
+ *  than the unit vector: <i>doc-len-norm(d)</i>.
+ *  </li>
+ *
+ *  <li>At indexing, users can specify that certain documents are more
+ *  important than others, by assigning a document boost.
+ *  For this, the score of each document is also multiplied by its boost value
+ *  <i>doc-boost(d)</i>.
+ *  </li>
+ *
+ *  <li>Lucene is field based, hence each query term applies to a single
+ *  field, document length normalization is by the length of the certain field,
+ *  and in addition to document boost there are also document fields boosts.
+ *  </li>
+ *
+ *  <li>The same field can be added to a document during indexing several times,
+ *  and so the boost of that field is the multiplication of the boosts of
+ *  the separate additions (or parts) of that field within the document.
+ *  </li>
+ *
+ *  <li>At search time users can specify boosts to each query, sub-query, and
+ *  each query term, hence the contribution of a query term to the score of
+ *  a document is multiplied by the boost of that query term <i>query-boost(q)</i>.
+ *  </li>
+ *
+ *  <li>A document may match a multi term query without containing all
+ *  the terms of that query (this is correct for some of the queries),
+ *  and users can further reward documents matching more query terms
+ *  through a coordination factor, which is usually larger when
+ *  more terms are matched: <i>coord-factor(q,d)</i>.
+ *  </li>
+ * </ul>
+ *
+ * <p>Under the simplifying assumption of a single field in the index,
+ * we get <i>Lucene's Conceptual scoring formula</i>:
+ *
+ *  <br>&nbsp;<br>
+ *  <table cellpadding="2" cellspacing="2" border="0" align="center">
+ *    <tr><td>
+ *    <table cellpadding="1" cellspacing="0" border="1" align="center">
+ *      <tr><td>
+ *      <table cellpadding="2" cellspacing="2" border="0" align="center">
+ *        <tr>
+ *          <td valign="middle" align="right" rowspan="1">
+ *            score(q,d) &nbsp; = &nbsp;
+ *            <font color="#FF9933">coord-factor(q,d)</font> &middot; &nbsp;
+ *            <font color="#CCCC00">query-boost(q)</font> &middot; &nbsp;
+ *          </td>
+ *          <td valign="middle" align="center">
+ *            <table>
+ *               <tr><td align="center"><small><font color="#993399">V(q)&nbsp;&middot;&nbsp;V(d)</font></small></td></tr>
+ *               <tr><td align="center">&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;</td></tr>
+ *               <tr><td align="center"><small><font color="#FF33CC">|V(q)|</font></small></td></tr>
+ *            </table>
+ *          </td>
+ *          <td valign="middle" align="right" rowspan="1">
+ *            &nbsp; &middot; &nbsp; <font color="#3399FF">doc-len-norm(d)</font>
+ *            &nbsp; &middot; &nbsp; <font color="#3399FF">doc-boost(d)</font>
+ *          </td>
+ *        </tr>
+ *      </table>
+ *      </td></tr>
+ *    </table>
+ *    </td></tr>
+ *    <tr><td>
+ *    <center><font=-1><u>Lucene Conceptual Scoring Formula</u></font></center>
+ *    </td></tr>
+ *  </table>
+ *  <br>&nbsp;<br>
+ *
+ * <p>The conceptual formula is a simplification in the sense that (1) terms and documents
+ * are fielded and (2) boosts are usually per query term rather than per query.
+ *
+ * <p>We now describe how Lucene implements this conceptual scoring formula, and
+ * derive from it <i>Lucene's Practical Scoring Function</i>.
+ *  
+ * <p>For efficient score computation some scoring components
+ * are computed and aggregated in advance:
+ *
+ * <ul>
+ *  <li><i>Query-boost</i> for the query (actually for each query term)
+ *  is known when search starts.
+ *  </li>
+ *
+ *  <li>Query Euclidean norm <i>|V(q)|</i> can be computed when search starts,
+ *  as it is independent of the document being scored.
+ *  From search optimization perspective, it is a valid question
+ *  why bother to normalize the query at all, because all
+ *  scored documents will be multiplied by the same <i>|V(q)|</i>,
+ *  and hence documents ranks (their order by score) will not
+ *  be affected by this normalization.
+ *  There are two good reasons to keep this normalization:
+ *  <ul>
+ *   <li>Recall that
+ *   <a href="http://en.wikipedia.org/wiki/Cosine_similarity">
+ *   Cosine Similarity</a> can be used find how similar
+ *   two documents are. One can use Lucene for e.g.
+ *   clustering, and use a document as a query to compute
+ *   its similarity to other documents.
+ *   In this use case it is important that the score of document <i>d3</i>
+ *   for query <i>d1</i> is comparable to the score of document <i>d3</i>
+ *   for query <i>d2</i>. In other words, scores of a document for two
+ *   distinct queries should be comparable.
+ *   There are other applications that may require this.
+ *   And this is exactly what normalizing the query vector <i>V(q)</i>
+ *   provides: comparability (to a certain extent) of two or more queries.
+ *   </li>
+ *
+ *   <li>Applying query normalization on the scores helps to keep the
+ *   scores around the unit vector, hence preventing loss of score data
+ *   because of floating point precision limitations.
+ *   </li>
+ *  </ul>
+ *  </li>
+ *
+ *  <li>Document length norm <i>doc-len-norm(d)</i> and document
+ *  boost <i>doc-boost(d)</i> are known at indexing time.
+ *  They are computed in advance and their multiplication
+ *  is saved as a single value in the index: <i>norm(d)</i>.
+ *  (In the equations below, <i>norm(t in d)</i> means <i>norm(field(t) in doc d)</i>
+ *  where <i>field(t)</i> is the field associated with term <i>t</i>.)
+ *  </li>
+ * </ul>
+ *
+ * <p><i>Lucene's Practical Scoring Function</i> is derived from the above.
+ * The color codes demonstrate how it relates
+ * to those of the <i>conceptual</i> formula:
+ *
+ * <P>
+ * <table cellpadding="2" cellspacing="2" border="0" align="center">
+ *  <tr><td>
+ *  <table cellpadding="" cellspacing="2" border="2" align="center">
+ *  <tr><td>
+ *   <table cellpadding="2" cellspacing="2" border="0" align="center">
+ *   <tr>
+ *     <td valign="middle" align="right" rowspan="1">
+ *       score(q,d) &nbsp; = &nbsp;
+ *       <A HREF="#formula_coord"><font color="#FF9933">coord(q,d)</font></A> &nbsp;&middot;&nbsp;
+ *       <A HREF="#formula_queryNorm"><font color="#FF33CC">queryNorm(q)</font></A> &nbsp;&middot;&nbsp;
+ *     </td>
+ *     <td valign="bottom" align="center" rowspan="1">
+ *       <big><big><big>&sum;</big></big></big>
+ *     </td>
+ *     <td valign="middle" align="right" rowspan="1">
+ *       <big><big>(</big></big>
+ *       <A HREF="#formula_tf"><font color="#993399">tf(t in d)</font></A> &nbsp;&middot;&nbsp;
+ *       <A HREF="#formula_idf"><font color="#993399">idf(t)</font></A><sup>2</sup> &nbsp;&middot;&nbsp;
+ *       <A HREF="#formula_termBoost"><font color="#CCCC00">t.getBoost()</font></A>&nbsp;&middot;&nbsp;
+ *       <A HREF="#formula_norm"><font color="#3399FF">norm(t,d)</font></A>
+ *       <big><big>)</big></big>
+ *     </td>
+ *   </tr>
+ *   <tr valigh="top">
+ *    <td></td>
+ *    <td align="center"><small>t in q</small></td>
+ *    <td></td>
+ *   </tr>
+ *   </table>
+ *  </td></tr>
+ *  </table>
+ * </td></tr>
+ * <tr><td>
+ *  <center><font=-1><u>Lucene Practical Scoring Function</u></font></center>
+ * </td></tr>
+ * </table>
+ *
+ * <p> where
+ * <ol>
+ *    <li>
+ *      <A NAME="formula_tf"></A>
+ *      <b><i>tf(t in d)</i></b>
+ *      correlates to the term's <i>frequency</i>,
+ *      defined as the number of times term <i>t</i> appears in the currently scored document <i>d</i>.
+ *      Documents that have more occurrences of a given term receive a higher score.
+ *      Note that <i>tf(t in q)</i> is assumed to be <i>1</i> and therefore it does not appear in this equation,
+ *      However if a query contains twice the same term, there will be
+ *      two term-queries with that same term and hence the computation would still be correct (although
+ *      not very efficient).
+ *      The default computation for <i>tf(t in d)</i> in
+ *      {@link org.apache.lucene.search.similarities.DefaultSimilarity#tf(float) DefaultSimilarity} is:
+ *
+ *      <br>&nbsp;<br>
+ *      <table cellpadding="2" cellspacing="2" border="0" align="center">
+ *        <tr>
+ *          <td valign="middle" align="right" rowspan="1">
+ *            {@link org.apache.lucene.search.similarities.DefaultSimilarity#tf(float) tf(t in d)} &nbsp; = &nbsp;
+ *          </td>
+ *          <td valign="top" align="center" rowspan="1">
+ *               frequency<sup><big>&frac12;</big></sup>
+ *          </td>
+ *        </tr>
+ *      </table>
+ *      <br>&nbsp;<br>
+ *    </li>
+ *
+ *    <li>
+ *      <A NAME="formula_idf"></A>
+ *      <b><i>idf(t)</i></b> stands for Inverse Document Frequency. This value
+ *      correlates to the inverse of <i>docFreq</i>
+ *      (the number of documents in which the term <i>t</i> appears).
+ *      This means rarer terms give higher contribution to the total score.
+ *      <i>idf(t)</i> appears for <i>t</i> in both the query and the document,
+ *      hence it is squared in the equation.
+ *      The default computation for <i>idf(t)</i> in
+ *      {@link org.apache.lucene.search.similarities.DefaultSimilarity#idf(int, int) DefaultSimilarity} is:
+ *
+ *      <br>&nbsp;<br>
+ *      <table cellpadding="2" cellspacing="2" border="0" align="center">
+ *        <tr>
+ *          <td valign="middle" align="right">
+ *            {@link org.apache.lucene.search.similarities.DefaultSimilarity#idf(int, int) idf(t)}&nbsp; = &nbsp;
+ *          </td>
+ *          <td valign="middle" align="center">
+ *            1 + log <big>(</big>
+ *          </td>
+ *          <td valign="middle" align="center">
+ *            <table>
+ *               <tr><td align="center"><small>numDocs</small></td></tr>
+ *               <tr><td align="center">&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;</td></tr>
+ *               <tr><td align="center"><small>docFreq+1</small></td></tr>
+ *            </table>
+ *          </td>
+ *          <td valign="middle" align="center">
+ *            <big>)</big>
+ *          </td>
+ *        </tr>
+ *      </table>
+ *      <br>&nbsp;<br>
+ *    </li>
+ *
+ *    <li>
+ *      <A NAME="formula_coord"></A>
+ *      <b><i>coord(q,d)</i></b>
+ *      is a score factor based on how many of the query terms are found in the specified document.
+ *      Typically, a document that contains more of the query's terms will receive a higher score
+ *      than another document with fewer query terms.
+ *      This is a search time factor computed in
+ *      {@link SimilarityProvider#coord(int, int) coord(q,d)}
+ *      by the SimilarityProvider in effect at search time.
+ *      <br>&nbsp;<br>
+ *    </li>
+ *
+ *    <li><b>
+ *      <A NAME="formula_queryNorm"></A>
+ *      <i>queryNorm(q)</i>
+ *      </b>
+ *      is a normalizing factor used to make scores between queries comparable.
+ *      This factor does not affect document ranking (since all ranked documents are multiplied by the same factor),
+ *      but rather just attempts to make scores from different queries (or even different indexes) comparable.
+ *      This is a search time factor computed by the Similarity in effect at search time.
+ *
+ *      The default computation in
+ *      {@link org.apache.lucene.search.similarities.DefaultSimilarityProvider#queryNorm(float) DefaultSimilarityProvider}
+ *      produces a <a href="http://en.wikipedia.org/wiki/Euclidean_norm#Euclidean_norm">Euclidean norm</a>:
+ *      <br>&nbsp;<br>
+ *      <table cellpadding="1" cellspacing="0" border="0" align="center">
+ *        <tr>
+ *          <td valign="middle" align="right" rowspan="1">
+ *            queryNorm(q)  &nbsp; = &nbsp;
+ *            {@link org.apache.lucene.search.similarities.DefaultSimilarityProvider#queryNorm(float) queryNorm(sumOfSquaredWeights)}
+ *            &nbsp; = &nbsp;
+ *          </td>
+ *          <td valign="middle" align="center" rowspan="1">
+ *            <table>
+ *               <tr><td align="center"><big>1</big></td></tr>
+ *               <tr><td align="center"><big>
+ *                  &ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;
+ *               </big></td></tr>
+ *               <tr><td align="center">sumOfSquaredWeights<sup><big>&frac12;</big></sup></td></tr>
+ *            </table>
+ *          </td>
+ *        </tr>
+ *      </table>
+ *      <br>&nbsp;<br>
+ *
+ *      The sum of squared weights (of the query terms) is
+ *      computed by the query {@link org.apache.lucene.search.Weight} object.
+ *      For example, a {@link org.apache.lucene.search.BooleanQuery}
+ *      computes this value as:
+ *
+ *      <br>&nbsp;<br>
+ *      <table cellpadding="1" cellspacing="0" border="0"n align="center">
+ *        <tr>
+ *          <td valign="middle" align="right" rowspan="1">
+ *            {@link org.apache.lucene.search.Weight#getValueForNormalization() sumOfSquaredWeights} &nbsp; = &nbsp;
+ *            {@link org.apache.lucene.search.Query#getBoost() q.getBoost()} <sup><big>2</big></sup>
+ *            &nbsp;&middot;&nbsp;
+ *          </td>
+ *          <td valign="bottom" align="center" rowspan="1">
+ *            <big><big><big>&sum;</big></big></big>
+ *          </td>
+ *          <td valign="middle" align="right" rowspan="1">
+ *            <big><big>(</big></big>
+ *            <A HREF="#formula_idf">idf(t)</A> &nbsp;&middot;&nbsp;
+ *            <A HREF="#formula_termBoost">t.getBoost()</A>
+ *            <big><big>) <sup>2</sup> </big></big>
+ *          </td>
+ *        </tr>
+ *        <tr valigh="top">
+ *          <td></td>
+ *          <td align="center"><small>t in q</small></td>
+ *          <td></td>
+ *        </tr>
+ *      </table>
+ *      <br>&nbsp;<br>
+ *
+ *    </li>
+ *
+ *    <li>
+ *      <A NAME="formula_termBoost"></A>
+ *      <b><i>t.getBoost()</i></b>
+ *      is a search time boost of term <i>t</i> in the query <i>q</i> as
+ *      specified in the query text
+ *      (see <A HREF="../../../../../../queryparsersyntax.html#Boosting a Term">query syntax</A>),
+ *      or as set by application calls to
+ *      {@link org.apache.lucene.search.Query#setBoost(float) setBoost()}.
+ *      Notice that there is really no direct API for accessing a boost of one term in a multi term query,
+ *      but rather multi terms are represented in a query as multi
+ *      {@link org.apache.lucene.search.TermQuery TermQuery} objects,
+ *      and so the boost of a term in the query is accessible by calling the sub-query
+ *      {@link org.apache.lucene.search.Query#getBoost() getBoost()}.
+ *      <br>&nbsp;<br>
+ *    </li>
+ *
+ *    <li>
+ *      <A NAME="formula_norm"></A>
+ *      <b><i>norm(t,d)</i></b> encapsulates a few (indexing time) boost and length factors:
+ *
+ *      <ul>
+ *        <li><b>Field boost</b> - set by calling
+ *        {@link org.apache.lucene.document.Field#setBoost(float) field.setBoost()}
+ *        before adding the field to a document.
+ *        </li>
+ *        <li><b>lengthNorm</b> - computed
+ *        when the document is added to the index in accordance with the number of tokens
+ *        of this field in the document, so that shorter fields contribute more to the score.
+ *        LengthNorm is computed by the Similarity class in effect at indexing.
+ *        </li>
+ *      </ul>
+ *      The {@link #computeNorm} method is responsible for
+ *      combining all of these factors into a single float.
+ *
+ *      <p>
+ *      When a document is added to the index, all the above factors are multiplied.
+ *      If the document has multiple fields with the same name, all their boosts are multiplied together:
+ *
+ *      <br>&nbsp;<br>
+ *      <table cellpadding="1" cellspacing="0" border="0"n align="center">
+ *        <tr>
+ *          <td valign="middle" align="right" rowspan="1">
+ *            norm(t,d) &nbsp; = &nbsp;
+ *            lengthNorm
+ *            &nbsp;&middot;&nbsp;
+ *          </td>
+ *          <td valign="bottom" align="center" rowspan="1">
+ *            <big><big><big>&prod;</big></big></big>
+ *          </td>
+ *          <td valign="middle" align="right" rowspan="1">
+ *            {@link org.apache.lucene.index.IndexableField#boost() f.boost}()
+ *          </td>
+ *        </tr>
+ *        <tr valigh="top">
+ *          <td></td>
+ *          <td align="center"><small>field <i><b>f</b></i> in <i>d</i> named as <i><b>t</b></i></small></td>
+ *          <td></td>
+ *        </tr>
+ *      </table>
+ *      <br>&nbsp;<br>
+ *      However the resulted <i>norm</i> value is {@link #encodeNormValue(float) encoded} as a single byte
+ *      before being stored.
+ *      At search time, the norm byte value is read from the index
+ *      {@link org.apache.lucene.store.Directory directory} and
+ *      {@link #decodeNormValue(byte) decoded} back to a float <i>norm</i> value.
+ *      This encoding/decoding, while reducing index size, comes with the price of
+ *      precision loss - it is not guaranteed that <i>decode(encode(x)) = x</i>.
+ *      For instance, <i>decode(encode(0.89)) = 0.75</i>.
+ *      <br>&nbsp;<br>
+ *      Compression of norm values to a single byte saves memory at search time, 
+ *      because once a field is referenced at search time, its norms - for 
+ *      all documents - are maintained in memory.
+ *      <br>&nbsp;<br>
+ *      The rationale supporting such lossy compression of norm values is that
+ *      given the difficulty (and inaccuracy) of users to express their true information
+ *      need by a query, only big differences matter.
+ *      <br>&nbsp;<br>
+ *      Last, note that search time is too late to modify this <i>norm</i> part of scoring, e.g. by
+ *      using a different {@link Similarity} for search.
+ *      <br>&nbsp;<br>
+ *    </li>
+ * </ol>
+ *
+ * @see org.apache.lucene.index.IndexWriterConfig#setSimilarityProvider(SimilarityProvider)
+ * @see IndexSearcher#setSimilarityProvider(SimilarityProvider)
+ */
+public abstract class TFIDFSimilarity extends Similarity {
+  
+  /** Computes a score factor based on a term or phrase's frequency in a
+   * document.  This value is multiplied by the {@link #idf(int, int)}
+   * factor for each term in the query and these products are then summed to
+   * form the initial score for a document.
+   *
+   * <p>Terms and phrases repeated in a document indicate the topic of the
+   * document, so implementations of this method usually return larger values
+   * when <code>freq</code> is large, and smaller values when <code>freq</code>
+   * is small.
+   *
+   * <p>The default implementation calls {@link #tf(float)}.
+   *
+   * @param freq the frequency of a term within a document
+   * @return a score factor based on a term's within-document frequency
+   */
+  public float tf(int freq) {
+    return tf((float)freq);
+  }
+
+  /** Computes a score factor based on a term or phrase's frequency in a
+   * document.  This value is multiplied by the {@link #idf(int, int)}
+   * factor for each term in the query and these products are then summed to
+   * form the initial score for a document.
+   *
+   * <p>Terms and phrases repeated in a document indicate the topic of the
+   * document, so implementations of this method usually return larger values
+   * when <code>freq</code> is large, and smaller values when <code>freq</code>
+   * is small.
+   *
+   * @param freq the frequency of a term within a document
+   * @return a score factor based on a term's within-document frequency
+   */
+  public abstract float tf(float freq);
+
+  /**
+   * Computes a score factor for a simple term and returns an explanation
+   * for that score factor.
+   * 
+   * <p>
+   * The default implementation uses:
+   * 
+   * <pre>
+   * idf(docFreq, searcher.maxDoc());
+   * </pre>
+   * 
+   * Note that {@link IndexSearcher#maxDoc()} is used instead of
+   * {@link org.apache.lucene.index.IndexReader#numDocs() IndexReader#numDocs()} because also 
+   * {@link IndexSearcher#docFreq(Term)} is used, and when the latter 
+   * is inaccurate, so is {@link IndexSearcher#maxDoc()}, and in the same direction.
+   * In addition, {@link IndexSearcher#maxDoc()} is more efficient to compute
+   *   
+   * @param stats statistics of the term in question
+   * @param searcher the document collection being searched
+   * @return an Explain object that includes both an idf score factor 
+             and an explanation for the term.
+   * @throws IOException
+   */
+  public Explanation idfExplain(TermContext stats, final IndexSearcher searcher) throws IOException {
+    final int df = stats.docFreq();
+    final int max = searcher.maxDoc();
+    final float idf = idf(df, max);
+    return new Explanation(idf, "idf(docFreq=" + df + ", maxDocs=" + max + ")");
+  }
+
+  /**
+   * Computes a score factor for a phrase.
+   * 
+   * <p>
+   * The default implementation sums the idf factor for
+   * each term in the phrase.
+   * 
+   * @param stats statistics of the terms in the phrase
+   * @param searcher the document collection being searched
+   * @return an Explain object that includes both an idf 
+   *         score factor for the phrase and an explanation 
+   *         for each term.
+   * @throws IOException
+   */
+  public Explanation idfExplain(final TermContext stats[], IndexSearcher searcher) throws IOException {
+    final int max = searcher.maxDoc();
+    float idf = 0.0f;
+    final Explanation exp = new Explanation();
+    exp.setDescription("idf(), sum of:");
+    for (final TermContext stat : stats ) {
+      final int df = stat.docFreq();
+      final float termIdf = idf(df, max);
+      exp.addDetail(new Explanation(termIdf, "idf(docFreq=" + df + ", maxDocs=" + max + ")"));
+      idf += termIdf;
+    }
+    exp.setValue(idf);
+    return exp;
+  }
+
+  /** Computes a score factor based on a term's document frequency (the number
+   * of documents which contain the term).  This value is multiplied by the
+   * {@link #tf(int)} factor for each term in the query and these products are
+   * then summed to form the initial score for a document.
+   *
+   * <p>Terms that occur in fewer documents are better indicators of topic, so
+   * implementations of this method usually return larger values for rare terms,
+   * and smaller values for common terms.
+   *
+   * @param docFreq the number of documents which contain the term
+   * @param numDocs the total number of documents in the collection
+   * @return a score factor based on the term's document frequency
+   */
+  public abstract float idf(int docFreq, int numDocs);
+
+  /** Cache of decoded bytes. */
+  private static final float[] NORM_TABLE = new float[256];
+
+  static {
+    for (int i = 0; i < 256; i++)
+      NORM_TABLE[i] = SmallFloat.byte315ToFloat((byte)i);
+  }
+
+  /** Decodes a normalization factor stored in an index.
+   * @see #encodeNormValue(float)
+   */
+  public float decodeNormValue(byte b) {
+    return NORM_TABLE[b & 0xFF];  // & 0xFF maps negative bytes to positive above 127
+  }
+
+  /** Encodes a normalization factor for storage in an index.
+  *
+  * <p>The encoding uses a three-bit mantissa, a five-bit exponent, and
+  * the zero-exponent point at 15, thus
+  * representing values from around 7x10^9 to 2x10^-9 with about one
+  * significant decimal digit of accuracy.  Zero is also represented.
+  * Negative numbers are rounded up to zero.  Values too large to represent
+  * are rounded down to the largest representable value.  Positive values too
+  * small to represent are rounded up to the smallest positive representable
+  * value.
+  * @see org.apache.lucene.document.Field#setBoost(float)
+  * @see org.apache.lucene.util.SmallFloat
+  */
+  public byte encodeNormValue(float f) {
+    return SmallFloat.floatToByte315(f);
+  }
+ 
+  /** Computes the amount of a sloppy phrase match, based on an edit distance.
+   * This value is summed for each sloppy phrase match in a document to form
+   * the frequency to be used in scoring instead of the exact term count.
+   *
+   * <p>A phrase match with a small edit distance to a document passage more
+   * closely matches the document, so implementations of this method usually
+   * return larger values when the edit distance is small and smaller values
+   * when it is large.
+   *
+   * @see PhraseQuery#setSlop(int)
+   * @param distance the edit distance of this sloppy phrase match
+   * @return the frequency increment for this match
+   */
+  public abstract float sloppyFreq(int distance);
+
+  /**
+   * Calculate a scoring factor based on the data in the payload.  Implementations
+   * are responsible for interpreting what is in the payload.  Lucene makes no assumptions about
+   * what is in the byte array.
+   *
+   * @param doc The docId currently being scored.
+   * @param start The start position of the payload
+   * @param end The end position of the payload
+   * @param payload The payload byte array to be scored
+   * @return An implementation dependent float to be used as a scoring factor
+   */
+  public abstract float scorePayload(int doc, int start, int end, BytesRef payload);
+
+  @Override
+  public final Stats computeStats(IndexSearcher searcher, String fieldName, float queryBoost,
+      TermContext... termContexts) throws IOException {
+    final Explanation idf = termContexts.length == 1
+    ? idfExplain(termContexts[0], searcher)
+    : idfExplain(termContexts, searcher);
+    return new IDFStats(idf, queryBoost);
+  }
+
+  @Override
+  public final ExactDocScorer exactDocScorer(Stats stats, String fieldName, AtomicReaderContext context) throws IOException {
+    return new ExactTFIDFDocScorer((IDFStats)stats, context.reader.norms(fieldName));
+  }
+
+  @Override
+  public final SloppyDocScorer sloppyDocScorer(Stats stats, String fieldName, AtomicReaderContext context) throws IOException {
+    return new SloppyTFIDFDocScorer((IDFStats)stats, context.reader.norms(fieldName));
+  }
+  
+  // TODO: we can specialize these for omitNorms up front, but we should test that it doesn't confuse stupid hotspot.
+
+  private final class ExactTFIDFDocScorer extends ExactDocScorer {
+    private final IDFStats stats;
+    private final float weightValue;
+    private final byte[] norms;
+    private static final int SCORE_CACHE_SIZE = 32;
+    private float[] scoreCache = new float[SCORE_CACHE_SIZE];
+    
+    ExactTFIDFDocScorer(IDFStats stats, byte norms[]) {
+      this.stats = stats;
+      this.weightValue = stats.value;
+      this.norms = norms;
+      for (int i = 0; i < SCORE_CACHE_SIZE; i++)
+        scoreCache[i] = tf(i) * weightValue;
+    }
+    
+    @Override
+    public float score(int doc, int freq) {
+      final float raw =                                // compute tf(f)*weight
+        freq < SCORE_CACHE_SIZE                        // check cache
+        ? scoreCache[freq]                             // cache hit
+        : tf(freq)*weightValue;        // cache miss
+
+      return norms == null ? raw : raw * decodeNormValue(norms[doc]); // normalize for field
+    }
+
+    @Override
+    public Explanation explain(int doc, Explanation freq) {
+      return explainScore(doc, freq, stats, norms);
+    }
+  }
+  
+  private final class SloppyTFIDFDocScorer extends SloppyDocScorer {
+    private final IDFStats stats;
+    private final float weightValue;
+    private final byte[] norms;
+    
+    SloppyTFIDFDocScorer(IDFStats stats, byte norms[]) {
+      this.stats = stats;
+      this.weightValue = stats.value;
+      this.norms = norms;
+    }
+    
+    @Override
+    public float score(int doc, float freq) {
+      final float raw = tf(freq) * weightValue; // compute tf(f)*weight
+      
+      return norms == null ? raw : raw * decodeNormValue(norms[doc]);  // normalize for field
+    }
+    
+    @Override
+    public float computeSlopFactor(int distance) {
+      return sloppyFreq(distance);
+    }
+
+    @Override
+    public float computePayloadFactor(int doc, int start, int end, BytesRef payload) {
+      return scorePayload(doc, start, end, payload);
+    }
+
+    @Override
+    public Explanation explain(int doc, Explanation freq) {
+      return explainScore(doc, freq, stats, norms);
+    }
+  }
+  
+  /** Collection statistics for the TF-IDF model. The only statistic of interest
+   * to this model is idf. */
+  private static class IDFStats extends Stats {
+    /** The idf and its explanation */
+    private final Explanation idf;
+    private float queryNorm;
+    private float queryWeight;
+    private final float queryBoost;
+    private float value;
+    
+    public IDFStats(Explanation idf, float queryBoost) {
+      // TODO: Validate?
+      this.idf = idf;
+      this.queryBoost = queryBoost;
+      this.queryWeight = idf.getValue() * queryBoost; // compute query weight
+    }
+
+    @Override
+    public float getValueForNormalization() {
+      // TODO: (sorta LUCENE-1907) make non-static class and expose this squaring via a nice method to subclasses?
+      return queryWeight * queryWeight;  // sum of squared weights
+    }
+
+    @Override
+    public void normalize(float queryNorm, float topLevelBoost) {
+      this.queryNorm = queryNorm * topLevelBoost;
+      queryWeight *= this.queryNorm;              // normalize query weight
+      value = queryWeight * idf.getValue();         // idf for document
+    }
+  }
+  
+  private Explanation explainScore(int doc, Explanation freq, IDFStats stats, byte[] norms) {
+    Explanation result = new Explanation();
+    result.setDescription("score(doc="+doc+",freq="+freq+"), product of:");
+
+    // explain query weight
+    Explanation queryExpl = new Explanation();
+    queryExpl.setDescription("queryWeight, product of:");
+
+    Explanation boostExpl = new Explanation(stats.queryBoost, "boost");
+    if (stats.queryBoost != 1.0f)
+      queryExpl.addDetail(boostExpl);
+    queryExpl.addDetail(stats.idf);
+
+    Explanation queryNormExpl = new Explanation(stats.queryNorm,"queryNorm");
+    queryExpl.addDetail(queryNormExpl);
+
+    queryExpl.setValue(boostExpl.getValue() *
+                       stats.idf.getValue() *
+                       queryNormExpl.getValue());
+
+    result.addDetail(queryExpl);
+
+    // explain field weight
+    Explanation fieldExpl = new Explanation();
+    fieldExpl.setDescription("fieldWeight in "+doc+
+                             ", product of:");
+
+    Explanation tfExplanation = new Explanation();
+    tfExplanation.setValue(tf(freq.getValue()));
+    tfExplanation.setDescription("tf(freq="+freq.getValue()+"), with freq of:");
+    tfExplanation.addDetail(freq);
+    fieldExpl.addDetail(tfExplanation);
+    fieldExpl.addDetail(stats.idf);
+
+    Explanation fieldNormExpl = new Explanation();
+    float fieldNorm =
+      norms!=null ? decodeNormValue(norms[doc]) : 1.0f;
+    fieldNormExpl.setValue(fieldNorm);
+    fieldNormExpl.setDescription("fieldNorm(doc="+doc+")");
+    fieldExpl.addDetail(fieldNormExpl);
+    
+    fieldExpl.setValue(tfExplanation.getValue() *
+                       stats.idf.getValue() *
+                       fieldNormExpl.getValue());
+
+    result.addDetail(fieldExpl);
+    
+    // combine them
+    result.setValue(queryExpl.getValue() * fieldExpl.getValue());
+
+    if (queryExpl.getValue() == 1.0f)
+      return fieldExpl;
+
+    return result;
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/Similarity.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/Similarity.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/Similarity.java	2011-07-17 06:27:33.748948135 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/Similarity.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,224 +0,0 @@
-package org.apache.lucene.search;
-
-/**
- * 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.
- */
-
-
-import java.io.IOException;
-
-import org.apache.lucene.document.IndexDocValuesField; // javadoc
-import org.apache.lucene.index.FieldInvertState;
-import org.apache.lucene.index.IndexReader; // javadoc
-import org.apache.lucene.index.IndexReader.AtomicReaderContext;
-import org.apache.lucene.index.Terms; // javadoc
-import org.apache.lucene.search.spans.SpanQuery; // javadoc
-import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.SmallFloat; // javadoc
-import org.apache.lucene.util.TermContext;
-
-
-/** 
- * Similarity defines the components of Lucene scoring.
- * <p>
- * Expert: Scoring API.
- * <p>
- * This is a low-level API, you should only extend this API if you want to implement 
- * an information retrieval <i>model</i>.  If you are instead looking for a convenient way 
- * to alter Lucene's scoring, consider extending a higher-level implementation
- * such as {@link TFIDFSimilarity}, which implements the vector space model with this API, or 
- * just tweaking the default implementation: {@link DefaultSimilarity}.
- * <p>
- * Similarity determines how Lucene weights terms, and Lucene interacts with
- * this class at both <a href="#indextime">index-time</a> and 
- * <a href="#querytime">query-time</a>.
- * <p>
- * <a name="indextime"/>
- * At indexing time, the indexer calls {@link #computeNorm(FieldInvertState)}, allowing
- * the Similarity implementation to return a per-document byte for the field that will 
- * be later accessible via {@link IndexReader#norms(String)}.  Lucene makes no assumption
- * about what is in this byte, but it is most useful for encoding length normalization 
- * information.
- * <p>
- * Implementations should carefully consider how the normalization byte is encoded: while
- * Lucene's classical {@link TFIDFSimilarity} encodes a combination of index-time boost
- * and length normalization information with {@link SmallFloat}, this might not be suitable
- * for all purposes.
- * <p>
- * Many formulas require the use of average document length, which can be computed via a 
- * combination of {@link Terms#getSumTotalTermFreq()} and {@link IndexReader#maxDoc()},
- * <p>
- * Because index-time boost is handled entirely at the application level anyway,
- * an application can alternatively store the index-time boost separately using an 
- * {@link IndexDocValuesField}, and access this at query-time with 
- * {@link IndexReader#docValues(String)}.
- * <p>
- * Finally, using index-time boosts (either via folding into the normalization byte or
- * via IndexDocValues), is an inefficient way to boost the scores of different fields if the
- * boost will be the same for every document, instead the Similarity can simply take a constant
- * boost parameter <i>C</i>, and the SimilarityProvider can return different instances with
- * different boosts depending upon field name.
- * <p>
- * <a name="querytime"/>
- * At query-time, Queries interact with the Similarity via these steps:
- * <ol>
- *   <li>The {@link #computeStats(IndexSearcher, String, float, TermContext...)} method is called a single time,
- *       allowing the implementation to compute any statistics (such as IDF, average document length, etc)
- *       across <i>the entire collection</i>. The {@link TermContext}s passed in are already positioned
- *       to the terms involved with the raw statistics involved, so a Similarity can freely use any combination
- *       of term statistics without causing any additional I/O. Lucene makes no assumption about what is 
- *       stored in the returned {@link Similarity.Stats} object.
- *   <li>The query normalization process occurs a single time: {@link Similarity.Stats#getValueForNormalization()}
- *       is called for each query leaf node, {@link SimilarityProvider#queryNorm(float)} is called for the top-level
- *       query, and finally {@link Similarity.Stats#normalize(float, float)} passes down the normalization value
- *       and any top-level boosts (e.g. from enclosing {@link BooleanQuery}s).
- *   <li>For each segment in the index, the Query creates a {@link #exactDocScorer(Stats, String, IndexReader.AtomicReaderContext)}
- *       (for queries with exact frequencies such as TermQuerys and exact PhraseQueries) or a 
- *       {@link #sloppyDocScorer(Stats, String, IndexReader.AtomicReaderContext)} (for queries with sloppy frequencies such as
- *       SpanQuerys and sloppy PhraseQueries). The score() method is called for each matching document.
- * </ol>
- * <p>
- * <a name="explaintime"/>
- * When {@link IndexSearcher#explain(Query, int)} is called, queries consult the Similarity's DocScorer for an 
- * explanation of how it computed its score. The query passes in a the document id and an explanation of how the frequency
- * was computed.
- *
- * @see org.apache.lucene.index.IndexWriterConfig#setSimilarityProvider(SimilarityProvider)
- * @see IndexSearcher#setSimilarityProvider(SimilarityProvider)
- * @lucene.experimental
- */
-public abstract class Similarity {
-  /**
-   * Computes the normalization value for a field, given the accumulated
-   * state of term processing for this field (see {@link FieldInvertState}).
-   * 
-   * <p>Implementations should calculate a byte value based on the field
-   * state and then return that value.
-   *
-   * <p>Matches in longer fields are less precise, so implementations of this
-   * method usually return smaller values when <code>state.getLength()</code> is large,
-   * and larger values when <code>state.getLength()</code> is small.
-   * 
-   * @lucene.experimental
-   * 
-   * @param state current processing state for this field
-   * @return the calculated byte norm
-   */
-  public abstract byte computeNorm(FieldInvertState state);
-  
-  /**
-   * Compute any collection-level stats (e.g. IDF, average document length, etc) needed for scoring a query.
-   */
-  public abstract Stats computeStats(IndexSearcher searcher, String fieldName, float queryBoost, TermContext... termContexts) throws IOException;
-  
-  /**
-   * returns a new {@link Similarity.ExactDocScorer}.
-   */
-  public abstract ExactDocScorer exactDocScorer(Stats stats, String fieldName, AtomicReaderContext context) throws IOException;
-  
-  /**
-   * returns a new {@link Similarity.SloppyDocScorer}.
-   */
-  public abstract SloppyDocScorer sloppyDocScorer(Stats stats, String fieldName, AtomicReaderContext context) throws IOException;
-  
-  /**
-   * API for scoring exact queries such as {@link TermQuery} and 
-   * exact {@link PhraseQuery}.
-   * <p>
-   * Term frequencies are integers (the term or phrase's tf)
-   */
-  public abstract class ExactDocScorer {
-    /**
-     * Score a single document
-     * @param doc document id
-     * @param freq term frequency
-     * @return document's score
-     */
-    public abstract float score(int doc, int freq);
-    
-    /**
-     * Explain the score for a single document
-     * @param doc document id
-     * @param freq Explanation of how the term frequency was computed
-     * @return document's score
-     */
-    public Explanation explain(int doc, Explanation freq) {
-      Explanation result = new Explanation(score(doc, (int)freq.getValue()), 
-          "score(doc=" + doc + ",freq=" + freq.getValue() +"), with freq of:");
-      result.addDetail(freq);
-      return result;
-    }
-  }
-  
-  /**
-   * API for scoring "sloppy" queries such as {@link SpanQuery} and 
-   * sloppy {@link PhraseQuery}.
-   * <p>
-   * Term frequencies are floating point values.
-   */
-  public abstract class SloppyDocScorer {
-    /**
-     * Score a single document
-     * @param doc document id
-     * @param freq sloppy term frequency
-     * @return document's score
-     */
-    public abstract float score(int doc, float freq);
-
-    /** Computes the amount of a sloppy phrase match, based on an edit distance. */
-    public abstract float computeSlopFactor(int distance);
-    
-    /** Calculate a scoring factor based on the data in the payload. */
-    public abstract float computePayloadFactor(int doc, int start, int end, BytesRef payload);
-    
-    /**
-     * Explain the score for a single document
-     * @param doc document id
-     * @param freq Explanation of how the sloppy term frequency was computed
-     * @return document's score
-     */
-    public Explanation explain(int doc, Explanation freq) {
-      Explanation result = new Explanation(score(doc, freq.getValue()), 
-          "score(doc=" + doc + ",freq=" + freq.getValue() +"), with freq of:");
-      result.addDetail(freq);
-      return result;
-    }
-  }
-  
-  /** Stores the statistics for the indexed collection. This abstract
-   * implementation is empty; descendants of {@code Similarity} should
-   * subclass {@code Stats} and define the statistics they require in the
-   * subclass. Examples include idf, average field length, etc.
-   */
-  public static abstract class Stats {
-    
-    /** The value for normalization of contained query clauses (e.g. sum of squared weights).
-     * <p>
-     * NOTE: a Similarity implementation might not use any query normalization at all,
-     * its not required. However, if it wants to participate in query normalization,
-     * it can return a value here.
-     */
-    public abstract float getValueForNormalization();
-    
-    /** Assigns the query normalization factor and boost from parent queries to this.
-     * <p>
-     * NOTE: a Similarity implementation might not use this normalized value at all,
-     * its not required. However, its usually a good idea to at least incorporate 
-     * the topLevelBoost (e.g. from an outer BooleanQuery) into its score.
-     */
-    public abstract void normalize(float queryNorm, float topLevelBoost);
-  }
-}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/SimilarityProvider.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/SimilarityProvider.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/SimilarityProvider.java	2011-05-08 10:52:19.360078710 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/SimilarityProvider.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,66 +0,0 @@
-package org.apache.lucene.search;
-
-/**
- * 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.
- */
-
-/**
- * Expert: Scoring API.
- * 
- * Provides top-level scoring functions that aren't specific to a field,
- * and work across multi-field queries (such as {@link BooleanQuery}).
- * 
- * Field-specific scoring is accomplished through {@link Similarity}.
- * 
- * @lucene.experimental
- */
-public interface SimilarityProvider {
-
-  /** Computes a score factor based on the fraction of all query terms that a
-   * document contains.  This value is multiplied into scores.
-   *
-   * <p>The presence of a large portion of the query terms indicates a better
-   * match with the query, so implementations of this method usually return
-   * larger values when the ratio between these parameters is large and smaller
-   * values when the ratio between them is small.
-   *
-   * @param overlap the number of query terms matched in the document
-   * @param maxOverlap the total number of terms in the query
-   * @return a score factor based on term overlap with the query
-   */
-  public abstract float coord(int overlap, int maxOverlap);
-  
-  /** Computes the normalization value for a query given the sum of the squared
-   * weights of each of the query terms.  This value is multiplied into the
-   * weight of each query term. While the classic query normalization factor is
-   * computed as 1/sqrt(sumOfSquaredWeights), other implementations might
-   * completely ignore sumOfSquaredWeights (ie return 1).
-   *
-   * <p>This does not affect ranking, but the default implementation does make scores
-   * from different queries more comparable than they would be by eliminating the
-   * magnitude of the Query vector as a factor in the score.
-   *
-   * @param sumOfSquaredWeights the sum of the squares of query term weights
-   * @return a normalization factor for query weights
-   */
-  public abstract float queryNorm(float sumOfSquaredWeights);
-  
-  /** Returns a {@link Similarity} for scoring a field
-   * @param field field name.
-   * @return a field-specific Similarity.
-   */
-  public abstract Similarity get(String field);
-}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/SloppyPhraseScorer.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/SloppyPhraseScorer.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/SloppyPhraseScorer.java	2011-09-08 17:01:39.466036272 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/SloppyPhraseScorer.java	2011-09-08 12:56:46.716030847 -0400
@@ -20,6 +20,8 @@
 import java.io.IOException;
 import java.util.LinkedHashSet;
 
+import org.apache.lucene.search.similarities.Similarity;
+
 final class SloppyPhraseScorer extends PhraseScorer {
     private int slop;
     private PhrasePositions repeats[];


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/spans/SpanScorer.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/spans/SpanScorer.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/spans/SpanScorer.java	2011-07-17 06:27:33.738948135 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/spans/SpanScorer.java	2011-08-23 08:43:39.731460295 -0400
@@ -20,10 +20,10 @@
 import java.io.IOException;
 
 import org.apache.lucene.search.Explanation;
-import org.apache.lucene.search.TFIDFSimilarity;
 import org.apache.lucene.search.Weight;
 import org.apache.lucene.search.Scorer;
-import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.TFIDFSimilarity;
 
 /**
  * Public for extension only.


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/spans/SpanWeight.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/spans/SpanWeight.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/spans/SpanWeight.java	2011-07-17 06:27:33.738948135 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/spans/SpanWeight.java	2011-08-23 08:43:39.731460295 -0400
@@ -21,7 +21,8 @@
 import org.apache.lucene.index.IndexReader.ReaderContext;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.*;
-import org.apache.lucene.search.Similarity.SloppyDocScorer;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.Similarity.SloppyDocScorer;
 import org.apache.lucene.util.TermContext;
 
 import java.io.IOException;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/TermQuery.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/TermQuery.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/TermQuery.java	2011-08-20 13:35:07.911460633 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/TermQuery.java	2011-08-23 09:44:48.421460290 -0400
@@ -28,7 +28,8 @@
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.IndexReader.ReaderContext;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.search.Similarity.ExactDocScorer;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.Similarity.ExactDocScorer;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.TermContext;
 import org.apache.lucene.util.ReaderUtil;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/TermScorer.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/TermScorer.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/TermScorer.java	2011-08-20 13:35:07.931460633 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/TermScorer.java	2011-08-23 09:44:50.111460290 -0400
@@ -20,6 +20,7 @@
 import java.io.IOException;
 
 import org.apache.lucene.index.DocsEnum;
+import org.apache.lucene.search.similarities.Similarity;
 
 /** Expert: A <code>Scorer</code> for documents matching a <code>Term</code>.
  */


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/TFIDFSimilarity.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/TFIDFSimilarity.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/TFIDFSimilarity.java	2011-08-29 12:22:46.711459551 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/TFIDFSimilarity.java	1969-12-31 19:00:00.000000000 -0500
@@ -1,863 +0,0 @@
-package org.apache.lucene.search;
-
-/**
- * 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.
- */
-
-
-import java.io.IOException;
-
-import org.apache.lucene.index.IndexReader.AtomicReaderContext;
-import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.TermContext;
-import org.apache.lucene.util.SmallFloat;
-
-
-/**
- * Implementation of {@link Similarity} with the Vector Space Model.
- * <p>
- * Expert: Scoring API.
- * <p>TFIDFSimilarity defines the components of Lucene scoring.
- * Overriding computation of these components is a convenient
- * way to alter Lucene scoring.
- *
- * <p>Suggested reading:
- * <a href="http://nlp.stanford.edu/IR-book/html/htmledition/queries-as-vectors-1.html">
- * Introduction To Information Retrieval, Chapter 6</a>.
- *
- * <p>The following describes how Lucene scoring evolves from
- * underlying information retrieval models to (efficient) implementation.
- * We first brief on <i>VSM Score</i>, 
- * then derive from it <i>Lucene's Conceptual Scoring Formula</i>,
- * from which, finally, evolves <i>Lucene's Practical Scoring Function</i> 
- * (the latter is connected directly with Lucene classes and methods).    
- *
- * <p>Lucene combines
- * <a href="http://en.wikipedia.org/wiki/Standard_Boolean_model">
- * Boolean model (BM) of Information Retrieval</a>
- * with
- * <a href="http://en.wikipedia.org/wiki/Vector_Space_Model">
- * Vector Space Model (VSM) of Information Retrieval</a> -
- * documents "approved" by BM are scored by VSM.
- *
- * <p>In VSM, documents and queries are represented as
- * weighted vectors in a multi-dimensional space,
- * where each distinct index term is a dimension,
- * and weights are
- * <a href="http://en.wikipedia.org/wiki/Tfidf">Tf-idf</a> values.
- *
- * <p>VSM does not require weights to be <i>Tf-idf</i> values,
- * but <i>Tf-idf</i> values are believed to produce search results of high quality,
- * and so Lucene is using <i>Tf-idf</i>.
- * <i>Tf</i> and <i>Idf</i> are described in more detail below,
- * but for now, for completion, let's just say that
- * for given term <i>t</i> and document (or query) <i>x</i>,
- * <i>Tf(t,x)</i> varies with the number of occurrences of term <i>t</i> in <i>x</i>
- * (when one increases so does the other) and
- * <i>idf(t)</i> similarly varies with the inverse of the
- * number of index documents containing term <i>t</i>.
- *
- * <p><i>VSM score</i> of document <i>d</i> for query <i>q</i> is the
- * <a href="http://en.wikipedia.org/wiki/Cosine_similarity">
- * Cosine Similarity</a>
- * of the weighted query vectors <i>V(q)</i> and <i>V(d)</i>:
- *
- *  <br>&nbsp;<br>
- *  <table cellpadding="2" cellspacing="2" border="0" align="center">
- *    <tr><td>
- *    <table cellpadding="1" cellspacing="0" border="1" align="center">
- *      <tr><td>
- *      <table cellpadding="2" cellspacing="2" border="0" align="center">
- *        <tr>
- *          <td valign="middle" align="right" rowspan="1">
- *            cosine-similarity(q,d) &nbsp; = &nbsp;
- *          </td>
- *          <td valign="middle" align="center">
- *            <table>
- *               <tr><td align="center"><small>V(q)&nbsp;&middot;&nbsp;V(d)</small></td></tr>
- *               <tr><td align="center">&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;</td></tr>
- *               <tr><td align="center"><small>|V(q)|&nbsp;|V(d)|</small></td></tr>
- *            </table>
- *          </td>
- *        </tr>
- *      </table>
- *      </td></tr>
- *    </table>
- *    </td></tr>
- *    <tr><td>
- *    <center><font=-1><u>VSM Score</u></font></center>
- *    </td></tr>
- *  </table>
- *  <br>&nbsp;<br>
- *   
- *
- * Where <i>V(q)</i> &middot; <i>V(d)</i> is the
- * <a href="http://en.wikipedia.org/wiki/Dot_product">dot product</a>
- * of the weighted vectors,
- * and <i>|V(q)|</i> and <i>|V(d)|</i> are their
- * <a href="http://en.wikipedia.org/wiki/Euclidean_norm#Euclidean_norm">Euclidean norms</a>.
- *
- * <p>Note: the above equation can be viewed as the dot product of
- * the normalized weighted vectors, in the sense that dividing
- * <i>V(q)</i> by its euclidean norm is normalizing it to a unit vector.
- *
- * <p>Lucene refines <i>VSM score</i> for both search quality and usability:
- * <ul>
- *  <li>Normalizing <i>V(d)</i> to the unit vector is known to be problematic in that 
- *  it removes all document length information. 
- *  For some documents removing this info is probably ok, 
- *  e.g. a document made by duplicating a certain paragraph <i>10</i> times,
- *  especially if that paragraph is made of distinct terms. 
- *  But for a document which contains no duplicated paragraphs, 
- *  this might be wrong. 
- *  To avoid this problem, a different document length normalization 
- *  factor is used, which normalizes to a vector equal to or larger 
- *  than the unit vector: <i>doc-len-norm(d)</i>.
- *  </li>
- *
- *  <li>At indexing, users can specify that certain documents are more
- *  important than others, by assigning a document boost.
- *  For this, the score of each document is also multiplied by its boost value
- *  <i>doc-boost(d)</i>.
- *  </li>
- *
- *  <li>Lucene is field based, hence each query term applies to a single
- *  field, document length normalization is by the length of the certain field,
- *  and in addition to document boost there are also document fields boosts.
- *  </li>
- *
- *  <li>The same field can be added to a document during indexing several times,
- *  and so the boost of that field is the multiplication of the boosts of
- *  the separate additions (or parts) of that field within the document.
- *  </li>
- *
- *  <li>At search time users can specify boosts to each query, sub-query, and
- *  each query term, hence the contribution of a query term to the score of
- *  a document is multiplied by the boost of that query term <i>query-boost(q)</i>.
- *  </li>
- *
- *  <li>A document may match a multi term query without containing all
- *  the terms of that query (this is correct for some of the queries),
- *  and users can further reward documents matching more query terms
- *  through a coordination factor, which is usually larger when
- *  more terms are matched: <i>coord-factor(q,d)</i>.
- *  </li>
- * </ul>
- *
- * <p>Under the simplifying assumption of a single field in the index,
- * we get <i>Lucene's Conceptual scoring formula</i>:
- *
- *  <br>&nbsp;<br>
- *  <table cellpadding="2" cellspacing="2" border="0" align="center">
- *    <tr><td>
- *    <table cellpadding="1" cellspacing="0" border="1" align="center">
- *      <tr><td>
- *      <table cellpadding="2" cellspacing="2" border="0" align="center">
- *        <tr>
- *          <td valign="middle" align="right" rowspan="1">
- *            score(q,d) &nbsp; = &nbsp;
- *            <font color="#FF9933">coord-factor(q,d)</font> &middot; &nbsp;
- *            <font color="#CCCC00">query-boost(q)</font> &middot; &nbsp;
- *          </td>
- *          <td valign="middle" align="center">
- *            <table>
- *               <tr><td align="center"><small><font color="#993399">V(q)&nbsp;&middot;&nbsp;V(d)</font></small></td></tr>
- *               <tr><td align="center">&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;</td></tr>
- *               <tr><td align="center"><small><font color="#FF33CC">|V(q)|</font></small></td></tr>
- *            </table>
- *          </td>
- *          <td valign="middle" align="right" rowspan="1">
- *            &nbsp; &middot; &nbsp; <font color="#3399FF">doc-len-norm(d)</font>
- *            &nbsp; &middot; &nbsp; <font color="#3399FF">doc-boost(d)</font>
- *          </td>
- *        </tr>
- *      </table>
- *      </td></tr>
- *    </table>
- *    </td></tr>
- *    <tr><td>
- *    <center><font=-1><u>Lucene Conceptual Scoring Formula</u></font></center>
- *    </td></tr>
- *  </table>
- *  <br>&nbsp;<br>
- *
- * <p>The conceptual formula is a simplification in the sense that (1) terms and documents
- * are fielded and (2) boosts are usually per query term rather than per query.
- *
- * <p>We now describe how Lucene implements this conceptual scoring formula, and
- * derive from it <i>Lucene's Practical Scoring Function</i>.
- *  
- * <p>For efficient score computation some scoring components
- * are computed and aggregated in advance:
- *
- * <ul>
- *  <li><i>Query-boost</i> for the query (actually for each query term)
- *  is known when search starts.
- *  </li>
- *
- *  <li>Query Euclidean norm <i>|V(q)|</i> can be computed when search starts,
- *  as it is independent of the document being scored.
- *  From search optimization perspective, it is a valid question
- *  why bother to normalize the query at all, because all
- *  scored documents will be multiplied by the same <i>|V(q)|</i>,
- *  and hence documents ranks (their order by score) will not
- *  be affected by this normalization.
- *  There are two good reasons to keep this normalization:
- *  <ul>
- *   <li>Recall that
- *   <a href="http://en.wikipedia.org/wiki/Cosine_similarity">
- *   Cosine Similarity</a> can be used find how similar
- *   two documents are. One can use Lucene for e.g.
- *   clustering, and use a document as a query to compute
- *   its similarity to other documents.
- *   In this use case it is important that the score of document <i>d3</i>
- *   for query <i>d1</i> is comparable to the score of document <i>d3</i>
- *   for query <i>d2</i>. In other words, scores of a document for two
- *   distinct queries should be comparable.
- *   There are other applications that may require this.
- *   And this is exactly what normalizing the query vector <i>V(q)</i>
- *   provides: comparability (to a certain extent) of two or more queries.
- *   </li>
- *
- *   <li>Applying query normalization on the scores helps to keep the
- *   scores around the unit vector, hence preventing loss of score data
- *   because of floating point precision limitations.
- *   </li>
- *  </ul>
- *  </li>
- *
- *  <li>Document length norm <i>doc-len-norm(d)</i> and document
- *  boost <i>doc-boost(d)</i> are known at indexing time.
- *  They are computed in advance and their multiplication
- *  is saved as a single value in the index: <i>norm(d)</i>.
- *  (In the equations below, <i>norm(t in d)</i> means <i>norm(field(t) in doc d)</i>
- *  where <i>field(t)</i> is the field associated with term <i>t</i>.)
- *  </li>
- * </ul>
- *
- * <p><i>Lucene's Practical Scoring Function</i> is derived from the above.
- * The color codes demonstrate how it relates
- * to those of the <i>conceptual</i> formula:
- *
- * <P>
- * <table cellpadding="2" cellspacing="2" border="0" align="center">
- *  <tr><td>
- *  <table cellpadding="" cellspacing="2" border="2" align="center">
- *  <tr><td>
- *   <table cellpadding="2" cellspacing="2" border="0" align="center">
- *   <tr>
- *     <td valign="middle" align="right" rowspan="1">
- *       score(q,d) &nbsp; = &nbsp;
- *       <A HREF="#formula_coord"><font color="#FF9933">coord(q,d)</font></A> &nbsp;&middot;&nbsp;
- *       <A HREF="#formula_queryNorm"><font color="#FF33CC">queryNorm(q)</font></A> &nbsp;&middot;&nbsp;
- *     </td>
- *     <td valign="bottom" align="center" rowspan="1">
- *       <big><big><big>&sum;</big></big></big>
- *     </td>
- *     <td valign="middle" align="right" rowspan="1">
- *       <big><big>(</big></big>
- *       <A HREF="#formula_tf"><font color="#993399">tf(t in d)</font></A> &nbsp;&middot;&nbsp;
- *       <A HREF="#formula_idf"><font color="#993399">idf(t)</font></A><sup>2</sup> &nbsp;&middot;&nbsp;
- *       <A HREF="#formula_termBoost"><font color="#CCCC00">t.getBoost()</font></A>&nbsp;&middot;&nbsp;
- *       <A HREF="#formula_norm"><font color="#3399FF">norm(t,d)</font></A>
- *       <big><big>)</big></big>
- *     </td>
- *   </tr>
- *   <tr valigh="top">
- *    <td></td>
- *    <td align="center"><small>t in q</small></td>
- *    <td></td>
- *   </tr>
- *   </table>
- *  </td></tr>
- *  </table>
- * </td></tr>
- * <tr><td>
- *  <center><font=-1><u>Lucene Practical Scoring Function</u></font></center>
- * </td></tr>
- * </table>
- *
- * <p> where
- * <ol>
- *    <li>
- *      <A NAME="formula_tf"></A>
- *      <b><i>tf(t in d)</i></b>
- *      correlates to the term's <i>frequency</i>,
- *      defined as the number of times term <i>t</i> appears in the currently scored document <i>d</i>.
- *      Documents that have more occurrences of a given term receive a higher score.
- *      Note that <i>tf(t in q)</i> is assumed to be <i>1</i> and therefore it does not appear in this equation,
- *      However if a query contains twice the same term, there will be
- *      two term-queries with that same term and hence the computation would still be correct (although
- *      not very efficient).
- *      The default computation for <i>tf(t in d)</i> in
- *      {@link org.apache.lucene.search.DefaultSimilarity#tf(float) DefaultSimilarity} is:
- *
- *      <br>&nbsp;<br>
- *      <table cellpadding="2" cellspacing="2" border="0" align="center">
- *        <tr>
- *          <td valign="middle" align="right" rowspan="1">
- *            {@link org.apache.lucene.search.DefaultSimilarity#tf(float) tf(t in d)} &nbsp; = &nbsp;
- *          </td>
- *          <td valign="top" align="center" rowspan="1">
- *               frequency<sup><big>&frac12;</big></sup>
- *          </td>
- *        </tr>
- *      </table>
- *      <br>&nbsp;<br>
- *    </li>
- *
- *    <li>
- *      <A NAME="formula_idf"></A>
- *      <b><i>idf(t)</i></b> stands for Inverse Document Frequency. This value
- *      correlates to the inverse of <i>docFreq</i>
- *      (the number of documents in which the term <i>t</i> appears).
- *      This means rarer terms give higher contribution to the total score.
- *      <i>idf(t)</i> appears for <i>t</i> in both the query and the document,
- *      hence it is squared in the equation.
- *      The default computation for <i>idf(t)</i> in
- *      {@link org.apache.lucene.search.DefaultSimilarity#idf(int, int) DefaultSimilarity} is:
- *
- *      <br>&nbsp;<br>
- *      <table cellpadding="2" cellspacing="2" border="0" align="center">
- *        <tr>
- *          <td valign="middle" align="right">
- *            {@link org.apache.lucene.search.DefaultSimilarity#idf(int, int) idf(t)}&nbsp; = &nbsp;
- *          </td>
- *          <td valign="middle" align="center">
- *            1 + log <big>(</big>
- *          </td>
- *          <td valign="middle" align="center">
- *            <table>
- *               <tr><td align="center"><small>numDocs</small></td></tr>
- *               <tr><td align="center">&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;</td></tr>
- *               <tr><td align="center"><small>docFreq+1</small></td></tr>
- *            </table>
- *          </td>
- *          <td valign="middle" align="center">
- *            <big>)</big>
- *          </td>
- *        </tr>
- *      </table>
- *      <br>&nbsp;<br>
- *    </li>
- *
- *    <li>
- *      <A NAME="formula_coord"></A>
- *      <b><i>coord(q,d)</i></b>
- *      is a score factor based on how many of the query terms are found in the specified document.
- *      Typically, a document that contains more of the query's terms will receive a higher score
- *      than another document with fewer query terms.
- *      This is a search time factor computed in
- *      {@link SimilarityProvider#coord(int, int) coord(q,d)}
- *      by the SimilarityProvider in effect at search time.
- *      <br>&nbsp;<br>
- *    </li>
- *
- *    <li><b>
- *      <A NAME="formula_queryNorm"></A>
- *      <i>queryNorm(q)</i>
- *      </b>
- *      is a normalizing factor used to make scores between queries comparable.
- *      This factor does not affect document ranking (since all ranked documents are multiplied by the same factor),
- *      but rather just attempts to make scores from different queries (or even different indexes) comparable.
- *      This is a search time factor computed by the Similarity in effect at search time.
- *
- *      The default computation in
- *      {@link org.apache.lucene.search.DefaultSimilarityProvider#queryNorm(float) DefaultSimilarityProvider}
- *      produces a <a href="http://en.wikipedia.org/wiki/Euclidean_norm#Euclidean_norm">Euclidean norm</a>:
- *      <br>&nbsp;<br>
- *      <table cellpadding="1" cellspacing="0" border="0" align="center">
- *        <tr>
- *          <td valign="middle" align="right" rowspan="1">
- *            queryNorm(q)  &nbsp; = &nbsp;
- *            {@link org.apache.lucene.search.DefaultSimilarityProvider#queryNorm(float) queryNorm(sumOfSquaredWeights)}
- *            &nbsp; = &nbsp;
- *          </td>
- *          <td valign="middle" align="center" rowspan="1">
- *            <table>
- *               <tr><td align="center"><big>1</big></td></tr>
- *               <tr><td align="center"><big>
- *                  &ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;&ndash;
- *               </big></td></tr>
- *               <tr><td align="center">sumOfSquaredWeights<sup><big>&frac12;</big></sup></td></tr>
- *            </table>
- *          </td>
- *        </tr>
- *      </table>
- *      <br>&nbsp;<br>
- *
- *      The sum of squared weights (of the query terms) is
- *      computed by the query {@link org.apache.lucene.search.Weight} object.
- *      For example, a {@link org.apache.lucene.search.BooleanQuery}
- *      computes this value as:
- *
- *      <br>&nbsp;<br>
- *      <table cellpadding="1" cellspacing="0" border="0"n align="center">
- *        <tr>
- *          <td valign="middle" align="right" rowspan="1">
- *            {@link org.apache.lucene.search.Weight#getValueForNormalization() sumOfSquaredWeights} &nbsp; = &nbsp;
- *            {@link org.apache.lucene.search.Query#getBoost() q.getBoost()} <sup><big>2</big></sup>
- *            &nbsp;&middot;&nbsp;
- *          </td>
- *          <td valign="bottom" align="center" rowspan="1">
- *            <big><big><big>&sum;</big></big></big>
- *          </td>
- *          <td valign="middle" align="right" rowspan="1">
- *            <big><big>(</big></big>
- *            <A HREF="#formula_idf">idf(t)</A> &nbsp;&middot;&nbsp;
- *            <A HREF="#formula_termBoost">t.getBoost()</A>
- *            <big><big>) <sup>2</sup> </big></big>
- *          </td>
- *        </tr>
- *        <tr valigh="top">
- *          <td></td>
- *          <td align="center"><small>t in q</small></td>
- *          <td></td>
- *        </tr>
- *      </table>
- *      <br>&nbsp;<br>
- *
- *    </li>
- *
- *    <li>
- *      <A NAME="formula_termBoost"></A>
- *      <b><i>t.getBoost()</i></b>
- *      is a search time boost of term <i>t</i> in the query <i>q</i> as
- *      specified in the query text
- *      (see <A HREF="../../../../../../queryparsersyntax.html#Boosting a Term">query syntax</A>),
- *      or as set by application calls to
- *      {@link org.apache.lucene.search.Query#setBoost(float) setBoost()}.
- *      Notice that there is really no direct API for accessing a boost of one term in a multi term query,
- *      but rather multi terms are represented in a query as multi
- *      {@link org.apache.lucene.search.TermQuery TermQuery} objects,
- *      and so the boost of a term in the query is accessible by calling the sub-query
- *      {@link org.apache.lucene.search.Query#getBoost() getBoost()}.
- *      <br>&nbsp;<br>
- *    </li>
- *
- *    <li>
- *      <A NAME="formula_norm"></A>
- *      <b><i>norm(t,d)</i></b> encapsulates a few (indexing time) boost and length factors:
- *
- *      <ul>
- *        <li><b>Field boost</b> - set by calling
- *        {@link org.apache.lucene.document.Field#setBoost(float) field.setBoost()}
- *        before adding the field to a document.
- *        </li>
- *        <li><b>lengthNorm</b> - computed
- *        when the document is added to the index in accordance with the number of tokens
- *        of this field in the document, so that shorter fields contribute more to the score.
- *        LengthNorm is computed by the Similarity class in effect at indexing.
- *        </li>
- *      </ul>
- *      The {@link #computeNorm} method is responsible for
- *      combining all of these factors into a single float.
- *
- *      <p>
- *      When a document is added to the index, all the above factors are multiplied.
- *      If the document has multiple fields with the same name, all their boosts are multiplied together:
- *
- *      <br>&nbsp;<br>
- *      <table cellpadding="1" cellspacing="0" border="0"n align="center">
- *        <tr>
- *          <td valign="middle" align="right" rowspan="1">
- *            norm(t,d) &nbsp; = &nbsp;
- *            lengthNorm
- *            &nbsp;&middot;&nbsp;
- *          </td>
- *          <td valign="bottom" align="center" rowspan="1">
- *            <big><big><big>&prod;</big></big></big>
- *          </td>
- *          <td valign="middle" align="right" rowspan="1">
- *            {@link org.apache.lucene.index.IndexableField#boost() f.boost}()
- *          </td>
- *        </tr>
- *        <tr valigh="top">
- *          <td></td>
- *          <td align="center"><small>field <i><b>f</b></i> in <i>d</i> named as <i><b>t</b></i></small></td>
- *          <td></td>
- *        </tr>
- *      </table>
- *      <br>&nbsp;<br>
- *      However the resulted <i>norm</i> value is {@link #encodeNormValue(float) encoded} as a single byte
- *      before being stored.
- *      At search time, the norm byte value is read from the index
- *      {@link org.apache.lucene.store.Directory directory} and
- *      {@link #decodeNormValue(byte) decoded} back to a float <i>norm</i> value.
- *      This encoding/decoding, while reducing index size, comes with the price of
- *      precision loss - it is not guaranteed that <i>decode(encode(x)) = x</i>.
- *      For instance, <i>decode(encode(0.89)) = 0.75</i>.
- *      <br>&nbsp;<br>
- *      Compression of norm values to a single byte saves memory at search time, 
- *      because once a field is referenced at search time, its norms - for 
- *      all documents - are maintained in memory.
- *      <br>&nbsp;<br>
- *      The rationale supporting such lossy compression of norm values is that
- *      given the difficulty (and inaccuracy) of users to express their true information
- *      need by a query, only big differences matter.
- *      <br>&nbsp;<br>
- *      Last, note that search time is too late to modify this <i>norm</i> part of scoring, e.g. by
- *      using a different {@link Similarity} for search.
- *      <br>&nbsp;<br>
- *    </li>
- * </ol>
- *
- * @see org.apache.lucene.index.IndexWriterConfig#setSimilarityProvider(SimilarityProvider)
- * @see IndexSearcher#setSimilarityProvider(SimilarityProvider)
- */
-public abstract class TFIDFSimilarity extends Similarity {
-  
-  /** Computes a score factor based on a term or phrase's frequency in a
-   * document.  This value is multiplied by the {@link #idf(int, int)}
-   * factor for each term in the query and these products are then summed to
-   * form the initial score for a document.
-   *
-   * <p>Terms and phrases repeated in a document indicate the topic of the
-   * document, so implementations of this method usually return larger values
-   * when <code>freq</code> is large, and smaller values when <code>freq</code>
-   * is small.
-   *
-   * <p>The default implementation calls {@link #tf(float)}.
-   *
-   * @param freq the frequency of a term within a document
-   * @return a score factor based on a term's within-document frequency
-   */
-  public float tf(int freq) {
-    return tf((float)freq);
-  }
-
-  /** Computes a score factor based on a term or phrase's frequency in a
-   * document.  This value is multiplied by the {@link #idf(int, int)}
-   * factor for each term in the query and these products are then summed to
-   * form the initial score for a document.
-   *
-   * <p>Terms and phrases repeated in a document indicate the topic of the
-   * document, so implementations of this method usually return larger values
-   * when <code>freq</code> is large, and smaller values when <code>freq</code>
-   * is small.
-   *
-   * @param freq the frequency of a term within a document
-   * @return a score factor based on a term's within-document frequency
-   */
-  public abstract float tf(float freq);
-
-  /**
-   * Computes a score factor for a simple term and returns an explanation
-   * for that score factor.
-   * 
-   * <p>
-   * The default implementation uses:
-   * 
-   * <pre>
-   * idf(docFreq, searcher.maxDoc());
-   * </pre>
-   * 
-   * Note that {@link IndexSearcher#maxDoc()} is used instead of
-   * {@link org.apache.lucene.index.IndexReader#numDocs() IndexReader#numDocs()} because also 
-   * {@link IndexSearcher#docFreq(Term)} is used, and when the latter 
-   * is inaccurate, so is {@link IndexSearcher#maxDoc()}, and in the same direction.
-   * In addition, {@link IndexSearcher#maxDoc()} is more efficient to compute
-   *   
-   * @param stats statistics of the term in question
-   * @param searcher the document collection being searched
-   * @return an Explain object that includes both an idf score factor 
-             and an explanation for the term.
-   * @throws IOException
-   */
-  public Explanation idfExplain(TermContext stats, final IndexSearcher searcher) throws IOException {
-    final int df = stats.docFreq();
-    final int max = searcher.maxDoc();
-    final float idf = idf(df, max);
-    return new Explanation(idf, "idf(docFreq=" + df + ", maxDocs=" + max + ")");
-  }
-
-  /**
-   * Computes a score factor for a phrase.
-   * 
-   * <p>
-   * The default implementation sums the idf factor for
-   * each term in the phrase.
-   * 
-   * @param stats statistics of the terms in the phrase
-   * @param searcher the document collection being searched
-   * @return an Explain object that includes both an idf 
-   *         score factor for the phrase and an explanation 
-   *         for each term.
-   * @throws IOException
-   */
-  public Explanation idfExplain(final TermContext stats[], IndexSearcher searcher) throws IOException {
-    final int max = searcher.maxDoc();
-    float idf = 0.0f;
-    final Explanation exp = new Explanation();
-    exp.setDescription("idf(), sum of:");
-    for (final TermContext stat : stats ) {
-      final int df = stat.docFreq();
-      final float termIdf = idf(df, max);
-      exp.addDetail(new Explanation(termIdf, "idf(docFreq=" + df + ", maxDocs=" + max + ")"));
-      idf += termIdf;
-    }
-    exp.setValue(idf);
-    return exp;
-  }
-
-  /** Computes a score factor based on a term's document frequency (the number
-   * of documents which contain the term).  This value is multiplied by the
-   * {@link #tf(int)} factor for each term in the query and these products are
-   * then summed to form the initial score for a document.
-   *
-   * <p>Terms that occur in fewer documents are better indicators of topic, so
-   * implementations of this method usually return larger values for rare terms,
-   * and smaller values for common terms.
-   *
-   * @param docFreq the number of documents which contain the term
-   * @param numDocs the total number of documents in the collection
-   * @return a score factor based on the term's document frequency
-   */
-  public abstract float idf(int docFreq, int numDocs);
-
-  /** Cache of decoded bytes. */
-  private static final float[] NORM_TABLE = new float[256];
-
-  static {
-    for (int i = 0; i < 256; i++)
-      NORM_TABLE[i] = SmallFloat.byte315ToFloat((byte)i);
-  }
-
-  /** Decodes a normalization factor stored in an index.
-   * @see #encodeNormValue(float)
-   */
-  public float decodeNormValue(byte b) {
-    return NORM_TABLE[b & 0xFF];  // & 0xFF maps negative bytes to positive above 127
-  }
-
-  /** Encodes a normalization factor for storage in an index.
-  *
-  * <p>The encoding uses a three-bit mantissa, a five-bit exponent, and
-  * the zero-exponent point at 15, thus
-  * representing values from around 7x10^9 to 2x10^-9 with about one
-  * significant decimal digit of accuracy.  Zero is also represented.
-  * Negative numbers are rounded up to zero.  Values too large to represent
-  * are rounded down to the largest representable value.  Positive values too
-  * small to represent are rounded up to the smallest positive representable
-  * value.
-  * @see org.apache.lucene.document.Field#setBoost(float)
-  * @see org.apache.lucene.util.SmallFloat
-  */
-  public byte encodeNormValue(float f) {
-    return SmallFloat.floatToByte315(f);
-  }
- 
-  /** Computes the amount of a sloppy phrase match, based on an edit distance.
-   * This value is summed for each sloppy phrase match in a document to form
-   * the frequency to be used in scoring instead of the exact term count.
-   *
-   * <p>A phrase match with a small edit distance to a document passage more
-   * closely matches the document, so implementations of this method usually
-   * return larger values when the edit distance is small and smaller values
-   * when it is large.
-   *
-   * @see PhraseQuery#setSlop(int)
-   * @param distance the edit distance of this sloppy phrase match
-   * @return the frequency increment for this match
-   */
-  public abstract float sloppyFreq(int distance);
-
-  /**
-   * Calculate a scoring factor based on the data in the payload.  Implementations
-   * are responsible for interpreting what is in the payload.  Lucene makes no assumptions about
-   * what is in the byte array.
-   *
-   * @param doc The docId currently being scored.
-   * @param start The start position of the payload
-   * @param end The end position of the payload
-   * @param payload The payload byte array to be scored
-   * @return An implementation dependent float to be used as a scoring factor
-   */
-  public abstract float scorePayload(int doc, int start, int end, BytesRef payload);
-
-  @Override
-  public final Stats computeStats(IndexSearcher searcher, String fieldName, float queryBoost,
-      TermContext... termContexts) throws IOException {
-    final Explanation idf = termContexts.length == 1
-    ? idfExplain(termContexts[0], searcher)
-    : idfExplain(termContexts, searcher);
-    return new IDFStats(idf, queryBoost);
-  }
-
-  @Override
-  public final ExactDocScorer exactDocScorer(Stats stats, String fieldName, AtomicReaderContext context) throws IOException {
-    return new ExactTFIDFDocScorer((IDFStats)stats, context.reader.norms(fieldName));
-  }
-
-  @Override
-  public final SloppyDocScorer sloppyDocScorer(Stats stats, String fieldName, AtomicReaderContext context) throws IOException {
-    return new SloppyTFIDFDocScorer((IDFStats)stats, context.reader.norms(fieldName));
-  }
-  
-  // TODO: we can specialize these for omitNorms up front, but we should test that it doesn't confuse stupid hotspot.
-
-  private final class ExactTFIDFDocScorer extends ExactDocScorer {
-    private final IDFStats stats;
-    private final float weightValue;
-    private final byte[] norms;
-    private static final int SCORE_CACHE_SIZE = 32;
-    private float[] scoreCache = new float[SCORE_CACHE_SIZE];
-    
-    ExactTFIDFDocScorer(IDFStats stats, byte norms[]) {
-      this.stats = stats;
-      this.weightValue = stats.value;
-      this.norms = norms;
-      for (int i = 0; i < SCORE_CACHE_SIZE; i++)
-        scoreCache[i] = tf(i) * weightValue;
-    }
-    
-    @Override
-    public float score(int doc, int freq) {
-      final float raw =                                // compute tf(f)*weight
-        freq < SCORE_CACHE_SIZE                        // check cache
-        ? scoreCache[freq]                             // cache hit
-        : tf(freq)*weightValue;        // cache miss
-
-      return norms == null ? raw : raw * decodeNormValue(norms[doc]); // normalize for field
-    }
-
-    @Override
-    public Explanation explain(int doc, Explanation freq) {
-      return explainScore(doc, freq, stats, norms);
-    }
-  }
-  
-  private final class SloppyTFIDFDocScorer extends SloppyDocScorer {
-    private final IDFStats stats;
-    private final float weightValue;
-    private final byte[] norms;
-    
-    SloppyTFIDFDocScorer(IDFStats stats, byte norms[]) {
-      this.stats = stats;
-      this.weightValue = stats.value;
-      this.norms = norms;
-    }
-    
-    @Override
-    public float score(int doc, float freq) {
-      final float raw = tf(freq) * weightValue; // compute tf(f)*weight
-      
-      return norms == null ? raw : raw * decodeNormValue(norms[doc]);  // normalize for field
-    }
-    
-    @Override
-    public float computeSlopFactor(int distance) {
-      return sloppyFreq(distance);
-    }
-
-    @Override
-    public float computePayloadFactor(int doc, int start, int end, BytesRef payload) {
-      return scorePayload(doc, start, end, payload);
-    }
-
-    @Override
-    public Explanation explain(int doc, Explanation freq) {
-      return explainScore(doc, freq, stats, norms);
-    }
-  }
-  
-  /** Collection statistics for the TF-IDF model. The only statistic of interest
-   * to this model is idf. */
-  private static class IDFStats extends Stats {
-    /** The idf and its explanation */
-    private final Explanation idf;
-    private float queryNorm;
-    private float queryWeight;
-    private final float queryBoost;
-    private float value;
-    
-    public IDFStats(Explanation idf, float queryBoost) {
-      // TODO: Validate?
-      this.idf = idf;
-      this.queryBoost = queryBoost;
-      this.queryWeight = idf.getValue() * queryBoost; // compute query weight
-    }
-
-    @Override
-    public float getValueForNormalization() {
-      // TODO: (sorta LUCENE-1907) make non-static class and expose this squaring via a nice method to subclasses?
-      return queryWeight * queryWeight;  // sum of squared weights
-    }
-
-    @Override
-    public void normalize(float queryNorm, float topLevelBoost) {
-      this.queryNorm = queryNorm * topLevelBoost;
-      queryWeight *= this.queryNorm;              // normalize query weight
-      value = queryWeight * idf.getValue();         // idf for document
-    }
-  }
-  
-  private Explanation explainScore(int doc, Explanation freq, IDFStats stats, byte[] norms) {
-    Explanation result = new Explanation();
-    result.setDescription("score(doc="+doc+",freq="+freq+"), product of:");
-
-    // explain query weight
-    Explanation queryExpl = new Explanation();
-    queryExpl.setDescription("queryWeight, product of:");
-
-    Explanation boostExpl = new Explanation(stats.queryBoost, "boost");
-    if (stats.queryBoost != 1.0f)
-      queryExpl.addDetail(boostExpl);
-    queryExpl.addDetail(stats.idf);
-
-    Explanation queryNormExpl = new Explanation(stats.queryNorm,"queryNorm");
-    queryExpl.addDetail(queryNormExpl);
-
-    queryExpl.setValue(boostExpl.getValue() *
-                       stats.idf.getValue() *
-                       queryNormExpl.getValue());
-
-    result.addDetail(queryExpl);
-
-    // explain field weight
-    Explanation fieldExpl = new Explanation();
-    fieldExpl.setDescription("fieldWeight in "+doc+
-                             ", product of:");
-
-    Explanation tfExplanation = new Explanation();
-    tfExplanation.setValue(tf(freq.getValue()));
-    tfExplanation.setDescription("tf(freq="+freq.getValue()+"), with freq of:");
-    tfExplanation.addDetail(freq);
-    fieldExpl.addDetail(tfExplanation);
-    fieldExpl.addDetail(stats.idf);
-
-    Explanation fieldNormExpl = new Explanation();
-    float fieldNorm =
-      norms!=null ? decodeNormValue(norms[doc]) : 1.0f;
-    fieldNormExpl.setValue(fieldNorm);
-    fieldNormExpl.setDescription("fieldNorm(doc="+doc+")");
-    fieldExpl.addDetail(fieldNormExpl);
-    
-    fieldExpl.setValue(tfExplanation.getValue() *
-                       stats.idf.getValue() *
-                       fieldNormExpl.getValue());
-
-    result.addDetail(fieldExpl);
-    
-    // combine them
-    result.setValue(queryExpl.getValue() * fieldExpl.getValue());
-
-    if (queryExpl.getValue() == 1.0f)
-      return fieldExpl;
-
-    return result;
-  }
-}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/Weight.java lucene-flexscoring/lucene/src/java/org/apache/lucene/search/Weight.java
--- lucene-clean-trunk/lucene/src/java/org/apache/lucene/search/Weight.java	2011-07-08 01:31:28.421820268 -0400
+++ lucene-flexscoring/lucene/src/java/org/apache/lucene/search/Weight.java	2011-08-23 08:43:39.721460295 -0400
@@ -22,6 +22,7 @@
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.IndexReader.ReaderContext;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 
 /**
  * Expert: Calculate query weights and build query scorers.


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java	2011-08-29 12:22:46.661459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java	2011-08-29 13:43:37.421459544 -0400
@@ -35,13 +35,13 @@
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
-import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.FieldCache;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.NumericRangeQuery;
 import org.apache.lucene.search.ScoreDoc;
 import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
 import org.apache.lucene.store.CompoundFileDirectory;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.RAMDirectory;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestDeletionPolicy.java lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestDeletionPolicy.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestDeletionPolicy.java	2011-08-29 12:22:46.671459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestDeletionPolicy.java	2011-08-29 13:44:09.991459544 -0400
@@ -27,11 +27,11 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
-import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.ScoreDoc;
 import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestIndexFileDeleter.java lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestIndexFileDeleter.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestIndexFileDeleter.java	2011-08-29 12:22:46.671459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestIndexFileDeleter.java	2011-08-29 13:43:54.351459544 -0400
@@ -25,7 +25,7 @@
 import org.apache.lucene.document.StringField;
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
-import org.apache.lucene.search.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
 import org.apache.lucene.store.CompoundFileDirectory;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IndexInput;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestIndexReaderClone.java lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestIndexReaderClone.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestIndexReaderClone.java	2011-08-29 12:22:46.661459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestIndexReaderClone.java	2011-08-29 13:47:38.761459544 -0400
@@ -17,7 +17,7 @@
  * limitations under the License.
  */
 
-import org.apache.lucene.search.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.TextField;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestIndexReaderCloneNorms.java lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestIndexReaderCloneNorms.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestIndexReaderCloneNorms.java	2011-08-29 12:22:46.651459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestIndexReaderCloneNorms.java	2011-08-29 13:42:58.831459544 -0400
@@ -29,10 +29,10 @@
 import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
-import org.apache.lucene.search.DefaultSimilarity;
-import org.apache.lucene.search.DefaultSimilarityProvider;
-import org.apache.lucene.search.Similarity;
-import org.apache.lucene.search.SimilarityProvider;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestIndexReader.java lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestIndexReader.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestIndexReader.java	2011-09-08 17:01:39.456036272 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestIndexReader.java	2011-09-08 12:56:42.776030847 -0400
@@ -40,9 +40,9 @@
 import org.apache.lucene.index.IndexReader.FieldOption;
 import org.apache.lucene.index.codecs.CodecProvider;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
-import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.FieldCache;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
 import org.apache.lucene.store.AlreadyClosedException;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.LockObtainFailedException;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestIndexReaderOnDiskFull.java lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestIndexReaderOnDiskFull.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestIndexReaderOnDiskFull.java	2011-08-29 12:22:46.661459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestIndexReaderOnDiskFull.java	2011-08-29 13:43:46.771459544 -0400
@@ -23,10 +23,11 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.StringField;
 import org.apache.lucene.document.TextField;
-import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.ScoreDoc;
 import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.store.MockDirectoryWrapper;
 import org.apache.lucene.store.RAMDirectory;
 import org.apache.lucene.util.LuceneTestCase;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestIndexReaderReopen.java lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestIndexReaderReopen.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestIndexReaderReopen.java	2011-08-29 12:22:46.671459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestIndexReaderReopen.java	2011-08-29 13:44:03.351459544 -0400
@@ -35,11 +35,13 @@
 import org.apache.lucene.document.StringField;
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
-import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.FieldCache;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.ScoreDoc;
 import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.AlreadyClosedException;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.BitVector;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestIndexWriterConfig.java lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestIndexWriterConfig.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestIndexWriterConfig.java	2011-07-27 00:16:39.282328617 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestIndexWriterConfig.java	2011-08-23 09:44:16.451460290 -0400
@@ -26,8 +26,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.index.DocumentsWriterPerThread.IndexingChain;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
-import org.apache.lucene.search.DefaultSimilarityProvider;
 import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
 import org.apache.lucene.util.LuceneTestCase;
 import org.junit.Test;
 


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestMaxTermFrequency.java lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestMaxTermFrequency.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestMaxTermFrequency.java	2011-08-29 12:22:46.651459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestMaxTermFrequency.java	2011-08-29 13:48:08.921459544 -0400
@@ -27,9 +27,9 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.TextField;
-import org.apache.lucene.search.DefaultSimilarity;
-import org.apache.lucene.search.DefaultSimilarityProvider;
-import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util._TestUtil;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestNorms.java lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestNorms.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestNorms.java	2011-08-29 12:22:46.661459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestNorms.java	2011-08-29 13:43:38.631459544 -0400
@@ -27,10 +27,10 @@
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
-import org.apache.lucene.search.DefaultSimilarity;
-import org.apache.lucene.search.DefaultSimilarityProvider;
-import org.apache.lucene.search.Similarity;
-import org.apache.lucene.search.SimilarityProvider;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestOmitTf.java lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestOmitTf.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestOmitTf.java	2011-08-30 09:57:44.641459442 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestOmitTf.java	2011-08-30 10:04:15.201459442 -0400
@@ -32,6 +32,9 @@
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.search.*;
 import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
+import org.apache.lucene.search.similarities.TFIDFSimilarity;
 import org.apache.lucene.store.Directory;
 
 


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestParallelReader.java lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestParallelReader.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestParallelReader.java	2011-08-29 12:22:46.671459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestParallelReader.java	2011-08-29 22:25:37.861459500 -0400
@@ -25,6 +25,7 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
 import org.apache.lucene.search.*;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
@@ -234,7 +235,8 @@
     w.addDocument(d2);
     w.close();
 
-    return new IndexSearcher(dir, false);
+    IndexReader ir = IndexReader.open(dir, false);
+    return newSearcher(ir);
   }
 
   // Fields 1 & 2 in one index, 3 & 4 in other, with ParallelReader:


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestUniqueTermCount.java lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestUniqueTermCount.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/index/TestUniqueTermCount.java	2011-08-29 12:22:46.671459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/index/TestUniqueTermCount.java	2011-08-29 13:49:52.791459544 -0400
@@ -25,9 +25,9 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.TextField;
-import org.apache.lucene.search.DefaultSimilarity;
-import org.apache.lucene.search.DefaultSimilarityProvider;
-import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util._TestUtil;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/JustCompileSearch.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/JustCompileSearch.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/JustCompileSearch.java	2011-07-17 06:27:33.558948135 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/JustCompileSearch.java	2011-08-23 08:43:39.751460295 -0400
@@ -20,9 +20,11 @@
 import java.io.IOException;
 
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
-import org.apache.lucene.search.Similarity.ExactDocScorer;
-import org.apache.lucene.search.Similarity.SloppyDocScorer;
-import org.apache.lucene.search.Similarity.Stats;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity.ExactDocScorer;
+import org.apache.lucene.search.similarities.Similarity.SloppyDocScorer;
+import org.apache.lucene.search.similarities.Similarity.Stats;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.TermContext;
 import org.apache.lucene.index.FieldInvertState;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/payloads/PayloadHelper.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/payloads/PayloadHelper.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/payloads/PayloadHelper.java	2011-08-29 12:22:46.381459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/payloads/PayloadHelper.java	2011-08-29 13:42:11.991459544 -0400
@@ -29,7 +29,7 @@
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.SimilarityProvider;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.MockDirectoryWrapper;
 import org.apache.lucene.store.RAMDirectory;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/payloads/TestPayloadExplanations.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/payloads/TestPayloadExplanations.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/payloads/TestPayloadExplanations.java	2011-09-08 17:01:39.436036270 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/payloads/TestPayloadExplanations.java	2011-09-08 12:58:43.406030891 -0400
@@ -18,9 +18,9 @@
  */
 
 import org.apache.lucene.index.Term;
-import org.apache.lucene.search.DefaultSimilarity;
-import org.apache.lucene.search.DefaultSimilarityProvider;
-import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.search.TestExplanations;
 import org.apache.lucene.search.spans.SpanQuery;
 import org.apache.lucene.util.BytesRef;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/payloads/TestPayloadNearQuery.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/payloads/TestPayloadNearQuery.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/payloads/TestPayloadNearQuery.java	2011-08-29 12:22:46.381459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/payloads/TestPayloadNearQuery.java	2011-08-29 13:42:10.801459544 -0400
@@ -27,14 +27,14 @@
 import org.apache.lucene.index.Payload;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.QueryUtils;
 import org.apache.lucene.search.ScoreDoc;
 import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.Similarity;
-import org.apache.lucene.search.SimilarityProvider;
 import org.apache.lucene.search.TopDocs;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.search.spans.SpanQuery;
 import org.apache.lucene.search.spans.SpanNearQuery;
 import org.apache.lucene.search.spans.SpanTermQuery;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/payloads/TestPayloadTermQuery.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/payloads/TestPayloadTermQuery.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/payloads/TestPayloadTermQuery.java	2011-08-29 12:22:46.381459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/payloads/TestPayloadTermQuery.java	2011-08-29 13:42:11.401459544 -0400
@@ -20,17 +20,17 @@
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.English;
-import org.apache.lucene.search.DefaultSimilarityProvider;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.QueryUtils;
-import org.apache.lucene.search.Similarity;
-import org.apache.lucene.search.SimilarityProvider;
 import org.apache.lucene.search.TopDocs;
 import org.apache.lucene.search.ScoreDoc;
 import org.apache.lucene.search.CheckHits;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.search.spans.MultiSpansWrapper;
 import org.apache.lucene.search.spans.SpanTermQuery;
 import org.apache.lucene.search.spans.Spans;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/similarities/SpoofIndexSearcher.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/similarities/SpoofIndexSearcher.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/similarities/SpoofIndexSearcher.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/similarities/SpoofIndexSearcher.java	2011-08-29 19:05:54.131459517 -0400
@@ -0,0 +1,211 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Map;
+
+import org.apache.lucene.index.CorruptIndexException;
+import org.apache.lucene.index.Fields;
+import org.apache.lucene.index.FieldsEnum;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.StoredFieldVisitor;
+import org.apache.lucene.index.TermFreqVector;
+import org.apache.lucene.index.TermVectorMapper;
+import org.apache.lucene.index.Terms;
+import org.apache.lucene.index.TermsEnum;
+import org.apache.lucene.index.codecs.PerDocValues;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.util.Bits;
+import org.apache.lucene.util.BytesRef;
+
+/**
+ * Index searcher implementation that takes an {@link BasicStats} instance and
+ * returns statistics accordingly. Most of the methods are not implemented, so
+ * it can only be used for Similarity unit testing.
+ */
+public class SpoofIndexSearcher extends IndexSearcher {
+  public SpoofIndexSearcher(BasicStats stats) {
+    super(new SpoofIndexReader(stats));
+  }
+  
+  public static class SpoofIndexReader extends IndexReader {
+    /** The stats the reader has to return. */
+    protected BasicStats stats;
+    /** The fields the reader has to return. */
+    protected SpoofFields fields;
+    
+    public SpoofIndexReader(BasicStats stats) {
+      this.stats = stats;
+      this.fields = new SpoofFields(stats);
+    }
+
+    @Override
+    public int numDocs() {
+      return stats.getNumberOfDocuments();
+    }
+
+    @Override
+    public int maxDoc() {
+      return stats.getNumberOfDocuments();
+    }
+
+    @Override
+    public Fields fields() throws IOException {
+      return fields;
+    }
+
+    @Override
+    public Collection<String> getFieldNames(FieldOption fldOption) {
+      return Arrays.asList(new String[]{"spoof"});
+    }
+
+    @Override
+    public ReaderContext getTopReaderContext() {
+      return new AtomicReaderContext(this);
+    }
+    
+    @Override
+    public boolean hasDeletions() {
+      return false;
+    }
+
+    // ------------------------ Not implemented methods ------------------------
+    
+    @Override
+    public TermFreqVector[] getTermFreqVectors(int docNumber)
+        throws IOException {
+      return null;
+    }
+
+    @Override
+    public TermFreqVector getTermFreqVector(int docNumber, String field)
+        throws IOException {
+      return null;
+    }
+
+    @Override
+    public void getTermFreqVector(int docNumber, String field,
+        TermVectorMapper mapper) throws IOException {
+    }
+
+    @Override
+    public void getTermFreqVector(int docNumber, TermVectorMapper mapper)
+        throws IOException {
+    }
+
+    @Override
+    public void document(int docID, StoredFieldVisitor visitor) throws CorruptIndexException, IOException {
+    }
+
+    @Override
+    public byte[] norms(String field) throws IOException {
+      return null;
+    }
+
+    @Override
+    protected void doSetNorm(int doc, String field, byte value)
+        throws CorruptIndexException, IOException {
+    }
+
+    @Override
+    public PerDocValues perDocValues() throws IOException {
+      return null;
+    }
+
+    @Override
+    protected void doDelete(int docNum) throws CorruptIndexException,
+        IOException {
+    }
+
+    @Override
+    protected void doUndeleteAll() throws CorruptIndexException, IOException {
+    }
+
+    @Override
+    protected void doCommit(Map<String,String> commitUserData)
+        throws IOException {
+    }
+
+    @Override
+    protected void doClose() throws IOException {
+    }
+
+    @Override
+    public Bits getLiveDocs() {
+      return null;
+    }
+  }
+  
+  /** Spoof Fields class for Similarity testing. */
+  public static class SpoofFields extends Fields {
+    /** The stats the object has to return. */
+    protected SpoofTerms terms;
+    
+    public SpoofFields(BasicStats stats) {
+      this.terms = new SpoofTerms(stats);
+    }
+    
+    @Override
+    public Terms terms(String field) throws IOException {
+      return terms;
+    }
+    
+    // ------------------------ Not implemented methods ------------------------
+
+    @Override
+    public FieldsEnum iterator() throws IOException {
+      return null;
+    }
+  }
+  
+  /** Spoof Terms class for Similarity testing. */
+  public static class SpoofTerms extends Terms {
+    /** The stats the object has to return. */
+    protected BasicStats stats;
+    
+    public SpoofTerms(BasicStats stats) {
+      this.stats = stats;
+    }
+    
+    @Override
+    public long getSumTotalTermFreq() throws IOException {
+      return stats.getNumberOfFieldTokens();
+    }
+
+    @Override
+    public long getSumDocFreq() throws IOException {
+      return stats.getDocFreq();
+    }
+    
+    // ------------------------ Not implemented methods ------------------------
+    
+    @Override
+    public TermsEnum iterator() throws IOException {
+      return null;
+    }
+
+    @Override
+    public Comparator<BytesRef> getComparator() throws IOException {
+      return null;
+    }
+  }
+}
\ No newline at end of file


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/similarities/TestSimilarity2.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/similarities/TestSimilarity2.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/similarities/TestSimilarity2.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/similarities/TestSimilarity2.java	2011-09-02 10:28:44.595836255 -0400
@@ -0,0 +1,218 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
+import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Collector;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.LuceneTestCase;
+
+/**
+ * Tests against all the similarities we have
+ */
+public class TestSimilarity2 extends LuceneTestCase {
+  List<SimilarityProvider> simProviders;
+  
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    simProviders = new ArrayList<SimilarityProvider>();
+    simProviders.add(new BasicSimilarityProvider(new DefaultSimilarity()));
+    simProviders.add(new BasicSimilarityProvider(new BM25Similarity()));
+    // TODO: not great that we dup this all with TestSimilarityBase
+    for (BasicModel basicModel : TestSimilarityBase.BASIC_MODELS) {
+      for (AfterEffect afterEffect : TestSimilarityBase.AFTER_EFFECTS) {
+        for (Normalization normalization : TestSimilarityBase.NORMALIZATIONS) {
+          simProviders.add(new BasicSimilarityProvider(new DFRSimilarity(basicModel, afterEffect, normalization)));
+        }
+      }
+    }
+    for (Distribution distribution : TestSimilarityBase.DISTRIBUTIONS) {
+      for (Lambda lambda : TestSimilarityBase.LAMBDAS) {
+        for (Normalization normalization : TestSimilarityBase.NORMALIZATIONS) {
+          simProviders.add(new BasicSimilarityProvider(new IBSimilarity(distribution, lambda, normalization)));
+        }
+      }
+    }
+    simProviders.add(new BasicSimilarityProvider(new LMDirichletSimilarity()));
+    simProviders.add(new BasicSimilarityProvider(new LMJelinekMercerSimilarity(0.1f)));
+    simProviders.add(new BasicSimilarityProvider(new LMJelinekMercerSimilarity(0.7f)));
+  }
+  
+  /** because of stupid things like querynorm, its possible we computeStats on a field that doesnt exist at all
+   *  test this against a totally empty index, to make sure sims handle it
+   */
+  public void testEmptyIndex() throws Exception {
+    Directory dir = newDirectory();
+    RandomIndexWriter iw = new RandomIndexWriter(random, dir);
+    IndexReader ir = iw.getReader();
+    iw.close();
+    IndexSearcher is = newSearcher(ir);
+    
+    for (SimilarityProvider simProvider : simProviders) {
+      is.setSimilarityProvider(simProvider);
+      assertEquals(0, is.search(new TermQuery(new Term("foo", "bar")), 10).totalHits);
+    }
+    is.close();
+    ir.close();
+    dir.close();
+  }
+  
+  /** similar to the above, but ORs the query with a real field */
+  public void testEmptyField() throws Exception {
+    Directory dir = newDirectory();
+    RandomIndexWriter iw = new RandomIndexWriter(random, dir);
+    Document doc = new Document();
+    doc.add(newField("foo", "bar", TextField.TYPE_UNSTORED));
+    iw.addDocument(doc);
+    IndexReader ir = iw.getReader();
+    iw.close();
+    IndexSearcher is = newSearcher(ir);
+    
+    for (SimilarityProvider simProvider : simProviders) {
+      is.setSimilarityProvider(simProvider);
+      BooleanQuery query = new BooleanQuery(true);
+      query.add(new TermQuery(new Term("foo", "bar")), BooleanClause.Occur.SHOULD);
+      query.add(new TermQuery(new Term("bar", "baz")), BooleanClause.Occur.SHOULD);
+      assertEquals(1, is.search(query, 10).totalHits);
+    }
+    is.close();
+    ir.close();
+    dir.close();
+  }
+  
+  /** similar to the above, however the field exists, but we query with a term that doesnt exist too */
+  public void testEmptyTerm() throws Exception {
+    Directory dir = newDirectory();
+    RandomIndexWriter iw = new RandomIndexWriter(random, dir);
+    Document doc = new Document();
+    doc.add(newField("foo", "bar", TextField.TYPE_UNSTORED));
+    iw.addDocument(doc);
+    IndexReader ir = iw.getReader();
+    iw.close();
+    IndexSearcher is = newSearcher(ir);
+    
+    for (SimilarityProvider simProvider : simProviders) {
+      is.setSimilarityProvider(simProvider);
+      BooleanQuery query = new BooleanQuery(true);
+      query.add(new TermQuery(new Term("foo", "bar")), BooleanClause.Occur.SHOULD);
+      query.add(new TermQuery(new Term("foo", "baz")), BooleanClause.Occur.SHOULD);
+      assertEquals(1, is.search(query, 10).totalHits);
+    }
+    is.close();
+    ir.close();
+    dir.close();
+  }
+  
+  /** make sure we can retrieve when norms are disabled */
+  public void testNoNorms() throws Exception {
+    Directory dir = newDirectory();
+    RandomIndexWriter iw = new RandomIndexWriter(random, dir);
+    Document doc = new Document();
+    FieldType ft = new FieldType(TextField.TYPE_UNSTORED);
+    ft.setOmitNorms(true);
+    ft.freeze();
+    doc.add(newField("foo", "bar", ft));
+    iw.addDocument(doc);
+    IndexReader ir = iw.getReader();
+    iw.close();
+    IndexSearcher is = newSearcher(ir);
+    
+    for (SimilarityProvider simProvider : simProviders) {
+      is.setSimilarityProvider(simProvider);
+      BooleanQuery query = new BooleanQuery(true);
+      query.add(new TermQuery(new Term("foo", "bar")), BooleanClause.Occur.SHOULD);
+      assertEquals(1, is.search(query, 10).totalHits);
+    }
+    is.close();
+    ir.close();
+    dir.close();
+  }
+  
+  /** make sure all sims work if TF is omitted */
+  public void testOmitTF() throws Exception {
+    Directory dir = newDirectory();
+    RandomIndexWriter iw = new RandomIndexWriter(random, dir);
+    Document doc = new Document();
+    FieldType ft = new FieldType(TextField.TYPE_UNSTORED);
+    ft.setIndexOptions(IndexOptions.DOCS_ONLY);
+    ft.freeze();
+    Field f = newField("foo", "bar", ft);
+    doc.add(f);
+    iw.addDocument(doc);
+    IndexReader ir = iw.getReader();
+    iw.close();
+    IndexSearcher is = newSearcher(ir);
+    
+    for (SimilarityProvider simProvider : simProviders) {
+      is.setSimilarityProvider(simProvider);
+      BooleanQuery query = new BooleanQuery(true);
+      query.add(new TermQuery(new Term("foo", "bar")), BooleanClause.Occur.SHOULD);
+      assertEquals(1, is.search(query, 10).totalHits);
+    }
+    is.close();
+    ir.close();
+    dir.close();
+  }
+  
+  /** make sure all sims work if TF and norms is omitted */
+  public void testOmitTFAndNorms() throws Exception {
+    Directory dir = newDirectory();
+    RandomIndexWriter iw = new RandomIndexWriter(random, dir);
+    Document doc = new Document();
+    FieldType ft = new FieldType(TextField.TYPE_UNSTORED);
+    ft.setIndexOptions(IndexOptions.DOCS_ONLY);
+    ft.setOmitNorms(true);
+    ft.freeze();
+    Field f = newField("foo", "bar", ft);
+    doc.add(f);
+    iw.addDocument(doc);
+    IndexReader ir = iw.getReader();
+    iw.close();
+    IndexSearcher is = newSearcher(ir);
+    
+    for (SimilarityProvider simProvider : simProviders) {
+      is.setSimilarityProvider(simProvider);
+      BooleanQuery query = new BooleanQuery(true);
+      query.add(new TermQuery(new Term("foo", "bar")), BooleanClause.Occur.SHOULD);
+      assertEquals(1, is.search(query, 10).totalHits);
+    }
+    is.close();
+    ir.close();
+    dir.close();
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/similarities/TestSimilarityBase.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/similarities/TestSimilarityBase.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/similarities/TestSimilarityBase.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/similarities/TestSimilarityBase.java	2011-09-07 01:31:25.205983786 -0400
@@ -0,0 +1,587 @@
+package org.apache.lucene.search.similarities;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.OrdTermState;
+import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.codecs.CodecProvider;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TopDocs;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util.TermContext;
+import org.junit.Ignore;
+
+/**
+ * Tests the {@link SimilarityBase}-based Similarities. Contains unit tests and 
+ * integration tests for all Similarities and correctness tests for a select
+ * few.
+ * <p>This class maintains a list of
+ * {@code SimilarityBase} subclasses. Each test case performs its test on all
+ * items in the list. If a test case fails, the name of the Similarity that
+ * caused the failure is returned as part of the assertion error message.</p>
+ * <p>Unit testing is performed by constructing statistics manually and calling
+ * the {@link SimilarityBase#score(BasicStats, float, int)} method of the
+ * Similarities. The statistics represent corner cases of corpus distributions.
+ * </p>
+ * <p>For the integration tests, a small (8-document) collection is indexed. The
+ * tests verify that for a specific query, all relevant documents are returned
+ * in the correct order. The collection consists of two poems of English poet
+ * <a href="http://en.wikipedia.org/wiki/William_blake">William Blake</a>.</p>
+ * <p>Note: the list of Similarities is maintained by hand. If a new Similarity
+ * is added to the {@code org.apache.lucene.search.similarities} package, the
+ * list should be updated accordingly.</p>
+ * <p>
+ * In the correctness tests, the score is verified against the result of manual
+ * computation. Since it would be impossible to test all Similarities
+ * (e.g. all possible DFR combinations, all parameter values for LM), only 
+ * the best performing setups in the original papers are verified.
+ * </p>
+ */
+public class TestSimilarityBase extends LuceneTestCase {
+  private static String FIELD_BODY = "body";
+  private static String FIELD_ID = "id";
+  /** The tolerance range for float equality. */
+  private static float FLOAT_EPSILON = 1e-5f;
+  /** The DFR basic models to test. */
+  static BasicModel[] BASIC_MODELS = {
+    new BasicModelBE(), new BasicModelD(), new BasicModelG(),
+    new BasicModelIF(), new BasicModelIn(), new BasicModelIne(),
+    new BasicModelP()
+  };
+  /** The DFR aftereffects to test. */
+  static AfterEffect[] AFTER_EFFECTS = {
+    new AfterEffectB(), new AfterEffectL(), new AfterEffect.NoAfterEffect()
+  };
+  /** The DFR normalizations to test. */
+  static Normalization[] NORMALIZATIONS = {
+    new NormalizationH1(), new NormalizationH2(), new NormalizationH3(),
+    new NormalizationZ(), new Normalization.NoNormalization()
+  };
+  /** The distributions for IB. */
+  static Distribution[] DISTRIBUTIONS = {
+    new DistributionLL(), new DistributionSPL()
+  };
+  /** Lambdas for IB. */
+  static Lambda[] LAMBDAS = {
+    new LambdaDF(), new LambdaTTF()
+  };
+  
+  private IndexSearcher searcher;
+  private Directory dir;
+  private IndexReader reader;
+  /** The list of similarities to test. */
+  private List<SimilarityBase> sims;
+  
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+
+    dir = newDirectory();
+    RandomIndexWriter writer = new RandomIndexWriter(random, dir);
+
+    for (int i = 0; i < docs.length; i++) {
+      Document d = new Document();
+      FieldType ft = new FieldType(TextField.TYPE_STORED);
+      ft.setIndexed(false);
+      d.add(newField(FIELD_ID, Integer.toString(i), ft));
+      d.add(newField(FIELD_BODY, docs[i], TextField.TYPE_STORED));
+      writer.addDocument(d);
+    }
+    
+    reader = writer.getReader();
+    searcher = newSearcher(reader);
+    writer.close();
+    
+    sims = new ArrayList<SimilarityBase>();
+    for (BasicModel basicModel : BASIC_MODELS) {
+      for (AfterEffect afterEffect : AFTER_EFFECTS) {
+        for (Normalization normalization : NORMALIZATIONS) {
+          sims.add(new DFRSimilarity(basicModel, afterEffect, normalization));
+        }
+      }
+    }
+    for (Distribution distribution : DISTRIBUTIONS) {
+      for (Lambda lambda : LAMBDAS) {
+        for (Normalization normalization : NORMALIZATIONS) {
+          sims.add(new IBSimilarity(distribution, lambda, normalization));
+        }
+      }
+    }
+    sims.add(new LMDirichletSimilarity());
+    sims.add(new LMJelinekMercerSimilarity(0.1f));
+    sims.add(new LMJelinekMercerSimilarity(0.7f));
+  }
+  
+  // ------------------------------- Unit tests --------------------------------
+  
+  /** The default number of documents in the unit tests. */
+  private static int NUMBER_OF_DOCUMENTS = 100;
+  /** The default total number of tokens in the field in the unit tests. */
+  private static long NUMBER_OF_FIELD_TOKENS = 5000;
+  /** The default average field length in the unit tests. */
+  private static float AVG_FIELD_LENGTH = 50;
+  /** The default document frequency in the unit tests. */
+  private static int DOC_FREQ = 10;
+  /**
+   * The default total number of occurrences of this term across all documents
+   * in the unit tests.
+   */
+  private static long TOTAL_TERM_FREQ = 70;
+  
+  /** The default tf in the unit tests. */
+  private static float FREQ = 7;
+  /** The default document length in the unit tests. */
+  private static int DOC_LEN = 40;
+  
+  /** Creates the default statistics object that the specific tests modify. */
+  private BasicStats createStats() {
+    BasicStats stats = new BasicStats(1);
+    stats.setNumberOfDocuments(NUMBER_OF_DOCUMENTS);
+    stats.setNumberOfFieldTokens(NUMBER_OF_FIELD_TOKENS);
+    stats.setAvgFieldLength(AVG_FIELD_LENGTH);
+    stats.setDocFreq(DOC_FREQ);
+    stats.setTotalTermFreq(TOTAL_TERM_FREQ);
+    return stats;
+  }
+
+  /**
+   * The generic test core called by all unit test methods. It calls the
+   * {@link SimilarityBase#score(BasicStats, float, int)} method of all
+   * Similarities in {@link #sims} and checks if the score is valid; i.e. it
+   * is a finite positive real number.
+   */
+  private void unitTestCore(BasicStats stats, float freq, int docLen)
+      throws IOException {
+    // We have to fake everything, because computeStats() can be overridden and
+    // there is no way to inject false data after fillBasicStats().
+    SpoofIndexSearcher searcher = new SpoofIndexSearcher(stats);
+    TermContext tc = new TermContext(
+        searcher.getIndexReader().getTopReaderContext(),
+        new OrdTermState(), 0, stats.getDocFreq(), stats.getTotalTermFreq());
+    
+    for (SimilarityBase sim : sims) {
+      BasicStats realStats = (BasicStats) sim.computeStats(new SpoofIndexSearcher(stats),
+          "spoof", stats.getTotalBoost(), tc);
+      float score = sim.score(realStats, freq, docLen);
+      float explScore = sim.explain(
+          realStats, 1, new Explanation(freq, "freq"), docLen).getValue();
+      assertFalse("Score infinite: " + sim.toString(), Float.isInfinite(score));
+      assertFalse("Score NaN: " + sim.toString(), Float.isNaN(score));
+      assertTrue("Score negative: " + sim.toString(), score >= 0);
+      assertEquals("score() and explain() return different values: "
+          + sim.toString(), score, explScore, FLOAT_EPSILON);
+    }
+  }
+  
+  /** Runs the unit test with the default statistics. */
+  public void testDefault() throws IOException {
+    unitTestCore(createStats(), FREQ, DOC_LEN);
+  }
+  
+  /**
+   * Tests correct behavior when
+   * {@code numberOfDocuments = numberOfFieldTokens}.
+   */
+  public void testSparseDocuments() throws IOException {
+    BasicStats stats = createStats();
+    stats.setNumberOfFieldTokens(stats.getNumberOfDocuments());
+    stats.setTotalTermFreq(stats.getDocFreq());
+    stats.setAvgFieldLength(
+        (float)stats.getNumberOfFieldTokens() / stats.getNumberOfDocuments());
+    unitTestCore(stats, FREQ, DOC_LEN);
+  }
+
+  /**
+   * Tests correct behavior when
+   * {@code numberOfDocuments > numberOfFieldTokens}.
+   */
+  public void testVerySparseDocuments() throws IOException {
+    BasicStats stats = createStats();
+    stats.setNumberOfFieldTokens(stats.getNumberOfDocuments() * 2 / 3);
+    stats.setTotalTermFreq(stats.getDocFreq());
+    stats.setAvgFieldLength(
+        (float)stats.getNumberOfFieldTokens() / stats.getNumberOfDocuments());
+    unitTestCore(stats, FREQ, DOC_LEN);
+  }
+  
+  /**
+   * Tests correct behavior when
+   * {@code NumberOfDocuments = 1}.
+   */
+  public void testOneDocument() throws IOException {
+    BasicStats stats = createStats();
+    stats.setNumberOfDocuments(1);
+    stats.setNumberOfFieldTokens(DOC_LEN);
+    stats.setAvgFieldLength(DOC_LEN);
+    stats.setDocFreq(1);
+    stats.setTotalTermFreq((int)FREQ);
+    unitTestCore(stats, FREQ, DOC_LEN);
+  }
+
+  /**
+   * Tests correct behavior when
+   * {@code docFreq = numberOfDocuments}.
+   */
+  public void testAllDocumentsRelevant() throws IOException {
+    BasicStats stats = createStats();
+    float mult = (0.0f + stats.getNumberOfDocuments()) / stats.getDocFreq();
+    stats.setTotalTermFreq((int)(stats.getTotalTermFreq() * mult));
+    stats.setDocFreq(stats.getNumberOfDocuments());
+    unitTestCore(stats, FREQ, DOC_LEN);
+  }
+
+  /**
+   * Tests correct behavior when
+   * {@code docFreq > numberOfDocuments / 2}.
+   */
+  public void testMostDocumentsRelevant() throws IOException {
+    BasicStats stats = createStats();
+    float mult = (0.6f * stats.getNumberOfDocuments()) / stats.getDocFreq();
+    stats.setTotalTermFreq((int)(stats.getTotalTermFreq() * mult));
+    stats.setDocFreq((int)(stats.getNumberOfDocuments() * 0.6));
+    unitTestCore(stats, FREQ, DOC_LEN);
+  }
+
+  /**
+   * Tests correct behavior when
+   * {@code docFreq = 1}.
+   */
+  public void testOnlyOneRelevantDocument() throws IOException {
+    BasicStats stats = createStats();
+    stats.setDocFreq(1);
+    stats.setTotalTermFreq((int)FREQ + 3);
+    unitTestCore(stats, FREQ, DOC_LEN);
+  }
+
+  /**
+   * Tests correct behavior when
+   * {@code totalTermFreq = numberOfFieldTokens}.
+   */
+  public void testAllTermsRelevant() throws IOException {
+    BasicStats stats = createStats();
+    stats.setTotalTermFreq(stats.getNumberOfFieldTokens());
+    unitTestCore(stats, DOC_LEN, DOC_LEN);
+    stats.setAvgFieldLength(DOC_LEN + 10);
+    unitTestCore(stats, DOC_LEN, DOC_LEN);
+  }
+
+  /**
+   * Tests correct behavior when
+   * {@code totalTermFreq > numberOfDocuments}.
+   */
+  public void testMoreTermsThanDocuments() throws IOException {
+    BasicStats stats = createStats();
+    stats.setTotalTermFreq(
+        stats.getTotalTermFreq() + stats.getNumberOfDocuments());
+    unitTestCore(stats, 2 * FREQ, DOC_LEN);
+  }
+
+  /**
+   * Tests correct behavior when
+   * {@code totalTermFreq = numberOfDocuments}.
+   */
+  public void testNumberOfTermsAsDocuments() throws IOException {
+    BasicStats stats = createStats();
+    stats.setTotalTermFreq(stats.getNumberOfDocuments());
+    unitTestCore(stats, FREQ, DOC_LEN);
+  }
+
+  /**
+   * Tests correct behavior when {@code totalTermFreq = 1}.
+   */
+  public void testOneTerm() throws IOException {
+    BasicStats stats = createStats();
+    stats.setDocFreq(1);
+    stats.setTotalTermFreq(1);
+    unitTestCore(stats, 1, DOC_LEN);
+  }
+  
+  /**
+   * Tests correct behavior when {@code totalTermFreq = freq}.
+   */
+  public void testOneRelevantDocument() throws IOException {
+    BasicStats stats = createStats();
+    stats.setDocFreq(1);
+    stats.setTotalTermFreq((int)FREQ);
+    unitTestCore(stats, FREQ, DOC_LEN);
+  }
+  
+  /**
+   * Tests correct behavior when {@code numberOfFieldTokens = freq}.
+   */
+  public void testAllTermsRelevantOnlyOneDocument() throws IOException {
+    BasicStats stats = createStats();
+    stats.setNumberOfDocuments(10);
+    stats.setNumberOfFieldTokens(50);
+    stats.setAvgFieldLength(5);
+    stats.setDocFreq(1);
+    stats.setTotalTermFreq(50);
+    unitTestCore(stats, 50, 50);
+  }
+
+  /**
+   * Tests correct behavior when there is only one document with a single term 
+   * in the collection.
+   */
+  public void testOnlyOneTermOneDocument() throws IOException {
+    BasicStats stats = createStats();
+    stats.setNumberOfDocuments(1);
+    stats.setNumberOfFieldTokens(1);
+    stats.setAvgFieldLength(1);
+    stats.setDocFreq(1);
+    stats.setTotalTermFreq(1);
+    unitTestCore(stats, 1, 1);
+  }
+
+  /**
+   * Tests correct behavior when there is only one term in the field, but
+   * more than one documents.
+   */
+  public void testOnlyOneTerm() throws IOException {
+    BasicStats stats = createStats();
+    stats.setNumberOfFieldTokens(1);
+    stats.setAvgFieldLength(1.0f / stats.getNumberOfDocuments());
+    stats.setDocFreq(1);
+    stats.setTotalTermFreq(1);
+    unitTestCore(stats, 1, DOC_LEN);
+  }
+  
+  /**
+   * Tests correct behavior when {@code avgFieldLength = docLen}.
+   */
+  public void testDocumentLengthAverage() throws IOException {
+    BasicStats stats = createStats();
+    unitTestCore(stats, FREQ, (int)stats.getAvgFieldLength());
+  }
+  
+  // ---------------------------- Correctness tests ----------------------------
+  
+  /** Correctness test for the Dirichlet LM model. */
+  public void testLMDirichlet() throws IOException {
+    float p =
+        (FREQ + 2000.0f * TOTAL_TERM_FREQ / (NUMBER_OF_FIELD_TOKENS + 1.0f)) /
+        (DOC_LEN + 2000.0f);
+    float a = 2000.0f / (DOC_LEN + 2000.0f);
+    float gold = (float)(
+        Math.log(p / (a * TOTAL_TERM_FREQ / (NUMBER_OF_FIELD_TOKENS + 1.0f))) +
+        Math.log(a));
+    correctnessTestCore(new LMDirichletSimilarity(), gold);
+  }
+  
+  /** Correctness test for the Jelinek-Mercer LM model. */
+  public void testLMJelinekMercer() throws IOException {
+    float p = (1 - 0.1f) * FREQ / DOC_LEN +
+              0.1f * TOTAL_TERM_FREQ / (NUMBER_OF_FIELD_TOKENS + 1.0f);
+    float gold = (float)(Math.log(
+        p / (0.1f * TOTAL_TERM_FREQ / (NUMBER_OF_FIELD_TOKENS + 1.0f))));
+    correctnessTestCore(new LMJelinekMercerSimilarity(0.1f), gold);
+  }
+  
+  /**
+   * Correctness test for the LL IB model with DF-based lambda and
+   * no normalization.
+   */
+  public void testLLForIB() throws IOException {
+    SimilarityBase sim = new IBSimilarity(new DistributionLL(), new LambdaDF(), new Normalization.NoNormalization());
+    correctnessTestCore(sim, 4.26267987704f);
+  }
+  
+  /**
+   * Correctness test for the SPL IB model with TTF-based lambda and
+   * no normalization.
+   */
+  public void testSPLForIB() throws IOException {
+    SimilarityBase sim =
+      new IBSimilarity(new DistributionSPL(), new LambdaTTF(), new Normalization.NoNormalization());
+    correctnessTestCore(sim, 2.24069910825f);
+  }
+  
+  /** Correctness test for the PL2 DFR model. */
+  public void testPL2() throws IOException {
+    SimilarityBase sim = new DFRSimilarity(
+        new BasicModelP(), new AfterEffectL(), new NormalizationH2());
+    float tfn = (float)(FREQ * SimilarityBase.log2(
+        1 + AVG_FIELD_LENGTH / DOC_LEN));  // 8.1894750101
+    float l = 1.0f / (tfn + 1.0f);         // 0.108820144666
+    float lambda = (1.0f * TOTAL_TERM_FREQ) / NUMBER_OF_DOCUMENTS;  // 0.7
+    float p = (float)(tfn * SimilarityBase.log2(tfn / lambda) +
+              (lambda + 1 / (12 * tfn) - tfn) * SimilarityBase.log2(Math.E) +
+              0.5 * SimilarityBase.log2(2 * Math.PI * tfn)); // 21.1113611585
+    float gold = l * p;                    // 2.29734137536
+    correctnessTestCore(sim, gold);
+  }
+
+  /** Correctness test for the IneB2 DFR model. */
+  public void testIneB2() throws IOException {
+    SimilarityBase sim = new DFRSimilarity(
+        new BasicModelIne(), new AfterEffectB(), new NormalizationH2());
+    correctnessTestCore(sim, 6.23455315685f);
+  }
+  
+  /** Correctness test for the GL1 DFR model. */
+  public void testGL1() throws IOException {
+    SimilarityBase sim = new DFRSimilarity(
+        new BasicModelG(), new AfterEffectL(), new NormalizationH1());
+    correctnessTestCore(sim, 1.6463143825531006f);
+  }
+  
+  /** Correctness test for the BEB1 DFR model. */
+  public void testBEB1() throws IOException {
+    SimilarityBase sim = new DFRSimilarity(
+        new BasicModelBE(), new AfterEffectB(), new NormalizationH1());
+    float tfn = FREQ * AVG_FIELD_LENGTH / DOC_LEN;  // 8.75
+    float b = (TOTAL_TERM_FREQ + 1) / (DOC_FREQ * (tfn + 1));  // 0.728205128205
+    float f = TOTAL_TERM_FREQ + tfn;
+    float n = f + NUMBER_OF_DOCUMENTS;
+    float n1 = n + f - 1;        // 256.5
+    float m1 = n + f - tfn - 2;  // 246.75
+    float n2 = f;                                      // 78.75
+    float m2 = f - tfn;                                // 70.0
+    float be = (float)(-SimilarityBase.log2(n - 1) -
+               SimilarityBase.log2(Math.E) +                   // -8.916400790508378
+               ((m1 + 0.5f) * SimilarityBase.log2(n1 / m1) +
+                (n1 - m1) * SimilarityBase.log2(n1)) -         // 91.85089272283668
+               ((m2 + 0.5f) * SimilarityBase.log2(n2 / m2) +
+                (n2 - m2) * SimilarityBase.log2(n2)));         // 67.09778276257171
+               // 15.836709
+    float gold = b * be;                                       // 11.532373
+    correctnessTestCore(sim, gold);
+  }
+
+  /** Correctness test for the D DFR model (basic model only). */
+  public void testD() throws IOException {
+    SimilarityBase sim = new DFRSimilarity(new BasicModelD(), new AfterEffect.NoAfterEffect(), new Normalization.NoNormalization());
+    double totalTermFreqNorm = TOTAL_TERM_FREQ + FREQ;
+    double p = 1.0 / (NUMBER_OF_DOCUMENTS + 1);                // 0.009900990099
+    double phi = FREQ / totalTermFreqNorm;                       // 0.09090909090909091
+    double D = phi * SimilarityBase.log2(phi / p) +            // 0.17884523239871358
+              (1 - phi) * SimilarityBase.log2((1 - phi) / (1 - p));
+    float gold = (float)(totalTermFreqNorm * D + 0.5 * SimilarityBase.log2(
+                 1 + 2 * Math.PI * FREQ * (1 - phi)));         // 16.449575
+    correctnessTestCore(sim, gold);
+  }
+  
+  /** Correctness test for the In2 DFR model with no aftereffect. */
+  public void testIn2() throws IOException {
+    SimilarityBase sim = new DFRSimilarity(
+        new BasicModelIn(), new AfterEffect.NoAfterEffect(), new NormalizationH2());
+    float tfn = (float)(FREQ * SimilarityBase.log2(            // 8.1894750101
+                1 + AVG_FIELD_LENGTH / DOC_LEN));
+    float gold = (float)(tfn * SimilarityBase.log2(            // 26.7459577898
+                 (NUMBER_OF_DOCUMENTS + 1) / (DOC_FREQ + 0.5)));
+    correctnessTestCore(sim, gold);
+  }
+  
+  /** Correctness test for the IFB DFR model with no normalization. */
+  public void testIFB() throws IOException {
+    SimilarityBase sim = new DFRSimilarity(
+        new BasicModelIF(), new AfterEffectB(), new Normalization.NoNormalization());
+    float B = (TOTAL_TERM_FREQ + 1) / (DOC_FREQ * (FREQ + 1)); // 0.8875
+    float IF = (float)(FREQ * SimilarityBase.log2(             // 8.97759389642
+               1 + (NUMBER_OF_DOCUMENTS + 1) / (TOTAL_TERM_FREQ + 0.5)));
+    float gold = B * IF;                                       // 7.96761458307
+    correctnessTestCore(sim, gold);
+  }
+  
+  /**
+   * The generic test core called by all correctness test methods. It calls the
+   * {@link SimilarityBase#score(BasicStats, float, int)} method of all
+   * Similarities in {@link #sims} and compares the score against the manually
+   * computed {@code gold}.
+   */
+  private void correctnessTestCore(SimilarityBase sim, float gold)
+      throws IOException {
+    // We have to fake everything, because computeStats() can be overridden and
+    // there is no way to inject false data after fillBasicStats().
+    BasicStats stats = createStats();
+    SpoofIndexSearcher searcher = new SpoofIndexSearcher(stats);
+    TermContext tc = new TermContext(
+        searcher.getIndexReader().getTopReaderContext(),
+        new OrdTermState(), 0, stats.getDocFreq(), stats.getTotalTermFreq());
+    
+    BasicStats realStats = (BasicStats) sim.computeStats(
+        searcher, "spoof", stats.getTotalBoost(), tc);
+    float score = sim.score(realStats, FREQ, DOC_LEN);
+    assertEquals(
+        sim.toString() + " score not correct.", gold, score, FLOAT_EPSILON);
+  }
+  
+  // ---------------------------- Integration tests ----------------------------
+
+  /** The "collection" for the integration tests. */
+  String[] docs = new String[] {
+      "Tiger, tiger burning bright   In the forest of the night   What immortal hand or eye   Could frame thy fearful symmetry ?",
+      "In what distant depths or skies   Burnt the fire of thine eyes ?   On what wings dare he aspire ?   What the hands the seize the fire ?",
+      "And what shoulder and what art   Could twist the sinews of thy heart ?   And when thy heart began to beat What dread hand ? And what dread feet ?",
+      "What the hammer? What the chain ?   In what furnace was thy brain ?   What the anvil ? And what dread grasp   Dare its deadly terrors clasp ?",
+      "And when the stars threw down their spears   And water'd heaven with their tear   Did he smile his work to see ?   Did he, who made the lamb, made thee ?",
+      "Tiger, tiger burning bright   In the forest of the night   What immortal hand or eye   Dare frame thy fearful symmetry ?",
+      "Cruelty has a human heart   And jealousy a human face   Terror the human form divine   And Secrecy the human dress .",
+      "The human dress is forg'd iron   The human form a fiery forge   The human face a furnace seal'd   The human heart its fiery gorge ."
+  };
+  
+  /**
+   * Tests whether all similarities return three documents for the query word
+   * "heart".
+   */
+  public void testHeartList() throws IOException {
+    Query q = new TermQuery(new Term(FIELD_BODY, "heart"));
+    
+    for (SimilarityBase sim : sims) {
+      searcher.setSimilarityProvider(new BasicSimilarityProvider(sim));
+      TopDocs topDocs = searcher.search(q, 1000);
+      assertEquals("Failed: " + sim.toString(), 3, topDocs.totalHits);
+    }
+  }
+  
+  /** Test whether all similarities return document 3 before documents 7 and 8. */
+  public void testHeartRanking() throws IOException {
+    assumeFalse("PreFlex codec does not support the stats necessary for this test!", 
+        "PreFlex".equals(CodecProvider.getDefault().getDefaultFieldCodec()));
+
+    Query q = new TermQuery(new Term(FIELD_BODY, "heart"));
+    
+    for (SimilarityBase sim : sims) {
+      searcher.setSimilarityProvider(new BasicSimilarityProvider(sim));
+      TopDocs topDocs = searcher.search(q, 1000);
+      assertEquals("Failed: " + sim.toString(), 2, topDocs.scoreDocs[0].doc);
+    }
+  }
+  
+  @Override
+  public void tearDown() throws Exception {
+    searcher.close();
+    reader.close();
+    dir.close();
+    super.tearDown();
+  }
+}
\ No newline at end of file


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/spans/JustCompileSearchSpans.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/spans/JustCompileSearchSpans.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/spans/JustCompileSearchSpans.java	2011-07-17 06:27:33.548948135 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/spans/JustCompileSearchSpans.java	2011-08-23 08:43:39.761460295 -0400
@@ -22,7 +22,7 @@
 
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.search.Weight;
-import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.similarities.Similarity;
 
 /**
  * Holds all implementations of classes in the o.a.l.s.spans package as a


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/spans/TestPayloadSpans.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/spans/TestPayloadSpans.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/spans/TestPayloadSpans.java	2011-08-29 12:22:46.401459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/spans/TestPayloadSpans.java	2011-08-29 13:42:18.941459544 -0400
@@ -37,13 +37,13 @@
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.Payload;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.search.DefaultSimilarityProvider;
 import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.SimilarityProvider;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.search.TopDocs;
 import org.apache.lucene.search.payloads.PayloadHelper;
 import org.apache.lucene.search.payloads.PayloadSpanUtil;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.LockObtainFailedException;
 import org.apache.lucene.util.LuceneTestCase;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/spans/TestSpansAdvanced2.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/spans/TestSpansAdvanced2.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/spans/TestSpansAdvanced2.java	2011-05-08 10:52:14.310078711 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/spans/TestSpansAdvanced2.java	2011-08-29 21:13:50.571459506 -0400
@@ -27,6 +27,7 @@
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.search.*;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
 
 /*******************************************************************************
  * Some expanded tests to make sure my patch doesn't break other SpanTermQuery
@@ -48,7 +49,8 @@
     final RandomIndexWriter writer = new RandomIndexWriter(random, mDirectory,
         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random,
             MockTokenizer.SIMPLE, true, MockTokenFilter.ENGLISH_STOPSET, true))
-                                                           .setOpenMode(OpenMode.APPEND).setMergePolicy(newLogMergePolicy()));
+            .setOpenMode(OpenMode.APPEND).setMergePolicy(newLogMergePolicy())
+            .setSimilarityProvider(new DefaultSimilarityProvider()));
     addDocument(writer, "A", "Should we, could we, would we?");
     addDocument(writer, "B", "It should.  Should it?");
     addDocument(writer, "C", "It shouldn't.");
@@ -58,6 +60,7 @@
     
     // re-open the searcher since we added more docs
     searcher2 = newSearcher(reader2);
+    searcher2.setSimilarityProvider(new DefaultSimilarityProvider());
   }
   
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/spans/TestSpansAdvanced.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/spans/TestSpansAdvanced.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/spans/TestSpansAdvanced.java	2011-08-29 12:22:46.401459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/spans/TestSpansAdvanced.java	2011-08-29 21:37:08.151459504 -0400
@@ -31,6 +31,7 @@
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.*;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
 import org.apache.lucene.store.Directory;
 
 /*******************************************************************************
@@ -57,10 +58,10 @@
     super.setUp();
     // create test index
     mDirectory = newDirectory();
-    final RandomIndexWriter writer = new RandomIndexWriter(random,
-                                                           mDirectory, newIndexWriterConfig(TEST_VERSION_CURRENT,
-                                                                                            new MockAnalyzer(random, MockTokenizer.SIMPLE, true,
-                                                                                                             MockTokenFilter.ENGLISH_STOPSET, true)).setMergePolicy(newLogMergePolicy()));
+    final RandomIndexWriter writer = new RandomIndexWriter(random, mDirectory, 
+        newIndexWriterConfig(TEST_VERSION_CURRENT, 
+            new MockAnalyzer(random, MockTokenizer.SIMPLE, true, MockTokenFilter.ENGLISH_STOPSET, true))
+            .setMergePolicy(newLogMergePolicy()).setSimilarityProvider(new DefaultSimilarityProvider()));
     addDocument(writer, "1", "I think it should work.");
     addDocument(writer, "2", "I think it should work.");
     addDocument(writer, "3", "I think it should work.");
@@ -68,6 +69,7 @@
     reader = writer.getReader();
     writer.close();
     searcher = newSearcher(reader);
+    searcher.setSimilarityProvider(new DefaultSimilarityProvider());
   }
   
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/spans/TestSpans.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/spans/TestSpans.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/spans/TestSpans.java	2011-08-29 12:22:46.401459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/spans/TestSpans.java	2011-08-29 13:42:16.551459544 -0400
@@ -17,17 +17,17 @@
  * limitations under the License.
  */
 
-import org.apache.lucene.search.DefaultSimilarityProvider;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.CheckHits;
-import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.Scorer;
-import org.apache.lucene.search.Similarity;
-import org.apache.lucene.search.SimilarityProvider;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Weight.ScorerContext;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.index.IndexReader.ReaderContext;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestBoolean2.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestBoolean2.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestBoolean2.java	2011-08-29 12:22:46.481459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestBoolean2.java	2011-08-29 13:42:26.711459544 -0400
@@ -26,6 +26,8 @@
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.MockDirectoryWrapper;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestBooleanQuery.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestBooleanQuery.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestBooleanQuery.java	2011-08-29 12:22:46.471459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestBooleanQuery.java	2011-09-08 13:40:06.096031807 -0400
@@ -27,6 +27,9 @@
 import org.apache.lucene.index.MultiReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.NamedThreadFactory;
@@ -72,6 +75,21 @@
 
     IndexReader r = w.getReader();
     IndexSearcher s = newSearcher(r);
+    // this test relies upon coord being the default implementation,
+    // otherwise scores are different!
+    final SimilarityProvider delegate = s.getSimilarityProvider();
+    s.setSimilarityProvider(new DefaultSimilarityProvider() {
+      @Override
+      public float queryNorm(float sumOfSquaredWeights) {
+        return delegate.queryNorm(sumOfSquaredWeights);
+      }
+
+      @Override
+      public Similarity get(String field) {
+        return delegate.get(field);
+      }
+    });
+
     BooleanQuery q = new BooleanQuery();
     q.add(new TermQuery(new Term("field", "a")), BooleanClause.Occur.SHOULD);
 
@@ -81,7 +99,7 @@
     subQuery.setBoost(0);
     q.add(subQuery, BooleanClause.Occur.SHOULD);
     float score2 = s.search(q, 10).getMaxScore();
-    assertEquals(score*.5, score2, 1e-6);
+    assertEquals(score*.5F, score2, 1e-6);
 
     // LUCENE-2617: make sure that a clause not in the index still contributes to the score via coord factor
     BooleanQuery qq = (BooleanQuery)q.clone();
@@ -91,14 +109,14 @@
     phrase.setBoost(0);
     qq.add(phrase, BooleanClause.Occur.SHOULD);
     score2 = s.search(qq, 10).getMaxScore();
-    assertEquals(score*(1.0/3), score2, 1e-6);
+    assertEquals(score*(1/3F), score2, 1e-6);
 
     // now test BooleanScorer2
     subQuery = new TermQuery(new Term("field", "b"));
     subQuery.setBoost(0);
     q.add(subQuery, BooleanClause.Occur.MUST);
     score2 = s.search(q, 10).getMaxScore();
-    assertEquals(score*(2.0/3), score2, 1e-6);
+    assertEquals(score*(2/3F), score2, 1e-6);
  
     // PhraseQuery w/ no terms added returns a null scorer
     PhraseQuery pq = new PhraseQuery();


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestComplexExplanations.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestComplexExplanations.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestComplexExplanations.java	2011-07-07 14:01:09.401820326 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestComplexExplanations.java	2011-08-23 08:43:39.751460295 -0400
@@ -19,6 +19,7 @@
 
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
 import org.apache.lucene.search.spans.*;
 
 /**


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestConstantScoreQuery.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestConstantScoreQuery.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestConstantScoreQuery.java	2011-09-08 17:01:39.436036270 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestConstantScoreQuery.java	2011-09-08 12:56:40.326030845 -0400
@@ -23,6 +23,7 @@
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java	2011-08-29 12:22:46.481459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java	2011-08-29 13:42:34.481459544 -0400
@@ -29,6 +29,10 @@
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.Weight.ScorerContext;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 
 import java.text.DecimalFormat;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestDocBoost.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestDocBoost.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestDocBoost.java	2011-08-29 12:22:46.491459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestDocBoost.java	2011-09-01 16:07:05.415811863 -0400
@@ -56,7 +56,8 @@
 
     final float[] scores = new float[4];
 
-    newSearcher(reader).search
+    IndexSearcher searcher = newSearcher(reader);
+    searcher.search
       (new TermQuery(new Term("field", "word")),
        new Collector() {
          private int base = 0;
@@ -82,7 +83,10 @@
     float lastScore = 0.0f;
 
     for (int i = 0; i < 2; i++) {
-      assertTrue(scores[i] > lastScore);
+      if (VERBOSE) {
+        System.out.println(searcher.explain(new TermQuery(new Term("field", "word")), i));
+      }
+      assertTrue("score: " + scores[i] + " should be > lastScore: " + lastScore, scores[i] > lastScore);
       lastScore = scores[i];
     }
     


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestDocValuesScoring.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestDocValuesScoring.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestDocValuesScoring.java	2011-08-29 12:22:46.471459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestDocValuesScoring.java	2011-08-29 21:42:38.141459504 -0400
@@ -30,6 +30,9 @@
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.codecs.CodecProvider;
 import org.apache.lucene.index.values.IndexDocValues.Source;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.LuceneTestCase;
@@ -71,13 +74,24 @@
     
     // no boosting
     IndexSearcher searcher1 = newSearcher(ir);
+    final SimilarityProvider base = searcher1.getSimilarityProvider();
     // boosting
     IndexSearcher searcher2 = newSearcher(ir);
-    searcher2.setSimilarityProvider(new DefaultSimilarityProvider() {
-      final Similarity fooSim = new BoostingSimilarity(super.get("foo"), "foo_boost");
+    searcher2.setSimilarityProvider(new SimilarityProvider() {
+      final Similarity fooSim = new BoostingSimilarity(base.get("foo"), "foo_boost");
 
       public Similarity get(String field) {
-        return "foo".equals(field) ? fooSim : super.get(field);
+        return "foo".equals(field) ? fooSim : base.get(field);
+      }
+
+      @Override
+      public float coord(int overlap, int maxOverlap) {
+        return base.coord(overlap, maxOverlap);
+      }
+
+      @Override
+      public float queryNorm(float sumOfSquaredWeights) {
+        return base.queryNorm(sumOfSquaredWeights);
       }
     });
     


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestElevationComparator.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestElevationComparator.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestElevationComparator.java	2011-08-29 12:22:46.491459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestElevationComparator.java	2011-08-30 00:32:35.271459490 -0400
@@ -23,6 +23,7 @@
 import org.apache.lucene.index.*;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.search.FieldValueHitQueue.Entry;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
 import org.apache.lucene.store.*;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.BytesRef;
@@ -41,7 +42,8 @@
         directory,
         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).
             setMaxBufferedDocs(2).
-            setMergePolicy(newLogMergePolicy(1000))
+            setMergePolicy(newLogMergePolicy(1000)).
+            setSimilarityProvider(new DefaultSimilarityProvider())
     );
     writer.addDocument(adoc(new String[] {"id", "a", "title", "ipod", "str_s", "a"}));
     writer.addDocument(adoc(new String[] {"id", "b", "title", "ipod ipod", "str_s", "b"}));
@@ -54,6 +56,7 @@
     writer.close();
 
     IndexSearcher searcher = newSearcher(r);
+    searcher.setSimilarityProvider(new DefaultSimilarityProvider());
 
     runTest(searcher, true);
     runTest(searcher, false);


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestFuzzyQuery2.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestFuzzyQuery2.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestFuzzyQuery2.java	2011-08-29 12:22:46.471459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestFuzzyQuery2.java	2011-08-29 20:35:48.811459510 -0400
@@ -29,6 +29,9 @@
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 
@@ -104,6 +107,21 @@
     if (VERBOSE) {
       System.out.println("TEST: searcher=" + searcher);
     }
+    // even though this uses a boost-only rewrite, this test relies upon queryNorm being the default implementation,
+    // otherwise scores are different!
+    final SimilarityProvider delegate = searcher.getSimilarityProvider();
+    searcher.setSimilarityProvider(new DefaultSimilarityProvider() {
+      @Override
+      public float coord(int overlap, int maxOverlap) {
+        return delegate.coord(overlap, maxOverlap);
+      }
+
+      @Override
+      public Similarity get(String field) {
+        return delegate.get(field);
+      }
+    });
+    
     writer.close();
     String line;
     while ((line = reader.readLine()) != null) {


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java	2011-08-29 12:22:46.491459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java	2011-08-29 13:42:43.521459544 -0400
@@ -37,6 +37,9 @@
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.store.RAMDirectory;
 import org.apache.lucene.util.LuceneTestCase;
 


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java	2011-09-08 17:01:39.436036270 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java	2011-09-08 12:56:38.026030845 -0400
@@ -26,6 +26,9 @@
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
@@ -173,6 +176,19 @@
 
     // test for correct application of query normalization
     // must use a non score normalizing method for this.
+    
+    final SimilarityProvider delegate = search.getSimilarityProvider();
+    search.setSimilarityProvider(new DefaultSimilarityProvider() {
+      @Override
+      public float coord(int overlap, int maxOverlap) {
+        return delegate.coord(overlap, maxOverlap);
+      }
+
+      @Override
+      public Similarity get(String field) {
+        return delegate.get(field);
+      }
+    });
     Query q = csrq("data", "1", "6", T, T);
     q.setBoost(100);
     search.search(q, null, new Collector() {


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestPhraseQuery.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestPhraseQuery.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestPhraseQuery.java	2011-08-29 12:22:46.471459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestPhraseQuery.java	2011-08-29 22:07:07.451459502 -0400
@@ -23,6 +23,7 @@
 import org.apache.lucene.document.*;
 import org.apache.lucene.index.*;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
 import org.apache.lucene.store.*;
 import org.apache.lucene.util.Version;
 import org.apache.lucene.util._TestUtil;
@@ -342,7 +343,10 @@
   
   public void testSlopScoring() throws IOException {
     Directory directory = newDirectory();
-    RandomIndexWriter writer = new RandomIndexWriter(random, directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
+    RandomIndexWriter writer = new RandomIndexWriter(random, directory, 
+        newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random))
+          .setMergePolicy(newLogMergePolicy())
+          .setSimilarityProvider(new DefaultSimilarityProvider()));
 
     Document doc = new Document();
     doc.add(newField("field", "foo firstname lastname foo", TextField.TYPE_STORED));
@@ -360,6 +364,7 @@
     writer.close();
 
     IndexSearcher searcher = newSearcher(reader);
+    searcher.setSimilarityProvider(new DefaultSimilarityProvider());
     PhraseQuery query = new PhraseQuery();
     query.add(new Term("field", "firstname"));
     query.add(new Term("field", "lastname"));


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestSetNorm.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestSetNorm.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestSetNorm.java	2011-08-29 12:22:46.481459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestSetNorm.java	2011-08-29 13:42:23.711459544 -0400
@@ -26,6 +26,7 @@
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
 import org.apache.lucene.store.Directory;
 
 /** Document boost unit test.


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestSimilarity.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestSimilarity.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestSimilarity.java	2011-09-08 17:01:39.436036270 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestSimilarity.java	2011-09-08 12:56:40.886030845 -0400
@@ -27,6 +27,9 @@
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestSimilarityProvider.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestSimilarityProvider.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestSimilarityProvider.java	2011-08-29 12:22:46.481459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestSimilarityProvider.java	2011-08-29 13:42:38.651459544 -0400
@@ -27,6 +27,9 @@
 import org.apache.lucene.index.MultiNorms;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
+import org.apache.lucene.search.similarities.TFIDFSimilarity;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.LuceneTestCase;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestSloppyPhraseQuery.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestSloppyPhraseQuery.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestSloppyPhraseQuery.java	2011-09-08 17:01:39.436036270 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestSloppyPhraseQuery.java	2011-09-08 12:56:37.456030845 -0400
@@ -17,6 +17,8 @@
  * limitations under the License.
  */
 
+import java.io.IOException;
+
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.analysis.MockTokenizer;
@@ -25,6 +27,7 @@
 import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.store.Directory;
@@ -68,9 +71,9 @@
    */
   public void testDoc1_Query1_All_Slops_Should_match() throws Exception {
     for (int slop=0; slop<30; slop++) {
-      float score1 = checkPhraseQuery(DOC_1, QUERY_1, slop, 1);
-      float score2 = checkPhraseQuery(DOC_1_B, QUERY_1, slop, 1);
-      assertTrue("slop="+slop+" score2="+score2+" should be greater than score1 "+score1, score2>score1);
+      float freq1 = checkPhraseQuery(DOC_1, QUERY_1, slop, 1);
+      float freq2 = checkPhraseQuery(DOC_1_B, QUERY_1, slop, 1);
+      assertTrue("slop="+slop+" freq2="+freq2+" should be greater than score1 "+freq1, freq2>freq1);
     }
   }
 
@@ -82,10 +85,10 @@
   public void testDoc2_Query1_Slop_6_or_more_Should_match() throws Exception {
     for (int slop=0; slop<30; slop++) {
       int numResultsExpected = slop<6 ? 0 : 1;
-      float score1 = checkPhraseQuery(DOC_2, QUERY_1, slop, numResultsExpected);
+      float freq1 = checkPhraseQuery(DOC_2, QUERY_1, slop, numResultsExpected);
       if (numResultsExpected>0) {
-        float score2 = checkPhraseQuery(DOC_2_B, QUERY_1, slop, 1);
-        assertTrue("slop="+slop+" score2="+score2+" should be greater than score1 "+score1, score2>score1);
+        float freq2 = checkPhraseQuery(DOC_2_B, QUERY_1, slop, 1);
+        assertTrue("slop="+slop+" freq2="+freq2+" should be greater than freq1 "+freq1, freq2>freq1);
       }
     }
   }
@@ -97,9 +100,9 @@
    */
   public void testDoc2_Query2_All_Slops_Should_match() throws Exception {
     for (int slop=0; slop<30; slop++) {
-      float score1 = checkPhraseQuery(DOC_2, QUERY_2, slop, 1);
-      float score2 = checkPhraseQuery(DOC_2_B, QUERY_2, slop, 1);
-      assertTrue("slop="+slop+" score2="+score2+" should be greater than score1 "+score1, score2>score1);
+      float freq1 = checkPhraseQuery(DOC_2, QUERY_2, slop, 1);
+      float freq2 = checkPhraseQuery(DOC_2_B, QUERY_2, slop, 1);
+      assertTrue("slop="+slop+" freq2="+freq2+" should be greater than freq1 "+freq1, freq2>freq1);
     }
   }
 
@@ -109,9 +112,9 @@
    */
   public void testDoc3_Query1_All_Slops_Should_match() throws Exception {
     for (int slop=0; slop<30; slop++) {
-      float score1 = checkPhraseQuery(DOC_3, QUERY_1, slop, 1);
-      float score2 = checkPhraseQuery(DOC_3_B, QUERY_1, slop, 1);
-      assertTrue("slop="+slop+" score2="+score2+" should be greater than score1 "+score1, score2>score1);
+      float freq1 = checkPhraseQuery(DOC_3, QUERY_1, slop, 1);
+      float freq2 = checkPhraseQuery(DOC_3_B, QUERY_1, slop, 1);
+      assertTrue("slop="+slop+" freq2="+freq2+" should be greater than freq1 "+freq1, freq2>freq1);
     }
   }
 
@@ -140,9 +143,9 @@
     IndexReader reader = writer.getReader();
 
     IndexSearcher searcher = newSearcher(reader);
-    TopDocs td = searcher.search(query,null,10);
-    //System.out.println("slop: "+slop+"  query: "+query+"  doc: "+doc+"  Expecting number of hits: "+expectedNumResults+" maxScore="+td.getMaxScore());
-    assertEquals("slop: "+slop+"  query: "+query+"  doc: "+doc+"  Wrong number of hits", expectedNumResults, td.totalHits);
+    MaxFreqCollector c = new MaxFreqCollector();
+    searcher.search(query, c);
+    assertEquals("slop: "+slop+"  query: "+query+"  doc: "+doc+"  Wrong number of hits", expectedNumResults, c.totalHits);
 
     //QueryUtils.check(query,searcher);
     writer.close();
@@ -150,7 +153,9 @@
     reader.close();
     ramDir.close();
 
-    return td.getMaxScore();
+    // returns the max Scorer.freq() found, because even though norms are omitted, many index stats are different
+    // with these different tokens/distributions/lengths.. otherwise this test is very fragile.
+    return c.max; 
   }
 
   private static Document makeDocument(String docText) {
@@ -171,4 +176,29 @@
     return query;
   }
 
+  static class MaxFreqCollector extends Collector {
+    float max;
+    int totalHits;
+    Scorer scorer;
+    
+    @Override
+    public void setScorer(Scorer scorer) throws IOException {
+      this.scorer = scorer;
+    }
+
+    @Override
+    public void collect(int doc) throws IOException {
+      totalHits++;
+      max = Math.max(max, scorer.freq());
+    }
+
+    @Override
+    public void setNextReader(AtomicReaderContext context) throws IOException {      
+    }
+
+    @Override
+    public boolean acceptsDocsOutOfOrder() {
+      return false;
+    }
+  }
 }


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestTermScorer.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestTermScorer.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestTermScorer.java	2011-08-29 12:22:46.481459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestTermScorer.java	2011-08-29 20:14:51.561459511 -0400
@@ -30,6 +30,7 @@
 import org.apache.lucene.index.SlowMultiReaderWrapper;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.Weight.ScorerContext;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 
@@ -47,7 +48,10 @@
     super.setUp();
     directory = newDirectory();
     
-    RandomIndexWriter writer = new RandomIndexWriter(random, directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
+    RandomIndexWriter writer = new RandomIndexWriter(random, directory, 
+        newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random))
+        .setMergePolicy(newLogMergePolicy())
+        .setSimilarityProvider(new DefaultSimilarityProvider()));
     for (int i = 0; i < values.length; i++) {
       Document doc = new Document();
       doc
@@ -57,6 +61,7 @@
     indexReader = new SlowMultiReaderWrapper(writer.getReader());
     writer.close();
     indexSearcher = newSearcher(indexReader);
+    indexSearcher.setSimilarityProvider(new DefaultSimilarityProvider());
   }
   
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestTermVectors.java lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestTermVectors.java
--- lucene-clean-trunk/lucene/src/test/org/apache/lucene/search/TestTermVectors.java	2011-08-29 12:22:46.471459551 -0400
+++ lucene-flexscoring/lucene/src/test/org/apache/lucene/search/TestTermVectors.java	2011-08-29 22:32:55.801459500 -0400
@@ -28,6 +28,7 @@
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.*;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.English;
 
@@ -244,7 +245,9 @@
     
     RandomIndexWriter writer = new RandomIndexWriter(random, dir, 
         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.SIMPLE, true))
-                                                     .setOpenMode(OpenMode.CREATE).setMergePolicy(newLogMergePolicy()));
+          .setOpenMode(OpenMode.CREATE)
+          .setMergePolicy(newLogMergePolicy())
+          .setSimilarityProvider(new DefaultSimilarityProvider()));
     writer.addDocument(testDoc1);
     writer.addDocument(testDoc2);
     writer.addDocument(testDoc3);
@@ -252,6 +255,7 @@
     IndexReader reader = writer.getReader();
     writer.close();
     IndexSearcher knownSearcher = newSearcher(reader);
+    knownSearcher.setSimilarityProvider(new DefaultSimilarityProvider());
     FieldsEnum fields = MultiFields.getFields(knownSearcher.reader).iterator();
     
     DocsEnum docs = null;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test-framework/org/apache/lucene/index/DocHelper.java lucene-flexscoring/lucene/src/test-framework/org/apache/lucene/index/DocHelper.java
--- lucene-clean-trunk/lucene/src/test-framework/org/apache/lucene/index/DocHelper.java	2011-08-29 12:22:46.931459551 -0400
+++ lucene-flexscoring/lucene/src/test-framework/org/apache/lucene/index/DocHelper.java	2011-08-29 14:04:40.141459542 -0400
@@ -33,7 +33,7 @@
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.TextField;
-import org.apache.lucene.search.SimilarityProvider;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 
 import static org.apache.lucene.util.LuceneTestCase.TEST_VERSION_CURRENT;


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test-framework/org/apache/lucene/search/CheckHits.java lucene-flexscoring/lucene/src/test-framework/org/apache/lucene/search/CheckHits.java
--- lucene-clean-trunk/lucene/src/test-framework/org/apache/lucene/search/CheckHits.java	2011-07-08 01:31:28.441820268 -0400
+++ lucene-flexscoring/lucene/src/test-framework/org/apache/lucene/search/CheckHits.java	2011-09-09 11:40:56.936061055 -0400
@@ -18,6 +18,7 @@
  */
 
 import java.io.IOException;
+import java.util.Locale;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.Random;
@@ -35,7 +36,7 @@
    * different  order of operations from the actual scoring method ...
    * this allows for a small amount of variation
    */
-  public static float EXPLAIN_SCORE_TOLERANCE_DELTA = 0.0002f;
+  public static float EXPLAIN_SCORE_TOLERANCE_DELTA = 0.02f;
     
   /**
    * Tests that all documents up to maxDoc which are *not* in the
@@ -327,6 +328,10 @@
     if (!deep) return;
 
     Explanation detail[] = expl.getDetails();
+    // TODO: can we improve this entire method? its really geared to work only with TF/IDF
+    if (expl.getDescription().endsWith("computed from:")) {
+      return; // something more complicated.
+    }
     if (detail!=null) {
       if (detail.length==1) {
         // simple containment, unless its a freq of: (which lets a query explain how the freq is calculated), 
@@ -338,7 +343,7 @@
         // - end with one of: "product of:", "sum of:", "max of:", or
         // - have "max plus <x> times others" (where <x> is float).
         float x = 0;
-        String descr = expl.getDescription().toLowerCase();
+        String descr = expl.getDescription().toLowerCase(Locale.ENGLISH);
         boolean productOf = descr.endsWith("product of:");
         boolean sumOf = descr.endsWith("sum of:");
         boolean maxOf = descr.endsWith("max of:");


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test-framework/org/apache/lucene/search/RandomSimilarityProvider.java lucene-flexscoring/lucene/src/test-framework/org/apache/lucene/search/RandomSimilarityProvider.java
--- lucene-clean-trunk/lucene/src/test-framework/org/apache/lucene/search/RandomSimilarityProvider.java	1969-12-31 19:00:00.000000000 -0500
+++ lucene-flexscoring/lucene/src/test-framework/org/apache/lucene/search/RandomSimilarityProvider.java	2011-09-09 11:45:30.366061155 -0400
@@ -0,0 +1,158 @@
+package org.apache.lucene.search;
+
+/**
+ * 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.
+ */
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import org.apache.lucene.search.similarities.AfterEffect;
+import org.apache.lucene.search.similarities.AfterEffectB;
+import org.apache.lucene.search.similarities.AfterEffectL;
+import org.apache.lucene.search.similarities.BM25Similarity;
+import org.apache.lucene.search.similarities.BasicModel;
+import org.apache.lucene.search.similarities.BasicModelBE;
+import org.apache.lucene.search.similarities.BasicModelD;
+import org.apache.lucene.search.similarities.BasicModelG;
+import org.apache.lucene.search.similarities.BasicModelIF;
+import org.apache.lucene.search.similarities.BasicModelIn;
+import org.apache.lucene.search.similarities.BasicModelIne;
+import org.apache.lucene.search.similarities.BasicModelP;
+import org.apache.lucene.search.similarities.DFRSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Distribution;
+import org.apache.lucene.search.similarities.DistributionLL;
+import org.apache.lucene.search.similarities.DistributionSPL;
+import org.apache.lucene.search.similarities.IBSimilarity;
+import org.apache.lucene.search.similarities.LMDirichletSimilarity;
+import org.apache.lucene.search.similarities.LMJelinekMercerSimilarity;
+import org.apache.lucene.search.similarities.Lambda;
+import org.apache.lucene.search.similarities.LambdaDF;
+import org.apache.lucene.search.similarities.LambdaTTF;
+import org.apache.lucene.search.similarities.Normalization;
+import org.apache.lucene.search.similarities.NormalizationH1;
+import org.apache.lucene.search.similarities.NormalizationH2;
+import org.apache.lucene.search.similarities.NormalizationH3;
+import org.apache.lucene.search.similarities.NormalizationZ;
+import org.apache.lucene.search.similarities.Similarity;
+
+public class RandomSimilarityProvider extends DefaultSimilarityProvider {
+  final List<Similarity> knownSims;
+  Map<String,Similarity> previousMappings = new HashMap<String,Similarity>();
+  final int perFieldSeed;
+  final boolean shouldCoord;
+  final boolean shouldQueryNorm;
+  
+  public RandomSimilarityProvider(Random random) {
+    perFieldSeed = random.nextInt();
+    shouldCoord = random.nextBoolean();
+    shouldQueryNorm = random.nextBoolean();
+    knownSims = new ArrayList<Similarity>(allSims);
+    Collections.shuffle(knownSims, random);
+  }
+  
+  @Override
+  public float coord(int overlap, int maxOverlap) {
+    if (shouldCoord) {
+      return super.coord(overlap, maxOverlap);
+    } else {
+      return 1.0f;
+    }
+  }
+  
+  @Override
+  public float queryNorm(float sumOfSquaredWeights) {
+    if (shouldQueryNorm) {
+      return super.queryNorm(sumOfSquaredWeights);
+    } else {
+      return 1.0f;
+    }
+  }
+  
+  @Override
+  public synchronized Similarity get(String field) {
+    assert field != null;
+    Similarity sim = previousMappings.get(field);
+    if (sim == null) {
+      sim = knownSims.get(Math.abs(perFieldSeed ^ field.hashCode()) % knownSims.size());
+      previousMappings.put(field, sim);
+    }
+    return sim;
+  }
+  
+  // all the similarities that we rotate through
+  /** The DFR basic models to test. */
+  static BasicModel[] BASIC_MODELS = {
+    new BasicModelBE(), /* TODO: enable new BasicModelD(), */ new BasicModelG(),
+    new BasicModelIF(), new BasicModelIn(), new BasicModelIne(),
+    /* TODO: enable new BasicModelP() */
+  };
+  /** The DFR aftereffects to test. */
+  static AfterEffect[] AFTER_EFFECTS = {
+    new AfterEffectB(), new AfterEffectL(), new AfterEffect.NoAfterEffect()
+  };
+  /** The DFR normalizations to test. */
+  static Normalization[] NORMALIZATIONS = {
+    new NormalizationH1(), new NormalizationH2(),
+    new NormalizationH3(), new NormalizationZ()
+    // TODO: if we enable NoNormalization, we have to deal with
+    // a couple tests (e.g. TestDocBoost, TestSort) that expect length normalization
+    // new Normalization.NoNormalization()
+  };
+  /** The distributions for IB. */
+  static Distribution[] DISTRIBUTIONS = {
+    new DistributionLL(), new DistributionSPL()
+  };
+  /** Lambdas for IB. */
+  static Lambda[] LAMBDAS = {
+    new LambdaDF(), new LambdaTTF()
+  };
+  static List<Similarity> allSims;
+  static {
+    allSims = new ArrayList<Similarity>();
+    allSims.add(new DefaultSimilarity());
+    allSims.add(new BM25Similarity());
+    for (BasicModel basicModel : BASIC_MODELS) {
+      for (AfterEffect afterEffect : AFTER_EFFECTS) {
+        for (Normalization normalization : NORMALIZATIONS) {
+          allSims.add(new DFRSimilarity(basicModel, afterEffect, normalization));
+        }
+      }
+    }
+    for (Distribution distribution : DISTRIBUTIONS) {
+      for (Lambda lambda : LAMBDAS) {
+        for (Normalization normalization : NORMALIZATIONS) {
+          allSims.add(new IBSimilarity(distribution, lambda, normalization));
+        }
+      }
+    }
+    /* TODO: enable Dirichlet 
+    allSims.add(new LMDirichletSimilarity()); */
+    allSims.add(new LMJelinekMercerSimilarity(0.1f));
+    allSims.add(new LMJelinekMercerSimilarity(0.7f));
+  }
+  
+  @Override
+  public synchronized String toString() {
+    return "RandomSimilarityProvider(queryNorm=" + shouldQueryNorm + ",coord=" + shouldCoord + "): " + previousMappings.toString();
+  }
+}


diff -ruN -x .svn -x build lucene-clean-trunk/lucene/src/test-framework/org/apache/lucene/util/LuceneTestCase.java lucene-flexscoring/lucene/src/test-framework/org/apache/lucene/util/LuceneTestCase.java
--- lucene-clean-trunk/lucene/src/test-framework/org/apache/lucene/util/LuceneTestCase.java	2011-08-29 12:22:46.941459551 -0400
+++ lucene-flexscoring/lucene/src/test-framework/org/apache/lucene/util/LuceneTestCase.java	2011-09-01 15:12:57.025810663 -0400
@@ -52,6 +52,8 @@
 import org.apache.lucene.search.FieldCache.CacheEntry;
 import org.apache.lucene.search.AssertingIndexSearcher;
 import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.RandomSimilarityProvider;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.FSDirectory;
 import org.apache.lucene.store.FlushInfo;
@@ -209,6 +211,8 @@
   private static Codec codec;
   // default codec provider
   private static CodecProvider savedCodecProvider;
+  
+  private static SimilarityProvider similarityProvider;
 
   private static Locale locale;
   private static Locale savedLocale;
@@ -393,6 +397,7 @@
     savedTimeZone = TimeZone.getDefault();
     timeZone = TEST_TIMEZONE.equals("random") ? randomTimeZone(random) : TimeZone.getTimeZone(TEST_TIMEZONE);
     TimeZone.setDefault(timeZone);
+    similarityProvider = new RandomSimilarityProvider(random);
     testsFailed = false;
   }
 
@@ -467,6 +472,7 @@
   /** print some useful debugging information about the environment */
   private static void printDebuggingInformation(String codecDescription) {
     System.err.println("NOTE: test params are: codec=" + codecDescription +
+        ", sim=" + similarityProvider +
         ", locale=" + locale +
         ", timezone=" + (timeZone == null ? "(null)" : timeZone.getID()));
     System.err.println("NOTE: all tests run in this JVM:");
@@ -943,6 +949,7 @@
   /** create a new index writer config with random defaults using the specified random */
   public static IndexWriterConfig newIndexWriterConfig(Random r, Version v, Analyzer a) {
     IndexWriterConfig c = new IndexWriterConfig(v, a);
+    c.setSimilarityProvider(similarityProvider);
     if (r.nextBoolean()) {
       c.setMergeScheduler(new SerialMergeScheduler());
     }
@@ -1270,7 +1277,9 @@
       if (maybeWrap && rarely()) {
         r = new SlowMultiReaderWrapper(r);
       }
-      return random.nextBoolean() ? new AssertingIndexSearcher(r) : new AssertingIndexSearcher(r.getTopReaderContext());
+      IndexSearcher ret = random.nextBoolean() ? new AssertingIndexSearcher(r) : new AssertingIndexSearcher(r.getTopReaderContext());
+      ret.setSimilarityProvider(similarityProvider);
+      return ret;
     } else {
       int threads = 0;
       final ExecutorService ex = (random.nextBoolean()) ? null
@@ -1279,7 +1288,7 @@
       if (ex != null && VERBOSE) {
         System.out.println("NOTE: newSearcher using ExecutorService with " + threads + " threads");
       }
-      return random.nextBoolean() ? 
+      IndexSearcher ret = random.nextBoolean() ? 
         new AssertingIndexSearcher(r, ex) {
           @Override
           public void close() throws IOException {
@@ -1293,6 +1302,8 @@
             shutdownExecutorService(ex);
           }
         };
+      ret.setSimilarityProvider(similarityProvider);
+      return ret;
     }
   }
   


diff -ruN -x .svn -x build lucene-clean-trunk/modules/queries/src/java/org/apache/lucene/queries/function/valuesource/IDFValueSource.java lucene-flexscoring/modules/queries/src/java/org/apache/lucene/queries/function/valuesource/IDFValueSource.java
--- lucene-clean-trunk/modules/queries/src/java/org/apache/lucene/queries/function/valuesource/IDFValueSource.java	2011-07-08 01:31:28.271820268 -0400
+++ lucene-flexscoring/modules/queries/src/java/org/apache/lucene/queries/function/valuesource/IDFValueSource.java	2011-08-23 08:43:39.761460295 -0400
@@ -21,8 +21,8 @@
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.queries.function.DocValues;
 import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.Similarity;
-import org.apache.lucene.search.TFIDFSimilarity;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.TFIDFSimilarity;
 import org.apache.lucene.util.BytesRef;
 
 import java.io.IOException;


diff -ruN -x .svn -x build lucene-clean-trunk/modules/queries/src/java/org/apache/lucene/queries/function/valuesource/NormValueSource.java lucene-flexscoring/modules/queries/src/java/org/apache/lucene/queries/function/valuesource/NormValueSource.java
--- lucene-clean-trunk/modules/queries/src/java/org/apache/lucene/queries/function/valuesource/NormValueSource.java	2011-07-08 01:31:28.271820268 -0400
+++ lucene-flexscoring/modules/queries/src/java/org/apache/lucene/queries/function/valuesource/NormValueSource.java	2011-08-23 08:43:39.761460295 -0400
@@ -22,8 +22,8 @@
 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.search.Similarity;
-import org.apache.lucene.search.TFIDFSimilarity;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.TFIDFSimilarity;
 
 import java.io.IOException;
 import java.util.Map;


diff -ruN -x .svn -x build lucene-clean-trunk/modules/queries/src/java/org/apache/lucene/queries/function/valuesource/TFValueSource.java lucene-flexscoring/modules/queries/src/java/org/apache/lucene/queries/function/valuesource/TFValueSource.java
--- lucene-clean-trunk/modules/queries/src/java/org/apache/lucene/queries/function/valuesource/TFValueSource.java	2011-07-08 01:31:28.271820268 -0400
+++ lucene-flexscoring/modules/queries/src/java/org/apache/lucene/queries/function/valuesource/TFValueSource.java	2011-08-23 08:43:39.761460295 -0400
@@ -23,8 +23,8 @@
 import org.apache.lucene.queries.function.docvalues.FloatDocValues;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.Similarity;
-import org.apache.lucene.search.TFIDFSimilarity;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.TFIDFSimilarity;
 import org.apache.lucene.util.BytesRef;
 
 import java.io.IOException;


diff -ruN -x .svn -x build lucene-clean-trunk/modules/queries/src/java/org/apache/lucene/queries/mlt/MoreLikeThis.java lucene-flexscoring/modules/queries/src/java/org/apache/lucene/queries/mlt/MoreLikeThis.java
--- lucene-clean-trunk/modules/queries/src/java/org/apache/lucene/queries/mlt/MoreLikeThis.java	2011-08-29 12:22:46.101459551 -0400
+++ lucene-flexscoring/modules/queries/src/java/org/apache/lucene/queries/mlt/MoreLikeThis.java	2011-08-29 14:05:15.661459542 -0400
@@ -24,6 +24,8 @@
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermFreqVector;
 import org.apache.lucene.search.*;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.TFIDFSimilarity;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.CharsRef;
 import org.apache.lucene.util.PriorityQueue;


diff -ruN -x .svn -x build lucene-clean-trunk/modules/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/StandardBooleanQueryNodeBuilder.java lucene-flexscoring/modules/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/StandardBooleanQueryNodeBuilder.java
--- lucene-clean-trunk/modules/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/StandardBooleanQueryNodeBuilder.java	2011-07-17 06:27:34.778948134 -0400
+++ lucene-flexscoring/modules/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/StandardBooleanQueryNodeBuilder.java	2011-08-23 08:43:39.761460295 -0400
@@ -31,8 +31,8 @@
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.Query;
-import org.apache.lucene.search.SimilarityProvider;
 import org.apache.lucene.search.BooleanQuery.TooManyClauses;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 
 /**
  * This builder does the same as the {@link BooleanQueryNodeBuilder}, but this


diff -ruN -x .svn -x build lucene-clean-trunk/modules/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/StandardBooleanQueryNode.java lucene-flexscoring/modules/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/StandardBooleanQueryNode.java
--- lucene-clean-trunk/modules/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/StandardBooleanQueryNode.java	2011-07-17 06:27:34.758948134 -0400
+++ lucene-flexscoring/modules/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/nodes/StandardBooleanQueryNode.java	2011-08-23 08:43:39.761460295 -0400
@@ -22,7 +22,7 @@
 import org.apache.lucene.queryparser.flexible.core.nodes.BooleanQueryNode;
 import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
 import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.SimilarityProvider;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 
 /**
  * A {@link StandardBooleanQueryNode} has the same behavior as


diff -ruN -x .svn -x build lucene-clean-trunk/solr/CHANGES.txt lucene-flexscoring/solr/CHANGES.txt
--- lucene-clean-trunk/solr/CHANGES.txt	2011-09-08 17:00:40.726036249 -0400
+++ lucene-flexscoring/solr/CHANGES.txt	2011-09-09 12:08:04.286061654 -0400
@@ -19,7 +19,7 @@
 See the tutorial at http://lucene.apache.org/solr/tutorial.html
 
 
-$Id: CHANGES.txt 1166866 2011-09-08 19:27:40Z yonik $
+$Id: CHANGES.txt 1167270 2011-09-09 16:07:58Z rmuir $
 
 ==================  4.0.0-dev ==================
 Versions of Major Components


diff -ruN -x .svn -x build lucene-clean-trunk/solr/client/ruby/solr-ruby/solr/conf/schema.xml lucene-flexscoring/solr/client/ruby/solr-ruby/solr/conf/schema.xml
--- lucene-clean-trunk/solr/client/ruby/solr-ruby/solr/conf/schema.xml	2011-05-08 10:52:01.280078712 -0400
+++ lucene-flexscoring/solr/client/ruby/solr-ruby/solr/conf/schema.xml	2011-08-23 08:43:39.771460295 -0400
@@ -217,6 +217,6 @@
  <!-- Similarity is the scoring routine for each document vs. a query.
       A custom similarity may be specified here, but the default is fine
       for most applications.  -->
- <!-- <similarity class="org.apache.lucene.search.DefaultSimilarity"/> -->
+ <!-- <similarity class="org.apache.lucene.search.similarities.DefaultSimilarity"/> -->
 
 </schema>


diff -ruN -x .svn -x build lucene-clean-trunk/solr/client/ruby/solr-ruby/test/conf/schema.xml lucene-flexscoring/solr/client/ruby/solr-ruby/test/conf/schema.xml
--- lucene-clean-trunk/solr/client/ruby/solr-ruby/test/conf/schema.xml	2011-05-08 10:52:01.320078712 -0400
+++ lucene-flexscoring/solr/client/ruby/solr-ruby/test/conf/schema.xml	2011-08-23 08:43:39.771460295 -0400
@@ -235,6 +235,6 @@
  <!-- Similarity is the scoring routine for each document vs. a query.
       A custom similarity may be specified here, but the default is fine
       for most applications.  -->
- <!-- <similarity class="org.apache.lucene.search.DefaultSimilarity"/> -->
+ <!-- <similarity class="org.apache.lucene.search.similarities.DefaultSimilarity"/> -->
 
 </schema>


diff -ruN -x .svn -x build lucene-clean-trunk/solr/contrib/dataimporthandler/CHANGES.txt lucene-flexscoring/solr/contrib/dataimporthandler/CHANGES.txt
--- lucene-clean-trunk/solr/contrib/dataimporthandler/CHANGES.txt	2011-09-08 17:00:37.326036247 -0400
+++ lucene-flexscoring/solr/contrib/dataimporthandler/CHANGES.txt	2011-09-08 13:27:31.116031529 -0400
@@ -7,7 +7,7 @@
 HTTP data sources quick and easy.
 
 
-$Id: CHANGES.txt 1166652 2011-09-08 12:24:16Z rmuir $
+$Id: CHANGES.txt 1166817 2011-09-08 17:27:25Z rmuir $
 ==================  4.0.0-dev ==============
 
 (No Changes)


diff -ruN -x .svn -x build lucene-clean-trunk/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DataImportHandler.java lucene-flexscoring/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DataImportHandler.java
--- lucene-clean-trunk/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DataImportHandler.java	2011-08-02 10:29:53.402327840 -0400
+++ lucene-flexscoring/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DataImportHandler.java	2011-08-23 10:07:05.901460288 -0400
@@ -339,7 +339,7 @@
 
   @Override
   public String getSourceId() {
-    return "$Id: DataImportHandler.java 1152692 2011-08-01 06:01:35Z noble $";
+    return "$Id: DataImportHandler.java 1160700 2011-08-23 14:06:58Z rmuir $";
   }
 
   @Override
@@ -349,7 +349,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DataImportHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DataImportHandler.java $";
   }
 
   public static final String ENABLE_DEBUG = "enableDebug";


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/core/RequestHandlers.java lucene-flexscoring/solr/core/src/java/org/apache/solr/core/RequestHandlers.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/core/RequestHandlers.java	2011-07-11 21:29:55.161819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/core/RequestHandlers.java	2011-08-05 09:11:33.222327484 -0400
@@ -299,7 +299,7 @@
     }
 
     public String getSource() {
-      String rev = "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/RequestHandlers.java $";
+      String rev = "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/core/RequestHandlers.java $";
       if( _handler != null ) {
         rev += "\n" + _handler.getSource();
       }


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/core/SolrCore.java lucene-flexscoring/solr/core/src/java/org/apache/solr/core/SolrCore.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/core/SolrCore.java	2011-09-08 17:00:37.186036247 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/core/SolrCore.java	2011-09-08 13:27:31.236031529 -0400
@@ -1713,11 +1713,11 @@
   }
 
   public String getSourceId() {
-    return "$Id: SolrCore.java 1165869 2011-09-06 21:37:32Z yonik $";
+    return "$Id: SolrCore.java 1166817 2011-09-08 17:27:25Z rmuir $";
   }
 
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrCore.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/core/SolrCore.java $";
   }
 
   public URL[] getDocs() {


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/AdminHandlers.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/AdminHandlers.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/AdminHandlers.java	2011-07-11 21:30:07.701819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/AdminHandlers.java	2011-08-05 09:11:33.262327484 -0400
@@ -121,7 +121,7 @@
   }
 
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/admin/AdminHandlers.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/admin/AdminHandlers.java $";
   }
 
   public Category getCategory() {


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java	2011-08-29 12:22:45.751459551 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java	2011-08-29 19:13:20.361459517 -0400
@@ -602,16 +602,16 @@
 
   @Override
   public String getVersion() {
-    return "$Revision: 1162394 $";
+    return "$Revision: 1163047 $";
   }
 
   @Override
   public String getSourceId() {
-    return "$Id: CoreAdminHandler.java 1162394 2011-08-27 16:25:46Z mikemccand $";
+    return "$Id: CoreAdminHandler.java 1163047 2011-08-29 23:13:10Z rmuir $";
   }
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java $";
   }
 }


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java	2011-08-29 12:22:45.751459551 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java	2011-08-29 19:13:20.361459517 -0400
@@ -509,17 +509,17 @@
 
   @Override
   public String getVersion() {
-    return "$Revision: 1162347 $";
+    return "$Revision: 1163047 $";
   }
 
   @Override
   public String getSourceId() {
-    return "$Id: LukeRequestHandler.java 1162347 2011-08-27 13:27:01Z mikemccand $";
+    return "$Id: LukeRequestHandler.java 1163047 2011-08-29 23:13:10Z rmuir $";
   }
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/PluginInfoHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/PluginInfoHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/PluginInfoHandler.java	2011-07-11 21:30:07.701819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/PluginInfoHandler.java	2011-08-05 09:11:33.262327484 -0400
@@ -111,6 +111,6 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/admin/PluginInfoHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/admin/PluginInfoHandler.java $";
   }
 }


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/PropertiesRequestHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/PropertiesRequestHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/PropertiesRequestHandler.java	2011-07-11 21:30:07.701819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/PropertiesRequestHandler.java	2011-08-05 09:11:33.262327484 -0400
@@ -66,6 +66,6 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/admin/PropertiesRequestHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/admin/PropertiesRequestHandler.java $";
   }
 }


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java	2011-07-17 06:27:34.458948135 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java	2011-08-05 09:11:33.262327484 -0400
@@ -233,6 +233,6 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/admin/ShowFileRequestHandler.java $";
   }
 }


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/SolrInfoMBeanHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/SolrInfoMBeanHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/SolrInfoMBeanHandler.java	2011-07-11 21:30:07.701819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/SolrInfoMBeanHandler.java	2011-08-05 09:11:33.262327484 -0400
@@ -107,7 +107,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/admin/SolrInfoMBeanHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/admin/SolrInfoMBeanHandler.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/SystemInfoHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/SystemInfoHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/SystemInfoHandler.java	2011-07-11 21:30:07.701819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/SystemInfoHandler.java	2011-08-05 09:11:33.262327484 -0400
@@ -292,7 +292,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/admin/SystemInfoHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/admin/SystemInfoHandler.java $";
   }
   
   private static final long ONE_KB = 1024;


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/ThreadDumpHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/ThreadDumpHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/admin/ThreadDumpHandler.java	2011-07-11 21:30:07.701819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/admin/ThreadDumpHandler.java	2011-08-05 09:11:33.262327484 -0400
@@ -144,6 +144,6 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/admin/ThreadDumpHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/admin/ThreadDumpHandler.java $";
   }
 }


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/BinaryUpdateRequestHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/BinaryUpdateRequestHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/BinaryUpdateRequestHandler.java	2011-09-08 17:00:37.196036247 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/BinaryUpdateRequestHandler.java	2011-09-08 13:27:31.366031529 -0400
@@ -119,16 +119,16 @@
 
   @Override
   public String getSourceId() {
-    return "$Id: BinaryUpdateRequestHandler.java 1165754 2011-09-06 16:27:20Z janhoy $";
+    return "$Id: BinaryUpdateRequestHandler.java 1166817 2011-09-08 17:27:25Z rmuir $";
   }
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/BinaryUpdateRequestHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/BinaryUpdateRequestHandler.java $";
   }
 
   @Override
   public String getVersion() {
-    return "$Revision: 1165754 $";
+    return "$Revision: 1166817 $";
   }
 }


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/DebugComponent.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/DebugComponent.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/DebugComponent.java	2011-07-11 21:30:20.691819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/DebugComponent.java	2011-08-05 09:11:33.302327484 -0400
@@ -260,7 +260,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/component/DebugComponent.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/component/DebugComponent.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java	2011-07-31 23:12:09.602328018 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java	2011-08-23 10:07:05.551460288 -0400
@@ -593,17 +593,17 @@
 
   @Override
   public String getVersion() {
-    return "$Revision: 1152530 $";
+    return "$Revision: 1160700 $";
   }
 
   @Override
   public String getSourceId() {
-    return "$Id: FacetComponent.java 1152530 2011-07-31 00:30:19Z koji $";
+    return "$Id: FacetComponent.java 1160700 2011-08-23 14:06:58Z rmuir $";
   }
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/HighlightComponent.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/HighlightComponent.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/HighlightComponent.java	2011-07-11 21:30:20.701819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/HighlightComponent.java	2011-08-05 09:11:33.302327484 -0400
@@ -199,7 +199,7 @@
   
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/component/HighlightComponent.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/component/HighlightComponent.java $";
   }
   
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/MoreLikeThisComponent.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/MoreLikeThisComponent.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/MoreLikeThisComponent.java	2011-07-11 21:30:20.701819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/MoreLikeThisComponent.java	2011-08-05 09:11:33.302327484 -0400
@@ -128,7 +128,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/component/MoreLikeThisComponent.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/component/MoreLikeThisComponent.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/PivotFacetHelper.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/PivotFacetHelper.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/PivotFacetHelper.java	2011-07-11 21:30:20.691819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/PivotFacetHelper.java	2011-08-05 09:11:33.302327484 -0400
@@ -249,7 +249,7 @@
 //  }
 //
 //  public String getSource() {
-//    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/component/PivotFacetHelper.java $";
+//    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/component/PivotFacetHelper.java $";
 //  }
 //
 //  public String getVersion() {


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java	2011-08-29 12:22:45.751459551 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java	2011-08-29 19:13:20.391459517 -0400
@@ -817,17 +817,17 @@
 
   @Override
   public String getVersion() {
-    return "$Revision: 1162347 $";
+    return "$Revision: 1163047 $";
   }
 
   @Override
   public String getSourceId() {
-    return "$Id: QueryComponent.java 1162347 2011-08-27 13:27:01Z mikemccand $";
+    return "$Id: QueryComponent.java 1163047 2011-08-29 23:13:10Z rmuir $";
   }
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/QueryElevationComponent.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/QueryElevationComponent.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/QueryElevationComponent.java	2011-07-11 21:30:20.691819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/QueryElevationComponent.java	2011-08-05 09:11:33.302327484 -0400
@@ -451,7 +451,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/component/QueryElevationComponent.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/component/QueryElevationComponent.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java	2011-09-08 17:00:37.186036247 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java	2011-09-08 13:27:31.226031529 -0400
@@ -210,17 +210,17 @@
 
   @Override
   public String getVersion() {
-    return "$Revision: 1165869 $";
+    return "$Revision: 1166817 $";
   }
 
   @Override
   public String getSourceId() {
-    return "$Id: RealTimeGetComponent.java 1165869 2011-09-06 21:37:32Z yonik $";
+    return "$Id: RealTimeGetComponent.java 1166817 2011-09-08 17:27:25Z rmuir $";
   }
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java	2011-07-11 21:30:20.691819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java	2011-08-05 09:11:33.302327484 -0400
@@ -330,7 +330,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java $";
   }
 }
 


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/SpellCheckComponent.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/SpellCheckComponent.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/SpellCheckComponent.java	2011-08-08 07:55:46.092327127 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/SpellCheckComponent.java	2011-08-23 10:07:05.551460288 -0400
@@ -726,17 +726,17 @@
 
   @Override
   public String getVersion() {
-    return "$Revision: 1154935 $";
+    return "$Revision: 1160700 $";
   }
 
   @Override
   public String getSourceId() {
-    return "$Id: SpellCheckComponent.java 1154935 2011-08-08 11:55:03Z rmuir $";
+    return "$Id: SpellCheckComponent.java 1160700 2011-08-23 14:06:58Z rmuir $";
   }
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/component/SpellCheckComponent.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/component/SpellCheckComponent.java $";
   }
 
 }


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java	2011-07-11 21:30:20.701819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java	2011-08-05 09:11:33.302327484 -0400
@@ -163,7 +163,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/component/StatsComponent.java $";
   }
 
 }


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/TermsComponent.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/TermsComponent.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/TermsComponent.java	2011-07-11 21:30:20.701819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/TermsComponent.java	2011-08-05 09:11:33.302327484 -0400
@@ -483,7 +483,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/component/TermsComponent.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/component/TermsComponent.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/TermVectorComponent.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/TermVectorComponent.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/component/TermVectorComponent.java	2011-08-29 12:22:45.751459551 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/component/TermVectorComponent.java	2011-08-29 19:13:20.391459517 -0400
@@ -419,17 +419,17 @@
 
   @Override
   public String getVersion() {
-    return "$Revision: 1162347 $";
+    return "$Revision: 1163047 $";
   }
 
   @Override
   public String getSourceId() {
-    return "$Id: TermVectorComponent.java 1162347 2011-08-27 13:27:01Z mikemccand $";
+    return "$Id: TermVectorComponent.java 1163047 2011-08-29 23:13:10Z rmuir $";
   }
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/component/TermVectorComponent.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/component/TermVectorComponent.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/CSVRequestHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/CSVRequestHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/CSVRequestHandler.java	2011-09-08 17:00:37.196036247 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/CSVRequestHandler.java	2011-09-08 13:27:31.366031529 -0400
@@ -61,17 +61,17 @@
 
   @Override
   public String getVersion() {
-    return "$Revision: 1165754 $";
+    return "$Revision: 1166817 $";
   }
 
   @Override
   public String getSourceId() {
-    return "$Id: CSVRequestHandler.java 1165754 2011-09-06 16:27:20Z janhoy $";
+    return "$Id: CSVRequestHandler.java 1166817 2011-09-08 17:27:25Z rmuir $";
   }
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/CSVRequestHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/CSVRequestHandler.java $";
   }
 }
 


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/DocumentAnalysisRequestHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/DocumentAnalysisRequestHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/DocumentAnalysisRequestHandler.java	2011-07-11 21:30:24.421819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/DocumentAnalysisRequestHandler.java	2011-08-05 09:11:33.322327484 -0400
@@ -132,7 +132,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/DocumentAnalysisRequestHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/DocumentAnalysisRequestHandler.java $";
   }
 
 


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/DumpRequestHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/DumpRequestHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/DumpRequestHandler.java	2011-07-11 21:30:24.421819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/DumpRequestHandler.java	2011-08-05 09:11:33.312327484 -0400
@@ -79,6 +79,6 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/DumpRequestHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/DumpRequestHandler.java $";
   }
 }


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/FieldAnalysisRequestHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/FieldAnalysisRequestHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/FieldAnalysisRequestHandler.java	2011-07-11 21:30:24.421819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/FieldAnalysisRequestHandler.java	2011-08-05 09:11:33.322327484 -0400
@@ -118,7 +118,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/FieldAnalysisRequestHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/FieldAnalysisRequestHandler.java $";
   }
 
   // ================================================= Helper methods ================================================


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/JsonUpdateRequestHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/JsonUpdateRequestHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/JsonUpdateRequestHandler.java	2011-07-11 21:30:24.421819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/JsonUpdateRequestHandler.java	2011-08-05 09:11:33.312327484 -0400
@@ -59,7 +59,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/JsonUpdateRequestHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/JsonUpdateRequestHandler.java $";
   }
 }
 


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java	2011-08-29 12:22:45.751459551 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java	2011-08-29 19:13:20.321459517 -0400
@@ -424,7 +424,7 @@
 
   @Override
   public String getVersion() {
-    return "$Revision: 1162347 $";
+    return "$Revision: 1163047 $";
   }
 
   @Override
@@ -434,12 +434,12 @@
 
   @Override
   public String getSourceId() {
-    return "$Id: MoreLikeThisHandler.java 1162347 2011-08-27 13:27:01Z mikemccand $";
+    return "$Id: MoreLikeThisHandler.java 1163047 2011-08-29 23:13:10Z rmuir $";
   }
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java	2011-07-11 21:30:24.411819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java	2011-08-05 09:11:33.312327484 -0400
@@ -100,6 +100,6 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java $";
   }
 }


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/RealTimeGetHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/RealTimeGetHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/RealTimeGetHandler.java	2011-09-08 17:00:37.196036247 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/RealTimeGetHandler.java	2011-09-08 13:27:31.376031529 -0400
@@ -37,7 +37,7 @@
 
   @Override
   public String getVersion() {
-    return "$Revision: 1165885 $";
+    return "$Revision: 1166817 $";
   }
 
   @Override
@@ -47,12 +47,12 @@
 
   @Override
   public String getSourceId() {
-    return "$Id: RealTimeGetHandler.java 1165885 2011-09-06 21:47:05Z yonik $";
+    return "$Id: RealTimeGetHandler.java 1166817 2011-09-08 17:27:25Z rmuir $";
   }
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/RealTimeGetHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/RealTimeGetHandler.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java	2011-08-11 08:24:42.412326762 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java	2011-08-23 10:07:05.491460288 -0400
@@ -461,17 +461,17 @@
 
   @Override
   public String getSourceId() {
-    return "$Id: ReplicationHandler.java 1155194 2011-08-09 02:40:52Z markrmiller $";
+    return "$Id: ReplicationHandler.java 1160700 2011-08-23 14:06:58Z rmuir $";
   }
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java $";
   }
 
   @Override
   public String getVersion() {
-    return "$Revision: 1155194 $";
+    return "$Revision: 1160700 $";
   }
 
   private long[] getIndexVersion() {


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/StandardRequestHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/StandardRequestHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/StandardRequestHandler.java	2011-07-11 21:30:24.411819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/StandardRequestHandler.java	2011-08-05 09:11:33.312327484 -0400
@@ -62,7 +62,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/StandardRequestHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/StandardRequestHandler.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java	2011-09-08 17:00:37.196036247 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java	2011-09-08 13:27:31.376031529 -0400
@@ -89,17 +89,17 @@
 
   @Override
   public String getVersion() {
-    return "$Revision: 1165754 $";
+    return "$Revision: 1166817 $";
   }
 
   @Override
   public String getSourceId() {
-    return "$Id: XmlUpdateRequestHandler.java 1165754 2011-09-06 16:27:20Z janhoy $";
+    return "$Id: XmlUpdateRequestHandler.java 1166817 2011-09-08 17:27:25Z rmuir $";
   }
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java $";
   }
 }
 


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/XsltUpdateRequestHandler.java lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/XsltUpdateRequestHandler.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/handler/XsltUpdateRequestHandler.java	2011-07-11 21:30:24.411819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/handler/XsltUpdateRequestHandler.java	2011-08-05 09:11:33.312327484 -0400
@@ -93,7 +93,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/XsltUpdateRequestHandler.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/handler/XsltUpdateRequestHandler.java $";
   }
 
 


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/DefaultEncoder.java lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/DefaultEncoder.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/DefaultEncoder.java	2011-07-11 21:29:41.951819802 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/DefaultEncoder.java	2011-08-05 09:11:33.182327484 -0400
@@ -42,7 +42,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/highlight/DefaultEncoder.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/highlight/DefaultEncoder.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/GapFragmenter.java lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/GapFragmenter.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/GapFragmenter.java	2011-07-11 21:29:41.951819802 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/GapFragmenter.java	2011-08-05 09:11:33.182327484 -0400
@@ -61,7 +61,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/highlight/GapFragmenter.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/highlight/GapFragmenter.java $";
   }
 }
 


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/HtmlEncoder.java lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/HtmlEncoder.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/HtmlEncoder.java	2011-07-11 21:29:41.951819802 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/HtmlEncoder.java	2011-08-05 09:11:33.182327484 -0400
@@ -42,7 +42,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/highlight/HtmlEncoder.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/highlight/HtmlEncoder.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/HtmlFormatter.java lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/HtmlFormatter.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/HtmlFormatter.java	2011-07-11 21:29:41.951819802 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/HtmlFormatter.java	2011-08-05 09:11:33.182327484 -0400
@@ -60,6 +60,6 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/highlight/HtmlFormatter.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/highlight/HtmlFormatter.java $";
   }
 }


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/RegexFragmenter.java lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/RegexFragmenter.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/RegexFragmenter.java	2011-07-11 21:29:41.951819802 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/RegexFragmenter.java	2011-08-05 09:11:33.182327484 -0400
@@ -107,7 +107,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/highlight/RegexFragmenter.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/highlight/RegexFragmenter.java $";
   }
 }
 


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/ScoreOrderFragmentsBuilder.java lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/ScoreOrderFragmentsBuilder.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/ScoreOrderFragmentsBuilder.java	2011-07-11 21:29:41.951819802 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/ScoreOrderFragmentsBuilder.java	2011-08-05 09:11:33.182327484 -0400
@@ -42,7 +42,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/highlight/ScoreOrderFragmentsBuilder.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/highlight/ScoreOrderFragmentsBuilder.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/SimpleFragListBuilder.java lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/SimpleFragListBuilder.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/SimpleFragListBuilder.java	2011-07-11 21:29:41.951819802 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/SimpleFragListBuilder.java	2011-08-05 09:11:33.182327484 -0400
@@ -44,7 +44,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/highlight/SimpleFragListBuilder.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/highlight/SimpleFragListBuilder.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/SimpleFragmentsBuilder.java lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/SimpleFragmentsBuilder.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/SimpleFragmentsBuilder.java	2011-07-11 21:29:41.951819802 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/SimpleFragmentsBuilder.java	2011-08-05 09:11:33.182327484 -0400
@@ -42,7 +42,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/highlight/SimpleFragmentsBuilder.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/highlight/SimpleFragmentsBuilder.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/SingleFragListBuilder.java lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/SingleFragListBuilder.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/highlight/SingleFragListBuilder.java	2011-07-11 21:29:41.951819802 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/highlight/SingleFragListBuilder.java	2011-08-05 09:11:33.182327484 -0400
@@ -44,7 +44,7 @@
 
   @Override
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/highlight/SingleFragListBuilder.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/highlight/SingleFragListBuilder.java $";
   }
 
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/schema/FieldType.java lucene-flexscoring/solr/core/src/java/org/apache/solr/schema/FieldType.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/schema/FieldType.java	2011-08-29 12:22:45.721459551 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/schema/FieldType.java	2011-08-29 13:16:55.481459546 -0400
@@ -27,10 +27,10 @@
 import org.apache.lucene.index.Term;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.search.Query;
-import org.apache.lucene.search.Similarity;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.search.TermRangeQuery;
+import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.CharsRef;
 import org.apache.lucene.util.UnicodeUtil;


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java lucene-flexscoring/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java	2011-07-20 07:06:54.528132723 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java	2011-08-23 09:55:23.341460289 -0400
@@ -18,7 +18,7 @@
 package org.apache.solr.schema;
 
 import org.apache.lucene.analysis.Analyzer;
-import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.util.Version;
 import org.apache.solr.common.ResourceLoader;
 import org.apache.solr.common.SolrException;


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/schema/IndexSchema.java lucene-flexscoring/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/schema/IndexSchema.java	2011-08-29 12:22:45.711459551 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/schema/IndexSchema.java	2011-08-29 13:16:48.331459546 -0400
@@ -20,9 +20,9 @@
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.index.IndexableField;
-import org.apache.lucene.search.DefaultSimilarity;
-import org.apache.lucene.search.Similarity;
-import org.apache.lucene.search.SimilarityProvider;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.apache.lucene.util.Version;
 import org.apache.solr.common.ResourceLoader;
 import org.apache.solr.common.SolrException;


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/schema/SimilarityFactory.java lucene-flexscoring/solr/core/src/java/org/apache/solr/schema/SimilarityFactory.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/schema/SimilarityFactory.java	2011-07-11 21:27:59.381819805 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/schema/SimilarityFactory.java	2011-08-23 08:43:39.771460295 -0400
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.similarities.Similarity;
 import org.apache.solr.common.params.SolrParams;
 
 public abstract class SimilarityFactory {


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/search/FastLRUCache.java lucene-flexscoring/solr/core/src/java/org/apache/solr/search/FastLRUCache.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/search/FastLRUCache.java	2011-07-11 21:29:32.191819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/search/FastLRUCache.java	2011-08-05 09:11:33.152327484 -0400
@@ -205,7 +205,7 @@
   }
 
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/FastLRUCache.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/search/FastLRUCache.java $";
   }
 
   public URL[] getDocs() {


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/search/function/FileFloatSource.java lucene-flexscoring/solr/core/src/java/org/apache/solr/search/function/FileFloatSource.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/search/function/FileFloatSource.java	2011-07-17 06:27:34.438948135 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/search/function/FileFloatSource.java	2011-08-23 10:07:05.381460288 -0400
@@ -327,17 +327,17 @@
 
     @Override
     public String getSource() {
-      return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/function/FileFloatSource.java $";
+      return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/search/function/FileFloatSource.java $";
     }
 
     @Override
     public String getSourceId() {
-      return "$Id: FileFloatSource.java 1147284 2011-07-15 19:14:01Z hossman $";
+      return "$Id: FileFloatSource.java 1160700 2011-08-23 14:06:58Z rmuir $";
     }
 
     @Override
     public String getVersion() {
-      return "$Revision: 1147284 $";
+      return "$Revision: 1160700 $";
     }    
   }
 }


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/search/JoinQParserPlugin.java lucene-flexscoring/solr/core/src/java/org/apache/solr/search/JoinQParserPlugin.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/search/JoinQParserPlugin.java	2011-07-11 21:29:32.191819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/search/JoinQParserPlugin.java	2011-08-23 08:43:39.771460295 -0400
@@ -19,6 +19,7 @@
 import org.apache.lucene.index.*;
 import org.apache.lucene.queryparser.classic.ParseException;
 import org.apache.lucene.search.*;
+import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.OpenBitSet;


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/search/LRUCache.java lucene-flexscoring/solr/core/src/java/org/apache/solr/search/LRUCache.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/search/LRUCache.java	2011-07-11 21:29:32.201819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/search/LRUCache.java	2011-08-05 09:11:33.152327484 -0400
@@ -231,7 +231,7 @@
   }
 
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/LRUCache.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/search/LRUCache.java $";
   }
 
   public URL[] getDocs() {


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/search/SolrFieldCacheMBean.java lucene-flexscoring/solr/core/src/java/org/apache/solr/search/SolrFieldCacheMBean.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/search/SolrFieldCacheMBean.java	2011-07-11 21:29:32.181819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/search/SolrFieldCacheMBean.java	2011-08-05 09:11:33.142327484 -0400
@@ -50,7 +50,7 @@
     return "$Id: SolrFieldCacheMBean.java 1144761 2011-07-09 23:01:53Z sarowe $"; 
   }
   public String getSource() { 
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/SolrFieldCacheMBean.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/search/SolrFieldCacheMBean.java $";
   }
   public URL[] getDocs() {
     return null;


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java lucene-flexscoring/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java	2011-08-29 12:22:45.731459551 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java	2011-08-29 19:13:20.061459517 -0400
@@ -1900,11 +1900,11 @@
   }
 
   public String getSourceId() {
-    return "$Id: SolrIndexSearcher.java 1162347 2011-08-27 13:27:01Z mikemccand $";
+    return "$Id: SolrIndexSearcher.java 1163047 2011-08-29 23:13:10Z rmuir $";
   }
 
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java $";
   }
 
   public URL[] getDocs() {


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/search/SolrSimilarityProvider.java lucene-flexscoring/solr/core/src/java/org/apache/solr/search/SolrSimilarityProvider.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/search/SolrSimilarityProvider.java	2011-07-11 21:29:32.191819804 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/search/SolrSimilarityProvider.java	2011-08-23 08:43:39.781460295 -0400
@@ -17,8 +17,8 @@
  * limitations under the License.
  */
 
-import org.apache.lucene.search.DefaultSimilarityProvider;
-import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.similarities.DefaultSimilarityProvider;
+import org.apache.lucene.search.similarities.Similarity;
 import org.apache.solr.schema.FieldType;
 import org.apache.solr.schema.IndexSchema;
 


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java lucene-flexscoring/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java
--- lucene-clean-trunk/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java	2011-09-09 12:05:14.136061592 -0400
+++ lucene-flexscoring/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java	2011-09-09 12:08:04.256061654 -0400
@@ -476,11 +476,11 @@
   }
 
   public String getSourceId() {
-    return "$Id: DirectUpdateHandler2.java 1167199 2011-09-09 14:20:24Z yonik $";
+    return "$Id: DirectUpdateHandler2.java 1167270 2011-09-09 16:07:58Z rmuir $";
   }
 
   public String getSource() {
-    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java $";
+    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/flexscoring/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler2.java $";
   }
 
   public URL[] getDocs() {


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/test/org/apache/solr/schema/CustomSimilarityFactory.java lucene-flexscoring/solr/core/src/test/org/apache/solr/schema/CustomSimilarityFactory.java
--- lucene-clean-trunk/solr/core/src/test/org/apache/solr/schema/CustomSimilarityFactory.java	2011-07-11 21:26:18.091819805 -0400
+++ lucene-flexscoring/solr/core/src/test/org/apache/solr/schema/CustomSimilarityFactory.java	2011-08-23 08:43:39.781460295 -0400
@@ -16,7 +16,7 @@
  */
 package org.apache.solr.schema;
 
-import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.similarities.Similarity;
 
 public class CustomSimilarityFactory extends SimilarityFactory {
   @Override


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/test/org/apache/solr/schema/IndexSchemaTest.java lucene-flexscoring/solr/core/src/test/org/apache/solr/schema/IndexSchemaTest.java
--- lucene-clean-trunk/solr/core/src/test/org/apache/solr/schema/IndexSchemaTest.java	2011-07-11 21:26:18.091819805 -0400
+++ lucene-flexscoring/solr/core/src/test/org/apache/solr/schema/IndexSchemaTest.java	2011-08-23 08:43:39.781460295 -0400
@@ -27,7 +27,7 @@
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.request.LocalSolrQueryRequest;
 import org.apache.solr.request.SolrQueryRequest;
-import org.apache.lucene.search.SimilarityProvider;
+import org.apache.lucene.search.similarities.SimilarityProvider;
 import org.junit.BeforeClass;
 import org.junit.Test;
 


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/test/org/apache/solr/schema/MockConfigurableSimilarity.java lucene-flexscoring/solr/core/src/test/org/apache/solr/schema/MockConfigurableSimilarity.java
--- lucene-clean-trunk/solr/core/src/test/org/apache/solr/schema/MockConfigurableSimilarity.java	2011-07-11 21:26:18.091819805 -0400
+++ lucene-flexscoring/solr/core/src/test/org/apache/solr/schema/MockConfigurableSimilarity.java	2011-08-23 08:43:39.781460295 -0400
@@ -16,7 +16,7 @@
  */
 package org.apache.solr.schema;
 
-import org.apache.lucene.search.DefaultSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
 
 public class MockConfigurableSimilarity extends DefaultSimilarity {
   private String passthrough;


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/test/org/apache/solr/schema/TestPerFieldSimilarity.java lucene-flexscoring/solr/core/src/test/org/apache/solr/schema/TestPerFieldSimilarity.java
--- lucene-clean-trunk/solr/core/src/test/org/apache/solr/schema/TestPerFieldSimilarity.java	2011-07-11 21:26:18.091819805 -0400
+++ lucene-flexscoring/solr/core/src/test/org/apache/solr/schema/TestPerFieldSimilarity.java	2011-08-23 08:43:39.781460295 -0400
@@ -18,8 +18,8 @@
  */
 
 import org.apache.lucene.misc.SweetSpotSimilarity;
-import org.apache.lucene.search.DefaultSimilarity;
-import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.Similarity;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.search.SolrIndexSearcher;


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/test/org/apache/solr/search/function/TestFunctionQuery.java lucene-flexscoring/solr/core/src/test/org/apache/solr/search/function/TestFunctionQuery.java
--- lucene-clean-trunk/solr/core/src/test/org/apache/solr/search/function/TestFunctionQuery.java	2011-07-31 23:12:09.562328018 -0400
+++ lucene-flexscoring/solr/core/src/test/org/apache/solr/search/function/TestFunctionQuery.java	2011-08-23 09:37:04.811460290 -0400
@@ -19,9 +19,9 @@
 
 import org.apache.lucene.index.FieldInvertState;
 import org.apache.lucene.index.codecs.CodecProvider;
-import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.FieldCache;
-import org.apache.lucene.search.TFIDFSimilarity;
+import org.apache.lucene.search.similarities.DefaultSimilarity;
+import org.apache.lucene.search.similarities.TFIDFSimilarity;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.NamedList;


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/test-files/solr/conf/schema12.xml lucene-flexscoring/solr/core/src/test-files/solr/conf/schema12.xml
--- lucene-clean-trunk/solr/core/src/test-files/solr/conf/schema12.xml	2011-07-24 19:00:08.612328885 -0400
+++ lucene-flexscoring/solr/core/src/test-files/solr/conf/schema12.xml	2011-08-23 10:07:05.671460288 -0400
@@ -23,7 +23,7 @@
      kitchen sink thrown in. See example/solr/conf/schema.xml for a 
      more concise example.
 
-     $Id: schema12.xml 1149050 2011-07-21 07:09:27Z koji $
+     $Id: schema12.xml 1160700 2011-08-23 14:06:58Z rmuir $
      $Source: /cvs/main/searching/solr-configs/test/WEB-INF/classes/schema.xml,v $
      $Name:  $
   -->


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/test-files/solr/conf/schema-copyfield-test.xml lucene-flexscoring/solr/core/src/test-files/solr/conf/schema-copyfield-test.xml
--- lucene-clean-trunk/solr/core/src/test-files/solr/conf/schema-copyfield-test.xml	2011-07-11 21:27:32.411819805 -0400
+++ lucene-flexscoring/solr/core/src/test-files/solr/conf/schema-copyfield-test.xml	2011-08-23 08:51:48.671460294 -0400
@@ -23,7 +23,7 @@
      kitchen sink thrown in. See example/solr/conf/schema.xml for a 
      more concise example.
 
-     $Id: schema-copyfield-test.xml 1144761 2011-07-09 23:01:53Z sarowe $
+     $Id: schema-copyfield-test.xml 1160668 2011-08-23 12:51:44Z rmuir $
      $Source: /cvs/main/searching/solr-configs/test/WEB-INF/classes/schema.xml,v $
      $Name:  $
   -->
@@ -468,6 +468,6 @@
       A custom similarity may be specified here, but the default is fine
       for most applications.
  -->
- <!-- <similarity class="org.apache.lucene.search.DefaultSimilarity"/> -->
+ <!-- <similarity class="org.apache.lucene.search.similarities.DefaultSimilarity"/> -->
 
 </schema>


diff -ruN -x .svn -x build lucene-clean-trunk/solr/core/src/test-files/solr/conf/schema-required-fields.xml lucene-flexscoring/solr/core/src/test-files/solr/conf/schema-required-fields.xml
--- lucene-clean-trunk/solr/core/src/test-files/solr/conf/schema-required-fields.xml	2011-07-11 21:27:32.391819805 -0400
+++ lucene-flexscoring/solr/core/src/test-files/solr/conf/schema-required-fields.xml	2011-08-23 08:51:48.671460294 -0400
@@ -23,7 +23,7 @@
      kitchen sink thrown in. See example/solr/conf/schema.xml for a 
      more concise example.
 
-     $Id: schema-required-fields.xml 1144761 2011-07-09 23:01:53Z sarowe $
+     $Id: schema-required-fields.xml 1160668 2011-08-23 12:51:44Z rmuir $
      $Source: /cvs/main/searching/solr-configs/test/WEB-INF/classes/schema.xml,v $
      $Name:  $
   -->
@@ -434,6 +434,6 @@
       A custom similarity may be specified here, but the default is fine
       for most applications.
  -->
- <!-- <similarity class="org.apache.lucene.search.DefaultSimilarity"/> -->
+ <!-- <similarity class="org.apache.lucene.search.similarities.DefaultSimilarity"/> -->
 
 </schema>


diff -ruN -x .svn -x build lucene-clean-trunk/solr/example/example-DIH/solr/db/conf/schema.xml lucene-flexscoring/solr/example/example-DIH/solr/db/conf/schema.xml
--- lucene-clean-trunk/solr/example/example-DIH/solr/db/conf/schema.xml	2011-07-05 19:28:11.691820540 -0400
+++ lucene-flexscoring/solr/example/example-DIH/solr/db/conf/schema.xml	2011-08-23 08:43:39.781460295 -0400
@@ -354,6 +354,6 @@
  <!-- Similarity is the scoring routine for each document vs. a query.
       A custom similarity may be specified here, but the default is fine
       for most applications.  -->
- <!-- <similarity class="org.apache.lucene.search.DefaultSimilarity"/> -->
+ <!-- <similarity class="org.apache.lucene.search.similarities.DefaultSimilarity"/> -->
 
 </schema>


diff -ruN -x .svn -x build lucene-clean-trunk/solr/example/solr/conf/schema.xml lucene-flexscoring/solr/example/solr/conf/schema.xml
--- lucene-clean-trunk/solr/example/solr/conf/schema.xml	2011-07-05 19:28:11.681820540 -0400
+++ lucene-flexscoring/solr/example/solr/conf/schema.xml	2011-08-23 08:43:39.781460295 -0400
@@ -615,7 +615,7 @@
  <!-- Similarity is the scoring routine for each document vs. a query.
       A custom similarity may be specified here, but the default is fine
       for most applications.  -->
- <!-- <similarity class="org.apache.lucene.search.DefaultSimilarity"/> -->
+ <!-- <similarity class="org.apache.lucene.search.similarities.DefaultSimilarity"/> -->
  <!-- ... OR ...
       Specify a SimilarityFactory class name implementation
       allowing parameters to be used.


diff -ruN -x .svn -x build lucene-clean-trunk/solr/solrj/src/test-files/solrj/solr/conf/schema-replication1.xml lucene-flexscoring/solr/solrj/src/test-files/solrj/solr/conf/schema-replication1.xml
--- lucene-clean-trunk/solr/solrj/src/test-files/solrj/solr/conf/schema-replication1.xml	2011-07-24 19:00:11.232328885 -0400
+++ lucene-flexscoring/solr/solrj/src/test-files/solrj/solr/conf/schema-replication1.xml	2011-08-23 10:07:05.361460288 -0400
@@ -23,7 +23,7 @@
      kitchen sink thrown in. See example/solr/conf/schema.xml for a 
      more concise example.
 
-     $Id: schema-replication1.xml 1144761 2011-07-09 23:01:53Z sarowe $
+     $Id: schema-replication1.xml 1160700 2011-08-23 14:06:58Z rmuir $
      $Source$
      $Name$
   -->


diff -ruN -x .svn -x build lucene-clean-trunk/solr/solrj/src/test-files/solrj/solr/conf/solrconfig-slave1.xml lucene-flexscoring/solr/solrj/src/test-files/solrj/solr/conf/solrconfig-slave1.xml
--- lucene-clean-trunk/solr/solrj/src/test-files/solrj/solr/conf/solrconfig-slave1.xml	2011-08-17 09:20:42.110062764 -0400
+++ lucene-flexscoring/solr/solrj/src/test-files/solrj/solr/conf/solrconfig-slave1.xml	2011-08-23 10:07:05.361460288 -0400
@@ -17,7 +17,7 @@
  limitations under the License.
 -->
 
-<!-- $Id: solrconfig-slave1.xml 1144761 2011-07-09 23:01:53Z sarowe $
+<!-- $Id: solrconfig-slave1.xml 1160700 2011-08-23 14:06:58Z rmuir $
      $Source$
      $Name$
   -->
