2 * Copyright 2005 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.
19 namespace Lucene
.Net
.Search
22 sealed class BooleanScorer
: Scorer
24 private void InitBlock()
26 bucketTable
= new BucketTable(this);
28 private SubScorer scorers
= null;
29 private BucketTable bucketTable
;
31 private int maxCoord
= 1;
32 private float[] coordFactors
= null;
34 private int requiredMask
= 0;
35 private int prohibitedMask
= 0;
36 private int nextMask
= 1;
38 internal BooleanScorer(Similarity similarity
) : base(similarity
)
43 internal sealed class SubScorer
47 public bool required
= false;
48 public bool prohibited
= false;
49 public HitCollector collector
;
50 public SubScorer next
;
52 public SubScorer(Scorer scorer
, bool required
, bool prohibited
, HitCollector collector
, SubScorer next
)
55 this.done
= !scorer
.Next();
56 this.required
= required
;
57 this.prohibited
= prohibited
;
58 this.collector
= collector
;
63 internal void Add(Scorer scorer
, bool required
, bool prohibited
)
66 if (required
|| prohibited
)
69 throw new System
.IndexOutOfRangeException("More than 32 required/prohibited clauses in query.");
71 nextMask
= nextMask
<< 1;
80 prohibitedMask
|= mask
;
81 // update prohibited mask
83 requiredMask
|= mask
; // update required mask
85 scorers
= new SubScorer(scorer
, required
, prohibited
, bucketTable
.NewCollector(mask
), scorers
);
88 private void ComputeCoordFactors()
90 coordFactors
= new float[maxCoord
];
91 for (int i
= 0; i
< maxCoord
; i
++)
92 coordFactors
[i
] = GetSimilarity().Coord(i
, maxCoord
- 1);
96 private Bucket current
;
98 public override void Score(HitCollector hc
)
101 Score(hc
, System
.Int32
.MaxValue
);
104 protected internal override bool Score(HitCollector hc
, int max
)
106 if (coordFactors
== null)
107 ComputeCoordFactors();
114 bucketTable
.first
= null;
116 while (current
!= null)
120 // check prohibited & required
121 if ((current
.bits
& prohibitedMask
) == 0 && (current
.bits
& requiredMask
) == requiredMask
)
124 if (current
.doc
>= max
)
127 current
= current
.next
;
128 tmp
.next
= bucketTable
.first
;
129 bucketTable
.first
= tmp
;
133 hc
.Collect(current
.doc
, current
.score
* coordFactors
[current
.coord
]);
136 current
= current
.next
; // pop the queue
139 if (bucketTable
.first
!= null)
141 current
= bucketTable
.first
;
142 bucketTable
.first
= current
.next
;
148 end
+= BucketTable
.SIZE
;
149 for (SubScorer sub
= scorers
; sub
!= null; sub
= sub
.next
)
153 sub
.done
= !sub
.scorer
.Score(sub
.collector
, end
);
158 current
= bucketTable
.first
;
160 while (current
!= null || more
);
165 public override int Doc()
170 public override bool Next()
175 while (bucketTable
.first
!= null)
178 current
= bucketTable
.first
;
179 bucketTable
.first
= current
.next
; // pop the queue
181 // check prohibited & required
182 if ((current
.bits
& prohibitedMask
) == 0 && (current
.bits
& requiredMask
) == requiredMask
)
190 end
+= BucketTable
.SIZE
;
191 for (SubScorer sub
= scorers
; sub
!= null; sub
= sub
.next
)
193 Scorer scorer
= sub
.scorer
;
194 while (!sub
.done
&& scorer
.Doc() < end
)
196 sub
.collector
.Collect(scorer
.Doc(), scorer
.Score());
197 sub
.done
= !scorer
.Next();
205 while (bucketTable
.first
!= null || more
);
210 public override float Score()
212 if (coordFactors
== null)
213 ComputeCoordFactors();
214 return current
.score
* coordFactors
[current
.coord
];
217 internal sealed class Bucket
219 internal int doc
= - 1; // tells if bucket is valid
220 internal float score
; // incremental score
221 internal int bits
; // used for bool constraints
222 internal int coord
; // count of terms in score
223 internal Bucket next
; // next valid bucket
226 /// <summary>A simple hash table of document scores within a range. </summary>
227 internal sealed class BucketTable
229 private void InitBlock()
231 buckets
= new Bucket
[SIZE
];
233 public const int SIZE
= 1 << 11;
234 public static readonly int MASK
;
236 internal Bucket
[] buckets
;
237 internal Bucket first
= null; // head of valid list
239 private BooleanScorer scorer
;
241 public BucketTable(BooleanScorer scorer
)
244 this.scorer
= scorer
;
252 public HitCollector
NewCollector(int mask
)
254 return new Collector(mask
, this);
262 internal sealed class Collector
: HitCollector
264 private BucketTable bucketTable
;
266 public Collector(int mask
, BucketTable bucketTable
)
269 this.bucketTable
= bucketTable
;
271 public override void Collect(int doc
, float score
)
273 BucketTable table
= bucketTable
;
274 int i
= doc
& Lucene
.Net
.Search
.BooleanScorer
.BucketTable
.MASK
;
275 Bucket bucket
= table
.buckets
[i
];
277 table
.buckets
[i
] = bucket
= new Bucket();
279 if (bucket
.doc
!= doc
)
282 bucket
.doc
= doc
; // set doc
283 bucket
.score
= score
; // initialize score
284 bucket
.bits
= mask
; // initialize mask
285 bucket
.coord
= 1; // initialize coord
287 bucket
.next
= table
.first
; // push onto valid list
288 table
.first
= bucket
;
293 bucket
.score
+= score
; // increment score
294 bucket
.bits
|= mask
; // add bits in mask
295 bucket
.coord
++; // increment coord
300 public override bool SkipTo(int target
)
302 throw new System
.NotSupportedException();
305 public override Explanation
Explain(int doc
)
307 throw new System
.NotSupportedException();
310 public override System
.String
ToString()
312 System
.Text
.StringBuilder buffer
= new System
.Text
.StringBuilder();
313 buffer
.Append("boolean(");
314 for (SubScorer sub
= scorers
; sub
!= null; sub
= sub
.next
)
316 buffer
.Append(sub
.scorer
.ToString());
320 return buffer
.ToString();