/*
* 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.
*/
using System;
using TermDocs = Lucene.Net.Index.TermDocs;
namespace Lucene.Net.Search
{
/// Expert: A Scorer for documents matching a Term.
public sealed class TermScorer:Scorer
{
private static readonly float[] SIM_NORM_DECODER;
private Weight weight;
private TermDocs termDocs;
private byte[] norms;
private float weightValue;
private int doc = - 1;
private int[] docs = new int[32]; // buffered doc numbers
private int[] freqs = new int[32]; // buffered term freqs
private int pointer;
private int pointerMax;
private const int SCORE_CACHE_SIZE = 32;
private float[] scoreCache = new float[SCORE_CACHE_SIZE];
/// Construct a TermScorer.
///
///
/// The weight of the Term in the query.
///
/// An iterator over the documents matching the Term.
///
/// The Similarity implementation to be used for score
/// computations.
///
/// The field norms of the document fields for the Term.
///
public /*internal*/ TermScorer(Weight weight, TermDocs td, Similarity similarity, byte[] norms):base(similarity)
{
this.weight = weight;
this.termDocs = td;
this.norms = norms;
this.weightValue = weight.Value;
for (int i = 0; i < SCORE_CACHE_SIZE; i++)
scoreCache[i] = Similarity.Tf(i) * weightValue;
}
public override void Score(Collector c)
{
Score(c, System.Int32.MaxValue, NextDoc());
}
// firstDocID is ignored since nextDoc() sets 'doc'
public /*protected internal*/ override bool Score(Collector c, int end, int firstDocID)
{
c.SetScorer(this);
while (doc < end)
{
// for docs in window
c.Collect(doc); // collect score
if (++pointer >= pointerMax)
{
pointerMax = termDocs.Read(docs, freqs); // refill buffers
if (pointerMax != 0)
{
pointer = 0;
}
else
{
termDocs.Close(); // close stream
doc = System.Int32.MaxValue; // set to sentinel value
return false;
}
}
doc = docs[pointer];
}
return true;
}
public override int DocID()
{
return doc;
}
/// Advances to the next document matching the query.
/// The iterator over the matching documents is buffered using
/// .
///
///
/// the document matching the query or -1 if there are no more documents.
///
public override int NextDoc()
{
pointer++;
if (pointer >= pointerMax)
{
pointerMax = termDocs.Read(docs, freqs); // refill buffer
if (pointerMax != 0)
{
pointer = 0;
}
else
{
termDocs.Close(); // close stream
return doc = NO_MORE_DOCS;
}
}
doc = docs[pointer];
return doc;
}
public override float Score()
{
System.Diagnostics.Debug.Assert(doc != - 1);
int f = freqs[pointer];
float raw = f < SCORE_CACHE_SIZE?scoreCache[f]:Similarity.Tf(f) * weightValue; // cache miss
return norms == null?raw:raw * SIM_NORM_DECODER[norms[doc] & 0xFF]; // normalize for field
}
/// Advances to the first match beyond the current whose document number is
/// greater than or equal to a given target.
/// The implementation uses .
///
///
/// The target document number.
///
/// the matching document or -1 if none exist.
///
public override int Advance(int target)
{
// first scan in cache
for (pointer++; pointer < pointerMax; pointer++)
{
if (docs[pointer] >= target)
{
return doc = docs[pointer];
}
}
// not found in cache, seek underlying stream
bool result = termDocs.SkipTo(target);
if (result)
{
pointerMax = 1;
pointer = 0;
docs[pointer] = doc = termDocs.Doc;
freqs[pointer] = termDocs.Freq;
}
else
{
doc = NO_MORE_DOCS;
}
return doc;
}
/// Returns a string representation of this TermScorer.
public override System.String ToString()
{
return "scorer(" + weight + ")";
}
static TermScorer()
{
SIM_NORM_DECODER = Search.Similarity.GetNormDecoder();
}
}
}