2 * Copyright 2004 The Apache Software Foundation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 namespace Lucene
.Net
.Search
20 sealed class BooleanScorer
: Scorer
22 private void InitBlock()
24 bucketTable
= new BucketTable(this);
26 private SubScorer scorers
= null;
27 private BucketTable bucketTable
;
29 private int maxCoord
= 1;
30 private float[] coordFactors
= null;
32 private int requiredMask
= 0;
33 private int prohibitedMask
= 0;
34 private int nextMask
= 1;
36 internal BooleanScorer(Similarity similarity
) : base(similarity
)
41 internal sealed class SubScorer
45 public bool required
= false;
46 public bool prohibited
= false;
47 public HitCollector collector
;
48 public SubScorer next
;
50 public SubScorer(Scorer scorer
, bool required
, bool prohibited
, HitCollector collector
, SubScorer next
)
53 this.done
= !scorer
.Next();
54 this.required
= required
;
55 this.prohibited
= prohibited
;
56 this.collector
= collector
;
61 internal void Add(Scorer scorer
, bool required
, bool prohibited
)
64 if (required
|| prohibited
)
67 throw new System
.IndexOutOfRangeException("More than 32 required/prohibited clauses in query.");
69 nextMask
= nextMask
<< 1;
78 prohibitedMask
|= mask
;
79 // update prohibited mask
81 requiredMask
|= mask
; // update required mask
83 scorers
= new SubScorer(scorer
, required
, prohibited
, bucketTable
.NewCollector(mask
), scorers
);
86 private void ComputeCoordFactors()
88 coordFactors
= new float[maxCoord
];
89 for (int i
= 0; i
< maxCoord
; i
++)
90 coordFactors
[i
] = GetSimilarity().Coord(i
, maxCoord
- 1);
94 private Bucket current
;
96 public override void Score(HitCollector hc
)
99 Score(hc
, System
.Int32
.MaxValue
);
102 protected internal override bool Score(HitCollector hc
, int max
)
104 if (coordFactors
== null)
105 ComputeCoordFactors();
112 bucketTable
.first
= null;
114 while (current
!= null)
118 // check prohibited & required
119 if ((current
.bits
& prohibitedMask
) == 0 && (current
.bits
& requiredMask
) == requiredMask
)
122 if (current
.doc
>= max
)
125 current
= current
.next
;
126 tmp
.next
= bucketTable
.first
;
127 bucketTable
.first
= tmp
;
131 hc
.Collect(current
.doc
, current
.score
* coordFactors
[current
.coord
]);
134 current
= current
.next
; // pop the queue
137 if (bucketTable
.first
!= null)
139 current
= bucketTable
.first
;
140 bucketTable
.first
= current
.next
;
146 end
+= BucketTable
.SIZE
;
147 for (SubScorer sub
= scorers
; sub
!= null; sub
= sub
.next
)
151 sub
.done
= !sub
.scorer
.Score(sub
.collector
, end
);
156 current
= bucketTable
.first
;
158 while (current
!= null || more
);
163 public override int Doc()
168 public override bool Next()
173 while (bucketTable
.first
!= null)
176 current
= bucketTable
.first
;
177 bucketTable
.first
= current
.next
; // pop the queue
179 // check prohibited & required
180 if ((current
.bits
& prohibitedMask
) == 0 && (current
.bits
& requiredMask
) == requiredMask
)
188 end
+= BucketTable
.SIZE
;
189 for (SubScorer sub
= scorers
; sub
!= null; sub
= sub
.next
)
191 Scorer scorer
= sub
.scorer
;
192 while (!sub
.done
&& scorer
.Doc() < end
)
194 sub
.collector
.Collect(scorer
.Doc(), scorer
.Score());
195 sub
.done
= !scorer
.Next();
203 while (bucketTable
.first
!= null || more
);
208 public override float Score()
210 if (coordFactors
== null)
211 ComputeCoordFactors();
212 return current
.score
* coordFactors
[current
.coord
];
215 internal sealed class Bucket
217 internal int doc
= - 1; // tells if bucket is valid
218 internal float score
; // incremental score
219 internal int bits
; // used for bool constraints
220 internal int coord
; // count of terms in score
221 internal Bucket next
; // next valid bucket
224 /// <summary>A simple hash table of document scores within a range. </summary>
225 internal sealed class BucketTable
227 private void InitBlock()
229 buckets
= new Bucket
[SIZE
];
231 public const int SIZE
= 1 << 11;
232 public static readonly int MASK
;
234 internal Bucket
[] buckets
;
235 internal Bucket first
= null; // head of valid list
237 private BooleanScorer scorer
;
239 public BucketTable(BooleanScorer scorer
)
241 this.scorer
= scorer
;
249 public HitCollector
NewCollector(int mask
)
251 return new Collector(mask
, this);
259 internal sealed class Collector
: HitCollector
261 private BucketTable bucketTable
;
263 public Collector(int mask
, BucketTable bucketTable
)
266 this.bucketTable
= bucketTable
;
268 public override void Collect(int doc
, float score
)
270 BucketTable table
= bucketTable
;
271 int i
= doc
& Lucene
.Net
.Search
.BooleanScorer
.BucketTable
.MASK
;
272 Bucket bucket
= table
.buckets
[i
];
274 table
.buckets
[i
] = bucket
= new Bucket();
276 if (bucket
.doc
!= doc
)
279 bucket
.doc
= doc
; // set doc
280 bucket
.score
= score
; // initialize score
281 bucket
.bits
= mask
; // initialize mask
282 bucket
.coord
= 1; // initialize coord
284 bucket
.next
= table
.first
; // push onto valid list
285 table
.first
= bucket
;
290 bucket
.score
+= score
; // increment score
291 bucket
.bits
|= mask
; // add bits in mask
292 bucket
.coord
++; // increment coord
297 public override bool SkipTo(int target
)
299 throw new System
.NotSupportedException();
302 public override Explanation
Explain(int doc
)
304 throw new System
.NotSupportedException();
307 public override System
.String
ToString()
309 System
.Text
.StringBuilder buffer
= new System
.Text
.StringBuilder();
310 buffer
.Append("boolean(");
311 for (SubScorer sub
= scorers
; sub
!= null; sub
= sub
.next
)
313 buffer
.Append(sub
.scorer
.ToString());
317 return buffer
.ToString();