Index: src/java/org/apache/lucene/search/Similarity.java =================================================================== --- src/java/org/apache/lucene/search/Similarity.java (revision 645637) +++ src/java/org/apache/lucene/search/Similarity.java (working copy) @@ -22,8 +22,11 @@ import java.io.IOException; import java.io.Serializable; +import java.io.Writer; import java.util.Collection; import java.util.Iterator; +import java.util.Arrays; +import java.text.DecimalFormat; /** Expert: Scoring API. *

Subclasses implement search scoring. @@ -311,26 +314,30 @@ return Similarity.defaultImpl; } - /** Cache of decoded bytes. */ - private static final float[] NORM_TABLE = new float[256]; + private static NormCodec normCodec = new DefaultNormCodec(); - static { - for (int i = 0; i < 256; i++) - NORM_TABLE[i] = SmallFloat.byte315ToFloat((byte)i); + + public static NormCodec getNormCodec() { + return normCodec; } + public static void setNormCodec(NormCodec normCodec) { + Similarity.normCodec = normCodec; + } + /** Decodes a normalization factor stored in an index. * @see #encodeNorm(float) */ public static float decodeNorm(byte b) { - return NORM_TABLE[b & 0xFF]; // & 0xFF maps negative bytes to positive above 127 + return normCodec.decodeNorm(b); } /** Returns a table for decoding normalization bytes. + * @deprecated access norm decoder using {@link Similarity#getNormCodec()} * @see #encodeNorm(float) */ public static float[] getNormDecoder() { - return NORM_TABLE; + return normCodec.getNormsTable(); } /** Computes the normalization value for a field given the total number of @@ -385,7 +392,7 @@ * @see org.apache.lucene.util.SmallFloat */ public static byte encodeNorm(float f) { - return SmallFloat.floatToByte315(f); + return normCodec.encodeNorm(f); } @@ -523,4 +530,80 @@ //Do nothing return 1; } + + + public static interface NormCodec { + + /** Encodes a normalization factor for storage in an index. + * @see org.apache.lucene.document.Field#setBoost(float) + */ + public abstract byte encodeNorm(float f); + + /** Decodes a normalization factor stored in an index. + * @see #encodeNorm(float) + */ + public abstract float decodeNorm(byte b); + + /** + * @deprecated 2.3.1 backwards compatibility + * @throws RuntimeException if no backwards compatibile norms table + * @see org.apache.lucene.search.Similarity#getNormDecoder() + */ + public abstract float[] getNormsTable(); + + } + + public static class DefaultNormCodec implements NormCodec { + + /** Cache of decoded bytes. */ + private float[] normsTable = new float[256]; + + public DefaultNormCodec() { + for (int i = 0; i < 256; i++) { + normsTable[i] = SmallFloat.byte315ToFloat((byte)i); + } + } + + public byte encodeNorm(float f) { + return SmallFloat.floatToByte315(f); + } + + public float decodeNorm(byte b) { + return normsTable[b & 0xFF]; // & 0xFF maps negative bytes to positive above 127 + } + + + public float[] getNormsTable() { + return normsTable; + } + } + + public static class SimpleNormCode implements NormCodec { + + private float[] normsTable; + + public SimpleNormCode(float[] NORM_TABLE) { + this.normsTable = NORM_TABLE; + } + + public float decodeNorm(byte b) { + return normsTable[b]; + } + + public byte encodeNorm(float f) { + int pos = Arrays.binarySearch(normsTable, f); + if (pos < 0) { + pos *= -1; + pos--; + } + return (byte) pos; + } + + + public float[] getNormsTable() { + throw new RuntimeException("Not supported"); + } + } + + } Index: src/java/org/apache/lucene/search/TermScorer.java =================================================================== --- src/java/org/apache/lucene/search/TermScorer.java (revision 645637) +++ src/java/org/apache/lucene/search/TermScorer.java (working copy) @@ -63,7 +63,6 @@ protected boolean score(HitCollector c, int end) throws IOException { Similarity similarity = getSimilarity(); // cache sim in local - float[] normDecoder = Similarity.getNormDecoder(); while (doc < end) { // for docs in window int f = freqs[pointer]; float score = // compute tf(f)*weight @@ -71,7 +70,7 @@ ? scoreCache[f] // cache hit : similarity.tf(f)*weightValue; // cache miss - score *= normDecoder[norms[doc] & 0xFF]; // normalize for field + score *= Similarity.decodeNorm(norms[doc]); // normalize for field c.collect(doc, score); // collect score