You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by mi...@apache.org on 2010/10/14 10:48:40 UTC
[lucy-commits] svn commit: r1022422 [20/43] - in /incubator/lucy/trunk/import: ./
charmonizer/ charmonizer/src/ charmonizer/src/Charmonizer/
charmonizer/src/Charmonizer/Core/ charmonizer/src/Charmonizer/Probe/
charmonizer/src/Charmonizer/Test/ clownfish/ clownfish/li...
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/NOTQuery.cfh
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/NOTQuery.cfh?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/NOTQuery.cfh (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/NOTQuery.cfh Thu Oct 14 08:48:04 2010
@@ -0,0 +1,71 @@
+parcel KinoSearch cnick Kino;
+
+/** Invert the result set of another Query.
+ *
+ * A NOTQuery wraps another Query and matches against its inverse document
+ * set. All matching docs recieve a score of 0.0.
+ *
+ * NOTQuery is often used in conjunction with ANDQuery to provide
+ * "a AND NOT b" semantics.
+ */
+
+class KinoSearch::Search::NOTQuery inherits KinoSearch::Search::PolyQuery
+ : dumpable {
+
+ /**
+ * @param negated_query The Query to be inverted.
+ */
+ inert incremented NOTQuery*
+ new(Query *negated_query);
+
+ /**
+ * @param negated_query The Query whose result set should be inverted.
+ */
+ public inert NOTQuery*
+ init(NOTQuery *self, Query *negated_query);
+
+ /** Accessor for the object's negated query. */
+ public Query*
+ Get_Negated_Query(NOTQuery *self);
+
+ /** Setter for the object's negated query. */
+ public void
+ Set_Negated_Query(NOTQuery *self, Query *negated_query);
+
+ public incremented Compiler*
+ Make_Compiler(NOTQuery *self, Searcher *searcher, float boost);
+
+ public incremented CharBuf*
+ To_String(NOTQuery *self);
+
+ public bool_t
+ Equals(NOTQuery *self, Obj *other);
+}
+
+class KinoSearch::Search::NOTCompiler
+ inherits KinoSearch::Search::PolyCompiler {
+
+ inert incremented NOTCompiler*
+ new(NOTQuery *parent, Searcher *searcher, float boost);
+
+ inert NOTCompiler*
+ init(NOTCompiler *self, NOTQuery *parent, Searcher *searcher,
+ float boost);
+
+ public incremented nullable Matcher*
+ Make_Matcher(NOTCompiler *self, SegReader *reader, bool_t need_score);
+
+ public float
+ Sum_Of_Squared_Weights(NOTCompiler *self);
+
+ public incremented VArray*
+ Highlight_Spans(NOTCompiler *self, Searcher *searcher,
+ DocVector *doc_vec, const CharBuf *field);
+}
+
+/* Copyright 2006-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/NOTScorer.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/NOTScorer.c?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/NOTScorer.c (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/NOTScorer.c Thu Oct 14 08:48:04 2010
@@ -0,0 +1,95 @@
+#define C_KINO_NOTSCORER
+#include "KinoSearch/Util/ToolSet.h"
+
+#include "KinoSearch/Search/NOTScorer.h"
+#include "KinoSearch/Index/Similarity.h"
+#include "KinoSearch/Plan/Schema.h"
+
+NOTScorer*
+NOTScorer_new(Matcher *negated_matcher, int32_t doc_max)
+{
+ NOTScorer *self = (NOTScorer*)VTable_Make_Obj(NOTSCORER);
+ return NOTScorer_init(self, negated_matcher, doc_max);
+}
+
+NOTScorer*
+NOTScorer_init(NOTScorer *self, Matcher *negated_matcher, int32_t doc_max)
+{
+ VArray *children = VA_new(1);
+ VA_Push(children, INCREF(negated_matcher));
+ PolyMatcher_init((PolyMatcher*)self, children, NULL);
+
+ // Init.
+ self->doc_id = 0;
+ self->next_negation = 0;
+
+ // Assign.
+ self->negated_matcher = (Matcher*)INCREF(negated_matcher);
+ self->doc_max = doc_max;
+
+ DECREF(children);
+
+ return self;
+}
+
+void
+NOTScorer_destroy(NOTScorer *self)
+{
+ DECREF(self->negated_matcher);
+ SUPER_DESTROY(self, NOTSCORER);
+}
+
+int32_t
+NOTScorer_next(NOTScorer *self)
+{
+ while (1) {
+ self->doc_id++;
+
+ // Get next negated doc id.
+ if (self->next_negation < self->doc_id) {
+ self->next_negation
+ = Matcher_Advance(self->negated_matcher, self->doc_id);
+ if (self->next_negation == 0) {
+ DECREF(self->negated_matcher);
+ self->negated_matcher = NULL;
+ self->next_negation = self->doc_max + 1;
+ }
+ }
+
+ if (self->doc_id > self->doc_max) {
+ self->doc_id = self->doc_max; // halt advance
+ return 0;
+ }
+ else if (self->doc_id != self->next_negation) {
+ // Success!
+ return self->doc_id;
+ }
+ }
+}
+
+int32_t
+NOTScorer_advance(NOTScorer *self, int32_t target)
+{
+ self->doc_id = target - 1;
+ return NOTScorer_next(self);
+}
+
+int32_t
+NOTScorer_get_doc_id(NOTScorer *self)
+{
+ return self->doc_id;
+}
+
+float
+NOTScorer_score(NOTScorer *self)
+{
+ UNUSED_VAR(self);
+ return 0.0f;
+}
+
+/* Copyright 2007-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Propchange: incubator/lucy/trunk/import/core/KinoSearch/Search/NOTScorer.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/NOTScorer.cfh
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/NOTScorer.cfh?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/NOTScorer.cfh (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/NOTScorer.cfh Thu Oct 14 08:48:04 2010
@@ -0,0 +1,40 @@
+parcel KinoSearch cnick Kino;
+
+/** Return the inverse of a Matcher's set. Scores are always 0.
+ */
+
+class KinoSearch::Search::NOTScorer inherits KinoSearch::Search::PolyMatcher {
+
+ Matcher *negated_matcher;
+ int32_t doc_id;
+ int32_t doc_max;
+ int32_t next_negation;
+
+ inert incremented NOTScorer*
+ new(Matcher* negated_matcher, int32_t doc_max);
+
+ inert NOTScorer*
+ init(NOTScorer *self, Matcher *negated_matcher, int32_t doc_max);
+
+ public void
+ Destroy(NOTScorer *self);
+
+ public int32_t
+ Next(NOTScorer *self);
+
+ public int32_t
+ Advance(NOTScorer *self, int32_t target);
+
+ public float
+ Score(NOTScorer *self);
+
+ public int32_t
+ Get_Doc_ID(NOTScorer *self);
+}
+
+/* Copyright 2006-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchQuery.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchQuery.c?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchQuery.c (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchQuery.c Thu Oct 14 08:48:04 2010
@@ -0,0 +1,91 @@
+#define C_KINO_NOMATCHQUERY
+#include "KinoSearch/Util/ToolSet.h"
+
+#include "KinoSearch/Search/NoMatchQuery.h"
+#include "KinoSearch/Index/SegReader.h"
+#include "KinoSearch/Index/Similarity.h"
+#include "KinoSearch/Plan/Schema.h"
+#include "KinoSearch/Search/NoMatchScorer.h"
+#include "KinoSearch/Search/Searcher.h"
+#include "KinoSearch/Store/InStream.h"
+#include "KinoSearch/Store/OutStream.h"
+#include "KinoSearch/Util/Freezer.h"
+
+NoMatchQuery*
+NoMatchQuery_new()
+{
+ NoMatchQuery *self = (NoMatchQuery*)VTable_Make_Obj(NOMATCHQUERY);
+ return NoMatchQuery_init(self);
+}
+
+NoMatchQuery*
+NoMatchQuery_init(NoMatchQuery *self)
+{
+ return (NoMatchQuery*)Query_init((Query*)self, 0.0f);
+}
+
+bool_t
+NoMatchQuery_equals(NoMatchQuery *self, Obj *other)
+{
+ NoMatchQuery *evil_twin = (NoMatchQuery*)other;
+ if (!Obj_Is_A(other, NOMATCHQUERY)) return false;
+ if (self->boost != evil_twin->boost) return false;
+ return true;
+}
+
+CharBuf*
+NoMatchQuery_to_string(NoMatchQuery *self)
+{
+ UNUSED_VAR(self);
+ return CB_new_from_trusted_utf8("[NOMATCH]", 9);
+}
+
+Compiler*
+NoMatchQuery_make_compiler(NoMatchQuery *self, Searcher *searcher,
+ float boost)
+{
+ return (Compiler*)NoMatchCompiler_new(self, searcher, boost);
+}
+
+/**********************************************************************/
+
+NoMatchCompiler*
+NoMatchCompiler_new(NoMatchQuery *parent, Searcher *searcher,
+ float boost)
+{
+ NoMatchCompiler *self
+ = (NoMatchCompiler*)VTable_Make_Obj(NOMATCHCOMPILER);
+ return NoMatchCompiler_init(self, parent, searcher, boost);
+}
+
+NoMatchCompiler*
+NoMatchCompiler_init(NoMatchCompiler *self, NoMatchQuery *parent,
+ Searcher *searcher, float boost)
+{
+ return (NoMatchCompiler*)Compiler_init((Compiler*)self,
+ (Query*)parent, searcher, NULL, boost);
+}
+
+NoMatchCompiler*
+NoMatchCompiler_deserialize(NoMatchCompiler *self, InStream *instream)
+{
+ self = self ? self : (NoMatchCompiler*)VTable_Make_Obj(NOMATCHCOMPILER);
+ return (NoMatchCompiler*)Compiler_deserialize((Compiler*)self, instream);
+}
+
+Matcher*
+NoMatchCompiler_make_matcher(NoMatchCompiler *self, SegReader *reader,
+ bool_t need_score)
+{
+ UNUSED_VAR(self);
+ UNUSED_VAR(reader);
+ UNUSED_VAR(need_score);
+ return (Matcher*)NoMatchScorer_new();
+}
+
+/* Copyright 2008-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Propchange: incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchQuery.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchQuery.cfh
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchQuery.cfh?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchQuery.cfh (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchQuery.cfh Thu Oct 14 08:48:04 2010
@@ -0,0 +1,52 @@
+parcel KinoSearch cnick Kino;
+
+/** Query which matches no documents.
+ *
+ * NoMatchQuery is a utility class representing a query which matches nothing.
+ * Typical usage might include e.g. returning a NoMatchQuery when a
+ * QueryParser is asked to parse an empty string.
+ */
+class KinoSearch::Search::NoMatchQuery inherits KinoSearch::Search::Query
+ : dumpable {
+
+ inert incremented NoMatchQuery*
+ new();
+
+ /** Constructor. Takes no arguments.
+ */
+ public inert NoMatchQuery*
+ init(NoMatchQuery *self);
+
+ public bool_t
+ Equals(NoMatchQuery *self, Obj *other);
+
+ public incremented CharBuf*
+ To_String(NoMatchQuery *self);
+
+ public incremented Compiler*
+ Make_Compiler(NoMatchQuery *self, Searcher *searcher, float boost);
+}
+
+class KinoSearch::Search::NoMatchCompiler
+ inherits KinoSearch::Search::Compiler {
+
+ inert incremented NoMatchCompiler*
+ new(NoMatchQuery *parent, Searcher *searcher, float boost);
+
+ inert NoMatchCompiler*
+ init(NoMatchCompiler *self, NoMatchQuery *parent,
+ Searcher *searcher, float boost);
+
+ public incremented nullable Matcher*
+ Make_Matcher(NoMatchCompiler *self, SegReader *reader, bool_t need_score);
+
+ public incremented NoMatchCompiler*
+ Deserialize(NoMatchCompiler *self, InStream *instream);
+}
+
+/* Copyright 2008-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchScorer.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchScorer.c?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchScorer.c (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchScorer.c Thu Oct 14 08:48:04 2010
@@ -0,0 +1,42 @@
+#define C_KINO_NOMATCHSCORER
+#include "KinoSearch/Util/ToolSet.h"
+
+#include "KinoSearch/Search/NoMatchScorer.h"
+#include "KinoSearch/Index/IndexReader.h"
+#include "KinoSearch/Index/Similarity.h"
+#include "KinoSearch/Plan/Schema.h"
+
+NoMatchScorer*
+NoMatchScorer_new()
+{
+ NoMatchScorer *self = (NoMatchScorer*)VTable_Make_Obj(NOMATCHSCORER);
+ return NoMatchScorer_init(self);
+}
+
+NoMatchScorer*
+NoMatchScorer_init(NoMatchScorer *self)
+{
+ return (NoMatchScorer*)Matcher_init((Matcher*)self);
+}
+
+int32_t
+NoMatchScorer_next(NoMatchScorer* self)
+{
+ UNUSED_VAR(self);
+ return 0;
+}
+
+int32_t
+NoMatchScorer_advance(NoMatchScorer* self, int32_t target)
+{
+ UNUSED_VAR(self);
+ UNUSED_VAR(target);
+ return 0;
+}
+
+/* Copyright 2007-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Propchange: incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchScorer.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchScorer.cfh
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchScorer.cfh?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchScorer.cfh (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/NoMatchScorer.cfh Thu Oct 14 08:48:04 2010
@@ -0,0 +1,23 @@
+parcel KinoSearch cnick Kino;
+
+class KinoSearch::Search::NoMatchScorer inherits KinoSearch::Search::Matcher {
+
+ inert incremented NoMatchScorer*
+ new();
+
+ inert NoMatchScorer*
+ init(NoMatchScorer *self);
+
+ public int32_t
+ Next(NoMatchScorer* self);
+
+ public int32_t
+ Advance(NoMatchScorer* self, int32_t target);
+}
+
+/* Copyright 2008-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/ORMatcher.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/ORMatcher.c?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/ORMatcher.c (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/ORMatcher.c Thu Oct 14 08:48:04 2010
@@ -0,0 +1,406 @@
+#define C_KINO_ORMATCHER
+#define C_KINO_ORSCORER
+#include "KinoSearch/Util/ToolSet.h"
+
+#include "KinoSearch/Search/ORMatcher.h"
+#include "KinoSearch/Index/Similarity.h"
+
+// Add an element to the queue. Unsafe -- bounds checking of queue size is
+// left to the caller.
+static void
+S_add_element(ORMatcher *self, Matcher *matcher, int32_t doc_id);
+
+// Empty out the queue.
+static void
+S_clear(ORMatcher *self);
+
+// Call Matcher_Next() on the top queue element and adjust the queue,
+// removing the element if Matcher_Next() returns false.
+static INLINE int32_t
+SI_top_next(ORMatcher *self);
+
+// Call Matcher_Advance() on the top queue element and adjust the queue,
+// removing the element if Matcher_Advance() returns false.
+static INLINE int32_t
+SI_top_advance(ORMatcher *self, int32_t target);
+
+/* React to a change in the top element, or "root" -- presumably the update of
+ * its doc_id resulting from a call to Matcher_Next() or Matcher_Advance().
+ * If the Matcher has been exhausted, remove it from the queue and replace it
+ * with the bottom node (i.e. perform "root replacement"). In either case,
+ * perform a "sift down" to restore the heap property. Return the doc id of
+ * the root node, or 0 if the queue has been emptied.
+ */
+static int32_t
+S_adjust_root(ORMatcher *self);
+
+// Take the bottom node (which probably violates the heap property when this
+// is called) and bubble it up through the heap until the heap property is
+// restored.
+static void
+S_bubble_up(ORMatcher *self);
+
+// Take the top node (which probably violates the heap property when this
+// is called) and sift it down through the heap until the heap property is
+// restored.
+static void
+S_sift_down(ORMatcher *self);
+
+ORMatcher*
+ORMatcher_new(VArray *children)
+{
+ ORMatcher *self = (ORMatcher*)VTable_Make_Obj(ORMATCHER);
+ return ORMatcher_init(self, children);
+}
+
+static ORMatcher*
+S_ormatcher_init2(ORMatcher *self, VArray *children, Similarity *sim)
+{
+ size_t amount_to_malloc;
+ uint32_t i;
+
+ // Init.
+ PolyMatcher_init((PolyMatcher*)self, children, sim);
+ self->size = 0;
+
+ // Derive.
+ self->max_size = VA_Get_Size(children);
+
+ // Allocate.
+ self->heap = (HeapedMatcherDoc**)CALLOCATE(self->max_size + 1, sizeof(HeapedMatcherDoc*));
+
+ // Create a pool of HMDs. Encourage CPU cache hits by using a single
+ // allocation for all of them.
+ amount_to_malloc = (self->max_size + 1) * sizeof(HeapedMatcherDoc);
+ self->blob = (char*)MALLOCATE(amount_to_malloc);
+ self->pool = (HeapedMatcherDoc**)CALLOCATE(self->max_size + 1, sizeof(HeapedMatcherDoc*));
+ for (i = 1; i <= self->max_size; i++) {
+ size_t offset = i * sizeof(HeapedMatcherDoc);
+ HeapedMatcherDoc *hmd = (HeapedMatcherDoc*)(self->blob + offset);
+ self->pool[i] = hmd;
+ }
+
+ // Prime queue.
+ for (i = 0; i < self->max_size; i++) {
+ Matcher *matcher = (Matcher*)VA_Fetch(children, i);
+ S_add_element(self, (Matcher*)INCREF(matcher), 0);
+ }
+
+ return self;
+}
+
+ORMatcher*
+ORMatcher_init(ORMatcher *self, VArray *children)
+{
+ return S_ormatcher_init2(self, children, NULL);
+}
+
+void
+ORMatcher_destroy(ORMatcher *self)
+{
+ if (self->blob) { S_clear(self); }
+ FREEMEM(self->blob);
+ FREEMEM(self->pool);
+ FREEMEM(self->heap);
+ SUPER_DESTROY(self, ORMATCHER);
+}
+
+int32_t
+ORMatcher_next(ORMatcher *self)
+{
+ if (self->size == 0) {
+ return 0;
+ }
+ else {
+ int32_t last_doc_id = self->top_hmd->doc;
+ while (self->top_hmd->doc == last_doc_id) {
+ int32_t top_doc_id = SI_top_next(self);
+ if (!top_doc_id && self->size == 0) {
+ return 0;
+ }
+ }
+ return self->top_hmd->doc;
+ }
+}
+
+int32_t
+ORMatcher_advance(ORMatcher *self, int32_t target)
+{
+ if (!self->size) { return 0; }
+ do {
+ int32_t least = SI_top_advance(self, target);
+ if (least >= target) { return least; }
+ if (!least) {
+ if (!self->size) { return 0; }
+ }
+ } while (true);
+}
+
+int32_t
+ORMatcher_get_doc_id(ORMatcher *self)
+{
+ return self->top_hmd->doc;
+}
+
+static void
+S_clear(ORMatcher *self)
+{
+ HeapedMatcherDoc **const heap = self->heap;
+ HeapedMatcherDoc **const pool = self->pool;
+
+ // Node 0 is held empty, to make the algo clearer.
+ for ( ; self->size > 0; self->size--) {
+ HeapedMatcherDoc *hmd = heap[ self->size ];
+ heap[ self->size ] = NULL;
+ DECREF(hmd->matcher);
+
+ // Put HMD back in pool.
+ pool[ self->size ] = hmd;
+ }
+}
+
+static INLINE int32_t
+SI_top_next(ORMatcher *self)
+{
+ HeapedMatcherDoc *const top_hmd = self->top_hmd;
+ top_hmd->doc = Matcher_Next(top_hmd->matcher);
+ return S_adjust_root(self);
+}
+
+static INLINE int32_t
+SI_top_advance(ORMatcher *self, int32_t target)
+{
+ HeapedMatcherDoc *const top_hmd = self->top_hmd;
+ top_hmd->doc = Matcher_Advance(top_hmd->matcher, target);
+ return S_adjust_root(self);
+}
+
+static void
+S_add_element(ORMatcher *self, Matcher *matcher, int32_t doc_id)
+{
+ HeapedMatcherDoc **const heap = self->heap;
+ HeapedMatcherDoc **const pool = self->pool;
+ HeapedMatcherDoc *hmd;
+
+ // Increment size.
+ self->size++;
+
+ // Put element at the bottom of the heap.
+ hmd = pool[ self->size ];
+ hmd->matcher = matcher;
+ hmd->doc = doc_id;
+ heap[ self->size ] = hmd;
+
+ // Adjust heap.
+ S_bubble_up(self);
+}
+
+static int32_t
+S_adjust_root(ORMatcher *self)
+{
+ HeapedMatcherDoc *const top_hmd = self->top_hmd;
+
+ // Inlined pop.
+ if (!top_hmd->doc) {
+ HeapedMatcherDoc *const last_hmd = self->heap[ self->size ];
+
+ // Last to first.
+ DECREF(top_hmd->matcher);
+ top_hmd->matcher = last_hmd->matcher;
+ top_hmd->doc = last_hmd->doc;
+ self->heap[ self->size ] = NULL;
+
+ // Put back in pool.
+ self->pool[ self->size ] = last_hmd;
+
+ self->size--;
+ if (self->size == 0)
+ return 0;
+ }
+
+ // Move queue no matter what.
+ S_sift_down(self);
+
+ return self->top_hmd->doc;
+}
+
+static void
+S_bubble_up(ORMatcher *self)
+{
+ HeapedMatcherDoc **const heap = self->heap;
+ uint32_t i = self->size;
+ uint32_t j = i >> 1;
+ HeapedMatcherDoc *const node = heap[i]; // save bottom node
+
+ while (j > 0 && node->doc < heap[j]->doc) {
+ heap[i] = heap[j];
+ i = j;
+ j = j >> 1;
+ }
+ heap[i] = node;
+ self->top_hmd = heap[1];
+}
+
+static void
+S_sift_down(ORMatcher *self)
+{
+ HeapedMatcherDoc **const heap = self->heap;
+ uint32_t i = 1;
+ uint32_t j = i << 1;
+ uint32_t k = j + 1;
+ HeapedMatcherDoc *const node = heap[i]; // save top node
+
+ // Find smaller child.
+ if (k <= self->size && heap[k]->doc < heap[j]->doc) {
+ j = k;
+ }
+
+ while (j <= self->size && heap[j]->doc < node->doc) {
+ heap[i] = heap[j];
+ i = j;
+ j = i << 1;
+ k = j + 1;
+ if (k <= self->size && heap[k]->doc < heap[j]->doc) {
+ j = k;
+ }
+ }
+ heap[i] = node;
+
+ self->top_hmd = heap[1];
+}
+
+/***************************************************************************/
+
+/* When this is called, all children are past the current self->doc_id. The
+ * least doc_id amongst them becomes the new self->doc_id, and they are all
+ * advanced so that they are once again out in front of it. While they are
+ * advancing, their scores are cached in an array, to be summed during
+ * Score().
+ */
+static int32_t
+S_advance_after_current(ORScorer *self);
+
+ORScorer*
+ORScorer_new(VArray *children, Similarity *sim)
+{
+ ORScorer *self = (ORScorer*)VTable_Make_Obj(ORSCORER);
+ return ORScorer_init(self, children, sim);
+}
+
+ORScorer*
+ORScorer_init(ORScorer *self, VArray *children, Similarity *sim)
+{
+ S_ormatcher_init2((ORMatcher*)self, children, sim);
+ self->doc_id = 0;
+ self->scores = (float*)MALLOCATE(self->num_kids * sizeof(float));
+
+ // Establish the state of all child matchers being past the current doc
+ // id, by invoking ORMatcher's Next() method.
+ ORMatcher_next((ORMatcher*)self);
+
+ return self;
+}
+
+void
+ORScorer_destroy(ORScorer *self)
+{
+ FREEMEM(self->scores);
+ SUPER_DESTROY(self, ORSCORER);
+}
+
+int32_t
+ORScorer_next(ORScorer *self)
+{
+ return S_advance_after_current(self);
+}
+
+static int32_t
+S_advance_after_current(ORScorer *self)
+{
+ float *const scores = self->scores;
+ Matcher *child;
+
+ // Get the top Matcher, or bail because there are no Matchers left.
+ if (!self->size) { return 0; }
+ else { child = self->top_hmd->matcher; }
+
+ // The top matcher will already be at the correct doc, so start there.
+ self->doc_id = self->top_hmd->doc;
+ scores[0] = Matcher_Score(child);
+ self->matching_kids = 1;
+
+ do {
+ // Attempt to advance past current doc.
+ int32_t top_doc_id = SI_top_next((ORMatcher*)self);
+ if (!top_doc_id) {
+ if (!self->size) {
+ break; // bail, no more to advance
+ }
+ }
+
+ if (top_doc_id != self->doc_id) {
+ // Bail, least doc in queue is now past the one we're scoring.
+ break;
+ }
+ else {
+ // Accumulate score.
+ child = self->top_hmd->matcher;
+ scores[ self->matching_kids ] = Matcher_Score(child);
+ self->matching_kids++;
+ }
+ } while (true);
+
+ return self->doc_id;
+}
+
+int32_t
+ORScorer_advance(ORScorer *self, int32_t target)
+{
+ // Return sentinel once exhausted.
+ if (!self->size) { return 0; }
+
+ // Succeed if we're already past and still on a valid doc.
+ if (target <= self->doc_id) {
+ return self->doc_id;
+ }
+
+ do {
+ // If all matchers are caught up, accumulate score and return.
+ if (self->top_hmd->doc >= target) {
+ return S_advance_after_current(self);
+ }
+
+ // Not caught up yet, so keep skipping matchers.
+ if ( !SI_top_advance((ORMatcher*)self, target) ) {
+ if (!self->size) { return 0; }
+ }
+ } while (true);
+}
+
+int32_t
+ORScorer_get_doc_id(ORScorer *self)
+{
+ return self->doc_id;
+}
+
+float
+ORScorer_score(ORScorer *self)
+{
+ float *const scores = self->scores;
+ float score = 0.0f;
+ uint32_t i;
+
+ // Accumulate score, then factor in coord bonus.
+ for (i = 0; i < self->matching_kids; i++) {
+ score += scores[i];
+ }
+ score *= self->coord_factors[ self->matching_kids ];
+
+ return score;
+}
+
+/* Copyright 2007-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
Propchange: incubator/lucy/trunk/import/core/KinoSearch/Search/ORMatcher.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/ORMatcher.cfh
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/ORMatcher.cfh?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/ORMatcher.cfh (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/ORMatcher.cfh Thu Oct 14 08:48:04 2010
@@ -0,0 +1,92 @@
+parcel KinoSearch cnick Kino;
+
+__C__
+#include "KinoSearch/Search/Matcher.h"
+
+/* A wrapper for a Matcher which caches the result of Matcher_Get_Doc_ID().
+ */
+typedef struct kino_HeapedMatcherDoc {
+ kino_Matcher *matcher;
+ int32_t doc;
+} kino_HeapedMatcherDoc;
+
+#ifdef KINO_USE_SHORT_NAMES
+ #define HeapedMatcherDoc kino_HeapedMatcherDoc
+#endif
+
+__END_C__
+
+/** Matcher which unions the doc id sets of other Matchers using a priority
+ * queue.
+ */
+
+class KinoSearch::Search::ORMatcher inherits KinoSearch::Search::PolyMatcher {
+
+ HeapedMatcherDoc **heap;
+ HeapedMatcherDoc **pool; /* Pool of HMDs to minimize mallocs */
+ char *blob; /* single allocation for all HMDs */
+ HeapedMatcherDoc *top_hmd; /* cached top elem */
+ uint32_t size;
+ uint32_t max_size;
+
+ inert incremented ORMatcher*
+ new(VArray *children);
+
+ /**
+ * @param children An array of Matchers.
+ */
+ inert incremented ORMatcher*
+ init(ORMatcher *self, VArray *children);
+
+ public void
+ Destroy(ORMatcher *self);
+
+ public int32_t
+ Next(ORMatcher *self);
+
+ public int32_t
+ Advance(ORMatcher *self, int32_t target);
+
+ public int32_t
+ Get_Doc_ID(ORMatcher *self);
+}
+
+/**
+ * Union results of multiple Matchers.
+ *
+ * ORScorer collates the output of multiple subscorers, summing their scores
+ * whenever they match the same document.
+ */
+class KinoSearch::Search::ORScorer inherits KinoSearch::Search::ORMatcher {
+
+ float *scores;
+ int32_t doc_id;
+
+ inert incremented ORScorer*
+ new(VArray *children, Similarity *similarity);
+
+ inert ORScorer*
+ init(ORScorer *self, VArray *children, Similarity *similarity);
+
+ public void
+ Destroy(ORScorer *self);
+
+ public int32_t
+ Next(ORScorer *self);
+
+ public int32_t
+ Advance(ORScorer *self, int32_t target);
+
+ public float
+ Score(ORScorer *self);
+
+ public int32_t
+ Get_Doc_ID(ORScorer *self);
+}
+
+/* Copyright 2007-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/ORQuery.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/ORQuery.c?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/ORQuery.c (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/ORQuery.c Thu Oct 14 08:48:04 2010
@@ -0,0 +1,136 @@
+#define C_KINO_ORQUERY
+#define C_KINO_ORCOMPILER
+#include "KinoSearch/Util/ToolSet.h"
+
+#include "KinoSearch/Search/ORQuery.h"
+#include "KinoSearch/Index/SegReader.h"
+#include "KinoSearch/Index/Similarity.h"
+#include "KinoSearch/Search/ORMatcher.h"
+#include "KinoSearch/Search/Searcher.h"
+#include "KinoSearch/Store/InStream.h"
+#include "KinoSearch/Store/OutStream.h"
+
+ORQuery*
+ORQuery_new(VArray *children)
+{
+ ORQuery *self = (ORQuery*)VTable_Make_Obj(ORQUERY);
+ return ORQuery_init(self, children);
+}
+
+ORQuery*
+ORQuery_init(ORQuery *self, VArray *children)
+{
+ return (ORQuery*)PolyQuery_init((PolyQuery*)self, children);
+}
+
+Compiler*
+ORQuery_make_compiler(ORQuery *self, Searcher *searcher, float boost)
+{
+ return (Compiler*)ORCompiler_new(self, searcher, boost);
+}
+
+bool_t
+ORQuery_equals(ORQuery *self, Obj *other)
+{
+ if ((ORQuery*)other == self) { return true; }
+ if (!Obj_Is_A(other, ORQUERY)) { return false; }
+ return PolyQuery_equals((PolyQuery*)self, other);
+}
+
+CharBuf*
+ORQuery_to_string(ORQuery *self)
+{
+ uint32_t num_kids = VA_Get_Size(self->children);
+ if (!num_kids) return CB_new_from_trusted_utf8("()", 2);
+ else {
+ CharBuf *retval = CB_new_from_trusted_utf8("(", 1);
+ uint32_t i;
+ uint32_t last_kid = num_kids - 1;
+ for (i = 0; i < num_kids; i++) {
+ CharBuf *kid_string = Obj_To_String(VA_Fetch(self->children, i));
+ CB_Cat(retval, kid_string);
+ DECREF(kid_string);
+ if (i == last_kid) {
+ CB_Cat_Trusted_Str(retval, ")", 1);
+ }
+ else {
+ CB_Cat_Trusted_Str(retval, " OR ", 4);
+ }
+ }
+ return retval;
+ }
+}
+
+/**********************************************************************/
+
+ORCompiler*
+ORCompiler_new(ORQuery *parent, Searcher *searcher, float boost)
+{
+ ORCompiler *self = (ORCompiler*)VTable_Make_Obj(ORCOMPILER);
+ return ORCompiler_init(self, parent, searcher, boost);
+}
+
+ORCompiler*
+ORCompiler_init(ORCompiler *self, ORQuery *parent, Searcher *searcher,
+ float boost)
+{
+ PolyCompiler_init((PolyCompiler*)self, (PolyQuery*)parent, searcher,
+ boost);
+ ORCompiler_Normalize(self);
+ return self;
+}
+
+Matcher*
+ORCompiler_make_matcher(ORCompiler *self, SegReader *reader,
+ bool_t need_score)
+{
+ uint32_t num_kids = VA_Get_Size(self->children);
+
+ if (num_kids == 1) {
+ Compiler *only_child = (Compiler*)VA_Fetch(self->children, 0);
+ return Compiler_Make_Matcher(only_child, reader, need_score);
+ }
+ else {
+ VArray *submatchers = VA_new(num_kids);
+ uint32_t i;
+ uint32_t num_submatchers = 0;
+
+ // Accumulate sub-matchers.
+ for (i = 0; i < num_kids; i++) {
+ Compiler *child = (Compiler*)VA_Fetch(self->children, i);
+ Matcher *submatcher
+ = Compiler_Make_Matcher(child, reader, need_score);
+ if (submatcher != NULL) {
+ VA_Push(submatchers, (Obj*)submatcher);
+ num_submatchers++;
+ }
+ }
+
+ if (num_submatchers == 0) {
+ // No possible matches, so return null.
+ DECREF(submatchers);
+ return NULL;
+ }
+ else if (num_submatchers == 1) {
+ // Only one submatcher, so no need for ORScorer wrapper.
+ Matcher *submatcher = (Matcher*)INCREF(VA_Fetch(submatchers, 0));
+ DECREF(submatchers);
+ return submatcher;
+ }
+ else {
+ Similarity *sim = ORCompiler_Get_Similarity(self);
+ Matcher *retval = need_score
+ ? (Matcher*)ORScorer_new(submatchers, sim)
+ : (Matcher*)ORMatcher_new(submatchers);
+ DECREF(submatchers);
+ return retval;
+ }
+ }
+}
+
+/* Copyright 2006-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Propchange: incubator/lucy/trunk/import/core/KinoSearch/Search/ORQuery.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/ORQuery.cfh
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/ORQuery.cfh?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/ORQuery.cfh (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/ORQuery.cfh Thu Oct 14 08:48:04 2010
@@ -0,0 +1,51 @@
+parcel KinoSearch cnick Kino;
+
+/** Union multiple result sets.
+ *
+ * ORQuery matches when any of its children match, so its result set is
+ * the union of their result sets. Matching documents recieve a summed
+ * score from all matching child Queries.
+ */
+
+class KinoSearch::Search::ORQuery inherits KinoSearch::Search::PolyQuery
+ : dumpable {
+
+ inert incremented ORQuery*
+ new(VArray *children = NULL);
+
+ /**
+ * @param children An array of child Queries.
+ */
+ public inert ORQuery*
+ init(ORQuery *self, VArray *children = NULL);
+
+ public incremented Compiler*
+ Make_Compiler(ORQuery *self, Searcher *searcher, float boost);
+
+ public incremented CharBuf*
+ To_String(ORQuery *self);
+
+ public bool_t
+ Equals(ORQuery *self, Obj *other);
+}
+
+class KinoSearch::Search::ORCompiler
+ inherits KinoSearch::Search::PolyCompiler {
+
+ inert incremented ORCompiler*
+ new(ORQuery *parent, Searcher *searcher, float boost);
+
+ inert ORCompiler*
+ init(ORCompiler *self, ORQuery *parent, Searcher *searcher,
+ float boost);
+
+ public incremented nullable Matcher*
+ Make_Matcher(ORCompiler *self, SegReader *reader, bool_t need_score);
+}
+
+/* Copyright 2006-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseQuery.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseQuery.c?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseQuery.c (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseQuery.c Thu Oct 14 08:48:04 2010
@@ -0,0 +1,402 @@
+#define C_KINO_PHRASEQUERY
+#define C_KINO_PHRASECOMPILER
+#include <stdarg.h>
+
+#include "KinoSearch/Util/ToolSet.h"
+
+#include "KinoSearch/Search/PhraseQuery.h"
+#include "KinoSearch/Index/DocVector.h"
+#include "KinoSearch/Index/Posting.h"
+#include "KinoSearch/Index/Posting/ScorePosting.h"
+#include "KinoSearch/Index/PostingList.h"
+#include "KinoSearch/Index/PostingListReader.h"
+#include "KinoSearch/Index/SegPostingList.h"
+#include "KinoSearch/Index/SegReader.h"
+#include "KinoSearch/Index/Similarity.h"
+#include "KinoSearch/Index/TermVector.h"
+#include "KinoSearch/Plan/Schema.h"
+#include "KinoSearch/Search/PhraseScorer.h"
+#include "KinoSearch/Search/Searcher.h"
+#include "KinoSearch/Search/Span.h"
+#include "KinoSearch/Search/TermQuery.h"
+#include "KinoSearch/Store/InStream.h"
+#include "KinoSearch/Store/OutStream.h"
+#include "KinoSearch/Util/Freezer.h"
+
+// Shared initialization routine which assumes that it's ok to assume control
+// over [field] and [terms], eating their refcounts.
+static PhraseQuery*
+S_do_init(PhraseQuery *self, CharBuf *field, VArray *terms, float boost);
+
+PhraseQuery*
+PhraseQuery_new(const CharBuf *field, VArray *terms)
+{
+ PhraseQuery *self = (PhraseQuery*)VTable_Make_Obj(PHRASEQUERY);
+ return PhraseQuery_init(self, field, terms);
+}
+
+PhraseQuery*
+PhraseQuery_init(PhraseQuery *self, const CharBuf *field, VArray *terms)
+{
+ return S_do_init(self, CB_Clone(field), VA_Clone(terms), 1.0f);
+}
+
+void
+PhraseQuery_destroy(PhraseQuery *self)
+{
+ DECREF(self->terms);
+ DECREF(self->field);
+ SUPER_DESTROY(self, PHRASEQUERY);
+}
+
+static PhraseQuery*
+S_do_init(PhraseQuery *self, CharBuf *field, VArray *terms, float boost)
+{
+ uint32_t i, max;
+ Query_init((Query*)self, boost);
+ for (i = 0, max = VA_Get_Size(terms); i < max; i++) {
+ CERTIFY(VA_Fetch(terms, i), OBJ);
+ }
+ self->field = field;
+ self->terms = terms;
+ return self;
+}
+
+void
+PhraseQuery_serialize(PhraseQuery *self, OutStream *outstream)
+{
+ OutStream_Write_F32(outstream, self->boost);
+ CB_Serialize(self->field, outstream);
+ VA_Serialize(self->terms, outstream);
+}
+
+PhraseQuery*
+PhraseQuery_deserialize(PhraseQuery *self, InStream *instream)
+{
+ float boost = InStream_Read_F32(instream);
+ CharBuf *field = CB_deserialize(NULL, instream);
+ VArray *terms = VA_deserialize(NULL, instream);
+ self = self ? self : (PhraseQuery*)VTable_Make_Obj(PHRASEQUERY);
+ return S_do_init(self, field, terms, boost);
+}
+
+bool_t
+PhraseQuery_equals(PhraseQuery *self, Obj *other)
+{
+ PhraseQuery *evil_twin = (PhraseQuery*)other;
+ if (evil_twin == self) return true;
+ if (!Obj_Is_A(other, PHRASEQUERY)) return false;
+ if (self->boost != evil_twin->boost) return false;
+ if (self->field && !evil_twin->field) return false;
+ if (!self->field && evil_twin->field) return false;
+ if (self->field && !CB_Equals(self->field, (Obj*)evil_twin->field))
+ return false;
+ if (!VA_Equals(evil_twin->terms, (Obj*)self->terms)) return false;
+ return true;
+}
+
+CharBuf*
+PhraseQuery_to_string(PhraseQuery *self)
+{
+ uint32_t i;
+ uint32_t num_terms = VA_Get_Size(self->terms);
+ CharBuf *retval = CB_Clone(self->field);
+ CB_Cat_Trusted_Str(retval, ":\"", 2);
+ for (i = 0; i < num_terms; i++) {
+ Obj *term = VA_Fetch(self->terms, i);
+ CharBuf *term_string = Obj_To_String(term);
+ CB_Cat(retval, term_string);
+ DECREF(term_string);
+ if (i < num_terms - 1) {
+ CB_Cat_Trusted_Str(retval, " ", 1);
+ }
+ }
+ CB_Cat_Trusted_Str(retval, "\"", 1);
+ return retval;
+}
+
+Compiler*
+PhraseQuery_make_compiler(PhraseQuery *self, Searcher *searcher,
+ float boost)
+{
+ if (VA_Get_Size(self->terms) == 1) {
+ // Optimize for one-term "phrases".
+ Obj *term = VA_Fetch(self->terms, 0);
+ TermQuery *term_query = TermQuery_new(self->field, term);
+ TermCompiler *term_compiler;
+ TermQuery_Set_Boost(term_query, self->boost);
+ term_compiler = (TermCompiler*)TermQuery_Make_Compiler(term_query,
+ searcher, boost);
+ DECREF(term_query);
+ return (Compiler*)term_compiler;
+ }
+ else {
+ return (Compiler*)PhraseCompiler_new(self, searcher, boost);
+ }
+}
+
+CharBuf*
+PhraseQuery_get_field(PhraseQuery *self) { return self->field; }
+VArray*
+PhraseQuery_get_terms(PhraseQuery *self) { return self->terms; }
+
+/*********************************************************************/
+
+PhraseCompiler*
+PhraseCompiler_new(PhraseQuery *parent, Searcher *searcher, float boost)
+{
+ PhraseCompiler *self = (PhraseCompiler*)VTable_Make_Obj(PHRASECOMPILER);
+ return PhraseCompiler_init(self, parent, searcher, boost);
+}
+
+PhraseCompiler*
+PhraseCompiler_init(PhraseCompiler *self, PhraseQuery *parent,
+ Searcher *searcher, float boost)
+{
+ Schema *schema = Searcher_Get_Schema(searcher);
+ Similarity *sim = Schema_Fetch_Sim(schema, parent->field);
+ VArray *terms = parent->terms;
+ uint32_t i, max;
+
+ // Try harder to find a Similarity if necessary.
+ if (!sim) { sim = Schema_Get_Similarity(schema); }
+
+ // Init.
+ Compiler_init((Compiler*)self, (Query*)parent, searcher, sim, boost);
+
+ // Store IDF for the phrase.
+ self->idf = 0;
+ for (i = 0, max = VA_Get_Size(terms); i < max; i++) {
+ Obj *term = VA_Fetch(terms, i);
+ int32_t doc_max = Searcher_Doc_Max(searcher);
+ int32_t doc_freq = Searcher_Doc_Freq(searcher, parent->field, term);
+ self->idf += Sim_IDF(sim, doc_freq, doc_max);
+ }
+
+ // Calculate raw weight.
+ self->raw_weight = self->idf * self->boost;
+
+ // Make final preparations.
+ PhraseCompiler_Normalize(self);
+
+ return self;
+}
+
+void
+PhraseCompiler_serialize(PhraseCompiler *self, OutStream *outstream)
+{
+ Compiler_serialize((Compiler*)self, outstream);
+ OutStream_Write_F32(outstream, self->idf);
+ OutStream_Write_F32(outstream, self->raw_weight);
+ OutStream_Write_F32(outstream, self->query_norm_factor);
+ OutStream_Write_F32(outstream, self->normalized_weight);
+}
+
+PhraseCompiler*
+PhraseCompiler_deserialize(PhraseCompiler *self, InStream *instream)
+{
+ self = self ? self : (PhraseCompiler*)VTable_Make_Obj(PHRASECOMPILER);
+ Compiler_deserialize((Compiler*)self, instream);
+ self->idf = InStream_Read_F32(instream);
+ self->raw_weight = InStream_Read_F32(instream);
+ self->query_norm_factor = InStream_Read_F32(instream);
+ self->normalized_weight = InStream_Read_F32(instream);
+ return self;
+}
+
+bool_t
+PhraseCompiler_equals(PhraseCompiler *self, Obj *other)
+{
+ PhraseCompiler *evil_twin = (PhraseCompiler*)other;
+ if (!Obj_Is_A(other, PHRASECOMPILER)) return false;
+ if (!Compiler_equals((Compiler*)self, other)) return false;
+ if (self->idf != evil_twin->idf) return false;
+ if (self->raw_weight != evil_twin->raw_weight) return false;
+ if (self->query_norm_factor != evil_twin->query_norm_factor) return false;
+ if (self->normalized_weight != evil_twin->normalized_weight) return false;
+ return true;
+}
+
+float
+PhraseCompiler_get_weight(PhraseCompiler *self)
+{
+ return self->normalized_weight;
+}
+
+float
+PhraseCompiler_sum_of_squared_weights(PhraseCompiler *self)
+{
+ return self->raw_weight * self->raw_weight;
+}
+
+void
+PhraseCompiler_apply_norm_factor(PhraseCompiler *self, float factor)
+{
+ self->query_norm_factor = factor;
+ self->normalized_weight = self->raw_weight * self->idf * factor;
+}
+
+Matcher*
+PhraseCompiler_make_matcher(PhraseCompiler *self, SegReader *reader,
+ bool_t need_score)
+{
+ UNUSED_VAR(need_score);
+ PhraseQuery *const parent = (PhraseQuery*)self->parent;
+ VArray *const terms = parent->terms;
+ uint32_t num_terms = VA_Get_Size(terms);
+
+ // Bail if there are no terms.
+ if (!num_terms) return NULL;
+
+ // Bail unless field is valid and posting type supports positions.
+ Similarity *sim = PhraseCompiler_Get_Similarity(self);
+ Posting *posting = Sim_Make_Posting(sim);
+ if (posting == NULL || !Obj_Is_A((Obj*)posting, SCOREPOSTING)) {
+ DECREF(posting);
+ return NULL;
+ }
+ DECREF(posting);
+
+ // Bail if there's no PostingListReader for this segment.
+ PostingListReader *const plist_reader = (PostingListReader*)SegReader_Fetch(
+ reader, VTable_Get_Name(POSTINGLISTREADER));
+ if (!plist_reader) { return NULL; }
+
+ // Look up each term.
+ VArray *plists = VA_new(num_terms);
+ for (uint32_t i = 0; i < num_terms; i++) {
+ Obj *term = VA_Fetch(terms, i);
+ PostingList *plist
+ = PListReader_Posting_List(plist_reader, parent->field, term);
+
+ // Bail if any one of the terms isn't in the index.
+ if (!plist || !PList_Get_Doc_Freq(plist)) {
+ DECREF(plist);
+ DECREF(plists);
+ return NULL;
+ }
+ VA_Push(plists, (Obj*)plist);
+ }
+
+ Matcher *retval
+ = (Matcher*)PhraseScorer_new(sim, plists, (Compiler*)self);
+ DECREF(plists);
+ return retval;
+}
+
+VArray*
+PhraseCompiler_highlight_spans(PhraseCompiler *self, Searcher *searcher,
+ DocVector *doc_vec, const CharBuf *field)
+{
+ PhraseQuery *const parent = (PhraseQuery*)self->parent;
+ VArray *const terms = parent->terms;
+ VArray *const spans = VA_new(0);
+ VArray *term_vectors;
+ BitVector *posit_vec;
+ BitVector *other_posit_vec;
+ uint32_t i;
+ const uint32_t num_terms = VA_Get_Size(terms);
+ uint32_t num_tvs;
+ UNUSED_VAR(searcher);
+
+ // Bail if no terms or field doesn't match.
+ if (!num_terms) { return spans; }
+ if (!CB_Equals(field, (Obj*)parent->field)) { return spans; }
+
+ term_vectors = VA_new(num_terms);
+ posit_vec = BitVec_new(0);
+ other_posit_vec = BitVec_new(0);
+ for (i = 0; i < num_terms; i++) {
+ Obj *term = VA_Fetch(terms, i);
+ TermVector *term_vector
+ = DocVec_Term_Vector(doc_vec, field, (CharBuf*)term);
+
+ // Bail if any term is missing.
+ if (!term_vector)
+ break;
+
+ VA_Push(term_vectors, (Obj*)term_vector);
+
+ if (i == 0) {
+ // Set initial positions from first term.
+ uint32_t j;
+ I32Array *positions = TV_Get_Positions(term_vector);
+ for (j = I32Arr_Get_Size(positions); j > 0; j--) {
+ BitVec_Set(posit_vec, I32Arr_Get(positions, j - 1));
+ }
+ }
+ else {
+ // Filter positions using logical "and".
+ uint32_t j;
+ I32Array *positions = TV_Get_Positions(term_vector);
+
+ BitVec_Clear_All(other_posit_vec);
+ for (j = I32Arr_Get_Size(positions); j > 0; j--) {
+ int32_t pos = I32Arr_Get(positions, j - 1) - i;
+ if (pos >= 0) {
+ BitVec_Set(other_posit_vec, pos);
+ }
+ }
+ BitVec_And(posit_vec, other_posit_vec);
+ }
+ }
+
+ // Proceed only if all terms are present.
+ num_tvs = VA_Get_Size(term_vectors);
+ if (num_tvs == num_terms) {
+ TermVector *first_tv = (TermVector*)VA_Fetch(term_vectors, 0);
+ TermVector *last_tv
+ = (TermVector*)VA_Fetch(term_vectors, num_tvs - 1);
+ I32Array *tv_start_positions = TV_Get_Positions(first_tv);
+ I32Array *tv_end_positions = TV_Get_Positions(last_tv);
+ I32Array *tv_start_offsets = TV_Get_Start_Offsets(first_tv);
+ I32Array *tv_end_offsets = TV_Get_End_Offsets(last_tv);
+ uint32_t terms_max = num_terms - 1;
+ I32Array *valid_posits = BitVec_To_Array(posit_vec);
+ uint32_t num_valid_posits = I32Arr_Get_Size(valid_posits);
+ uint32_t j = 0;
+ uint32_t posit_tick;
+ float weight = PhraseCompiler_Get_Weight(self);
+ i = 0;
+
+ // Add only those starts/ends that belong to a valid position.
+ for (posit_tick = 0; posit_tick < num_valid_posits; posit_tick++) {
+ int32_t valid_start_posit = I32Arr_Get(valid_posits, posit_tick);
+ int32_t valid_end_posit = valid_start_posit + terms_max;
+ int32_t start_offset = 0, end_offset = 0;
+ uint32_t max;
+
+ for (max = I32Arr_Get_Size(tv_start_positions); i < max; i++) {
+ if (I32Arr_Get(tv_start_positions, i) == valid_start_posit) {
+ start_offset = I32Arr_Get(tv_start_offsets, i);
+ break;
+ }
+ }
+ for (max = I32Arr_Get_Size(tv_end_positions); j < max; j++) {
+ if (I32Arr_Get(tv_end_positions, j) == valid_end_posit) {
+ end_offset = I32Arr_Get(tv_end_offsets, j);
+ break;
+ }
+ }
+
+ VA_Push(spans, (Obj*)Span_new(start_offset,
+ end_offset - start_offset, weight) );
+
+ i++, j++;
+ }
+
+ DECREF(valid_posits);
+ }
+
+ DECREF(other_posit_vec);
+ DECREF(posit_vec);
+ DECREF(term_vectors);
+ return spans;
+}
+
+/* Copyright 2006-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Propchange: incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseQuery.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseQuery.cfh
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseQuery.cfh?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseQuery.cfh (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseQuery.cfh Thu Oct 14 08:48:04 2010
@@ -0,0 +1,100 @@
+parcel KinoSearch cnick Kino;
+
+/** Query matching an ordered list of terms.
+ *
+ * PhraseQuery is a subclass of L<KinoSearch::Search::Query> for matching
+ * against an ordered sequence of terms.
+ */
+
+class KinoSearch::Search::PhraseQuery inherits KinoSearch::Search::Query
+ : dumpable {
+
+ CharBuf *field;
+ VArray *terms;
+
+ inert incremented PhraseQuery*
+ new(const CharBuf *field, VArray *terms);
+
+ /**
+ * @param field The field that the phrase must occur in.
+ * @param terms The ordered array of terms that must match.
+ */
+ public inert PhraseQuery*
+ init(PhraseQuery *self, const CharBuf *field, VArray *terms);
+
+ /** Accessor for object's field attribute.
+ */
+ public CharBuf*
+ Get_Field(PhraseQuery *self);
+
+ /** Accessor for object's array of terms.
+ */
+ public VArray*
+ Get_Terms(PhraseQuery *self);
+
+ public incremented Compiler*
+ Make_Compiler(PhraseQuery *self, Searcher *searcher, float boost);
+
+ public bool_t
+ Equals(PhraseQuery *self, Obj *other);
+
+ public incremented CharBuf*
+ To_String(PhraseQuery *self);
+
+ public void
+ Serialize(PhraseQuery *self, OutStream *outstream);
+
+ public incremented PhraseQuery*
+ Deserialize(PhraseQuery *self, InStream *instream);
+
+ public void
+ Destroy(PhraseQuery *self);
+}
+
+class KinoSearch::Search::PhraseCompiler
+ inherits KinoSearch::Search::Compiler {
+
+ float idf;
+ float raw_weight;
+ float query_norm_factor;
+ float normalized_weight;
+
+ inert incremented PhraseCompiler*
+ new(PhraseQuery *parent, Searcher *searcher, float boost);
+
+ inert PhraseCompiler*
+ init(PhraseCompiler *self, PhraseQuery *parent, Searcher *searcher,
+ float boost);
+
+ public incremented nullable Matcher*
+ Make_Matcher(PhraseCompiler *self, SegReader *reader, bool_t need_score);
+
+ public float
+ Get_Weight(PhraseCompiler *self);
+
+ public float
+ Sum_Of_Squared_Weights(PhraseCompiler *self);
+
+ public void
+ Apply_Norm_Factor(PhraseCompiler *self, float factor);
+
+ public incremented VArray*
+ Highlight_Spans(PhraseCompiler *self, Searcher *searcher,
+ DocVector *doc_vec, const CharBuf *field);
+
+ public bool_t
+ Equals(PhraseCompiler *self, Obj *other);
+
+ public void
+ Serialize(PhraseCompiler *self, OutStream *outstream);
+
+ public incremented PhraseCompiler*
+ Deserialize(PhraseCompiler *self, InStream *instream);
+}
+
+/* Copyright 2006-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseScorer.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseScorer.c?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseScorer.c (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseScorer.c Thu Oct 14 08:48:04 2010
@@ -0,0 +1,307 @@
+#define C_KINO_PHRASESCORER
+#define C_KINO_POSTING
+#define C_KINO_SCOREPOSTING
+#include "KinoSearch/Util/ToolSet.h"
+
+#include "KinoSearch/Search/PhraseScorer.h"
+#include "KinoSearch/Index/Posting/ScorePosting.h"
+#include "KinoSearch/Index/PostingList.h"
+#include "KinoSearch/Index/Similarity.h"
+#include "KinoSearch/Search/Compiler.h"
+
+PhraseScorer*
+PhraseScorer_new(Similarity *sim, VArray *plists, Compiler *compiler)
+{
+ PhraseScorer *self = (PhraseScorer*)VTable_Make_Obj(PHRASESCORER);
+ return PhraseScorer_init(self, sim, plists, compiler);
+
+}
+
+PhraseScorer*
+PhraseScorer_init(PhraseScorer *self, Similarity *similarity, VArray *plists,
+ Compiler *compiler)
+{
+ Matcher_init((Matcher*)self);
+
+ // Init.
+ self->anchor_set = BB_new(0);
+ self->phrase_freq = 0.0;
+ self->phrase_boost = 0.0;
+ self->first_time = true;
+ self->more = true;
+
+ // Extract PostingLists out of VArray into local C array for quick access.
+ self->num_elements = VA_Get_Size(plists);
+ self->plists = (PostingList**)MALLOCATE(
+ self->num_elements * sizeof(PostingList*));
+ for (size_t i = 0; i < self->num_elements; i++) {
+ PostingList *const plist = (PostingList*)CERTIFY(
+ VA_Fetch(plists, i), POSTINGLIST);
+ if (plist == NULL)
+ THROW(ERR, "Missing element %u32", i);
+ self->plists[i] = (PostingList*)INCREF(plist);
+ }
+
+ // Assign.
+ self->sim = (Similarity*)INCREF(similarity);
+ self->compiler = (Compiler*)INCREF(compiler);
+ self->weight = Compiler_Get_Weight(compiler);
+
+ return self;
+}
+
+void
+PhraseScorer_destroy(PhraseScorer *self)
+{
+ if (self->plists) {
+ for (size_t i = 0; i < self->num_elements; i++) {
+ DECREF(self->plists[i]);
+ }
+ FREEMEM(self->plists);
+ }
+ DECREF(self->sim);
+ DECREF(self->anchor_set);
+ DECREF(self->compiler);
+ SUPER_DESTROY(self, PHRASESCORER);
+}
+
+int32_t
+PhraseScorer_next(PhraseScorer *self)
+{
+ if (self->first_time) {
+ return PhraseScorer_Advance(self, 1);
+ }
+ else if (self->more) {
+ const int32_t target = PList_Get_Doc_ID(self->plists[0]) + 1;
+ return PhraseScorer_Advance(self, target);
+ }
+ else {
+ return 0;
+ }
+}
+
+int32_t
+PhraseScorer_advance(PhraseScorer *self, int32_t target)
+{
+ PostingList **const plists = self->plists;
+ const uint32_t num_elements = self->num_elements;
+ int32_t highest = 0;
+
+ // Reset match variables to indicate no match. New values will be
+ // assigned if a match succeeds.
+ self->phrase_freq = 0.0;
+ self->doc_id = 0;
+
+ // Find the lowest possible matching doc ID greater than the current doc
+ // ID. If any one of the PostingLists is exhausted, we're done.
+ if (self->first_time) {
+ self->first_time = false;
+
+ // On the first call to Advance(), advance all PostingLists.
+ for (size_t i = 0, max = self->num_elements; i < max; i++) {
+ int32_t candidate = PList_Advance(plists[i], target);
+ if (!candidate) {
+ self->more = false;
+ return 0;
+ }
+ else if (candidate > highest) {
+ // Remember the highest doc ID so far.
+ highest = candidate;
+ }
+ }
+ }
+ else {
+ // On subsequent iters, advance only one PostingList. Its new doc ID
+ // becomes the minimum target which all the others must move up to.
+ highest = PList_Advance(plists[0], target);
+ if (highest == 0) {
+ self->more = false;
+ return 0;
+ }
+ }
+
+ // Find a doc which contains all the terms.
+ while (1) {
+ bool_t agreement = true;
+
+ // Scoot all posting lists up to at least the current minimum.
+ for (uint32_t i = 0; i < num_elements; i++) {
+ PostingList *const plist = plists[i];
+ int32_t candidate = PList_Get_Doc_ID(plist);
+
+ // Is this PostingList already beyond the minimum? Then raise the
+ // bar for everyone else.
+ if (highest < candidate) { highest = candidate; }
+ if (target < highest) { target = highest; }
+
+ // Scoot this posting list up.
+ if (candidate < target) {
+ candidate = PList_Advance(plist, target);
+
+ // If this PostingList is exhausted, we're done.
+ if (candidate == 0) {
+ self->more = false;
+ return 0;
+ }
+
+ // After calling PList_Advance(), we are guaranteed to be
+ // either at or beyond the minimum, so we can assign without
+ // checking and the minumum will either go up or stay the
+ // same.
+ highest = candidate;
+ }
+ }
+
+ // See whether all the PostingLists have managed to converge on a
+ // single doc ID.
+ for (uint32_t i = 0; i < num_elements; i++) {
+ const int32_t candidate = PList_Get_Doc_ID(plists[i]);
+ if (candidate != highest) { agreement = false; }
+ }
+
+ // If we've found a doc with all terms in it, see if they form a
+ // phrase.
+ if (agreement && highest >= target) {
+ self->phrase_freq = PhraseScorer_Calc_Phrase_Freq(self);
+ if (self->phrase_freq == 0.0) {
+ // No phrase. Move on to another doc.
+ target += 1;
+ }
+ else {
+ // Success!
+ self->doc_id = highest;
+ return highest;
+ }
+ }
+ }
+}
+
+static INLINE uint32_t
+SI_winnow_anchors(uint32_t *anchors_start, const uint32_t *const anchors_end,
+ const uint32_t *candidates, const uint32_t *const candidates_end,
+ uint32_t offset)
+{
+ uint32_t *anchors = anchors_start;
+ uint32_t *anchors_found = anchors_start;
+ uint32_t target_anchor;
+ uint32_t target_candidate;
+
+ // Safety check, so there's no chance of a bad dereference.
+ if (anchors_start == anchors_end || candidates == candidates_end) {
+ return 0;
+ }
+
+ /* This function is a loop that finds terms that can continue a phrase.
+ * It overwrites the anchors in place, and returns the number remaining.
+ * The basic algorithm is to alternately increment the candidates' pointer
+ * until it is at or beyond its target position, and then increment the
+ * anchors' pointer until it is at or beyond its target. The non-standard
+ * form is to avoid unnecessary comparisons. This loop has not been
+ * tested for speed, but glancing at the object code produced (objdump -S)
+ * it appears to be significantly faster than the nested loop alternative.
+ * But given the vagaries of modern processors, it merits actual
+ * testing.*/
+
+ SPIN_CANDIDATES:
+ target_candidate = *anchors + offset;
+ while (*candidates < target_candidate) {
+ if (++candidates == candidates_end) goto DONE;
+ }
+ if (*candidates == target_candidate) goto MATCH;
+ goto SPIN_ANCHORS;
+
+ SPIN_ANCHORS:
+ target_anchor = *candidates - offset;
+ while (*anchors < target_anchor) {
+ if (++anchors == anchors_end) goto DONE;
+ };
+ if (*anchors == target_anchor) goto MATCH;
+ goto SPIN_CANDIDATES;
+
+ MATCH:
+ *anchors_found++ = *anchors;
+ if (++anchors == anchors_end) goto DONE;
+ goto SPIN_CANDIDATES;
+
+ DONE:
+ // Return number of anchors remaining.
+ return anchors_found - anchors_start;
+}
+
+float
+PhraseScorer_calc_phrase_freq(PhraseScorer *self)
+{
+ PostingList **const plists = self->plists;
+
+ /* Create a overwriteable "anchor set" from the first posting.
+ *
+ * Each "anchor" is a position, measured in tokens, corresponding to a a
+ * term which might start a phrase. We start off with an "anchor set"
+ * comprised of all positions at which the first term in the phrase occurs
+ * in the field.
+ *
+ * There can never be more phrase matches than instances of this first
+ * term. There may be fewer however, which we will determine by seeing
+ * whether all the other terms line up at subsequent position slots.
+ *
+ * Every time we eliminate an anchor from the anchor set, we splice it out
+ * of the array. So if we begin with an anchor set of (15, 51, 72) and we
+ * discover that phrases occur at the first and last instances of the
+ * first term but not the middle one, the final array will be (15, 72).
+ *
+ * The number of elements in the anchor set when we are finished winnowing
+ * is our phrase freq.
+ */
+ ScorePosting *posting = (ScorePosting*)PList_Get_Posting(plists[0]);
+ uint32_t anchors_remaining = posting->freq;
+ if (!anchors_remaining) { return 0.0f; }
+
+ size_t amount = anchors_remaining * sizeof(uint32_t);
+ uint32_t *anchors_start = (uint32_t*)BB_Grow(self->anchor_set, amount);
+ uint32_t *anchors_end = anchors_start + anchors_remaining;
+ memcpy(anchors_start, posting->prox, amount);
+
+ // Match the positions of other terms against the anchor set.
+ for (uint32_t i = 1, max = self->num_elements; i < max; i++) {
+ // Get the array of positions for the next term. Unlike the anchor
+ // set (which is a copy), these won't be overwritten.
+ ScorePosting *posting = (ScorePosting*)PList_Get_Posting(plists[i]);
+ uint32_t *candidates_start = posting->prox;
+ uint32_t *candidates_end = candidates_start + posting->freq;
+
+ // Splice out anchors that don't match the next term. Bail out if
+ // we've eliminated all possible anchors.
+ anchors_remaining = SI_winnow_anchors(anchors_start, anchors_end,
+ candidates_start, candidates_end, i);
+ if (!anchors_remaining) { return 0.0f; }
+
+ // Adjust end for number of anchors that remain.
+ anchors_end = anchors_start + anchors_remaining;
+ }
+
+ // The number of anchors left is the phrase freq.
+ return (float)anchors_remaining;
+}
+
+int32_t
+PhraseScorer_get_doc_id(PhraseScorer *self)
+{
+ return self->doc_id;
+}
+
+float
+PhraseScorer_score(PhraseScorer *self)
+{
+ ScorePosting *posting = (ScorePosting*)PList_Get_Posting(self->plists[0]);
+ float score = Sim_TF(self->sim, self->phrase_freq)
+ * self->weight
+ * posting->weight;
+ return score;
+}
+
+/* Copyright 2006-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Propchange: incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseScorer.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseScorer.cfh
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseScorer.cfh?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseScorer.cfh (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/PhraseScorer.cfh Thu Oct 14 08:48:04 2010
@@ -0,0 +1,53 @@
+parcel KinoSearch cnick Kino;
+
+/** Matcher for a PhraseQuery.
+ */
+
+class KinoSearch::Search::PhraseScorer inherits KinoSearch::Search::Matcher {
+
+ int32_t doc_id;
+ uint32_t num_elements;
+ Similarity *sim;
+ PostingList **plists;
+ ByteBuf *anchor_set;
+ float phrase_freq;
+ float phrase_boost;
+ Compiler *compiler;
+ float weight;
+ bool_t first_time;
+ bool_t more;
+
+ inert incremented PhraseScorer*
+ new(Similarity *similarity, VArray *posting_lists, Compiler *compiler);
+
+ inert PhraseScorer*
+ init(PhraseScorer *self, Similarity *similarity, VArray *posting_lists,
+ Compiler *compiler);
+
+ public void
+ Destroy(PhraseScorer *self);
+
+ public int32_t
+ Next(PhraseScorer *self);
+
+ public int32_t
+ Advance(PhraseScorer *self, int32_t target);
+
+ public int32_t
+ Get_Doc_ID(PhraseScorer *self);
+
+ public float
+ Score(PhraseScorer *self);
+
+ /** Calculate how often the phrase occurs in the current document.
+ */
+ float
+ Calc_Phrase_Freq(PhraseScorer *self);
+}
+
+/* Copyright 2006-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/PolyMatcher.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/PolyMatcher.c?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/PolyMatcher.c (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/PolyMatcher.c Thu Oct 14 08:48:04 2010
@@ -0,0 +1,46 @@
+#define C_KINO_POLYMATCHER
+#include "KinoSearch/Util/ToolSet.h"
+
+#include "KinoSearch/Search/PolyMatcher.h"
+#include "KinoSearch/Index/Similarity.h"
+
+PolyMatcher*
+PolyMatcher_new(VArray *children, Similarity *sim)
+{
+ PolyMatcher *self = (PolyMatcher*)VTable_Make_Obj(POLYMATCHER);
+ return PolyMatcher_init(self, children, sim);
+}
+
+PolyMatcher*
+PolyMatcher_init(PolyMatcher *self, VArray *children, Similarity *similarity)
+{
+ uint32_t i;
+
+ Matcher_init((Matcher*)self);
+ self->num_kids = VA_Get_Size(children);
+ self->sim = (Similarity*)INCREF(similarity);
+ self->children = (VArray*)INCREF(children);
+ self->coord_factors = (float*)MALLOCATE((self->num_kids + 1) * sizeof(float));
+ for (i = 0; i <= self->num_kids; i++) {
+ self->coord_factors[i] = similarity
+ ? Sim_Coord(similarity, i, self->num_kids)
+ : 1.0f;
+ }
+ return self;
+}
+
+void
+PolyMatcher_destroy(PolyMatcher *self)
+{
+ DECREF(self->children);
+ DECREF(self->sim);
+ FREEMEM(self->coord_factors);
+ SUPER_DESTROY(self, POLYMATCHER);
+}
+
+/* Copyright 2008-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Propchange: incubator/lucy/trunk/import/core/KinoSearch/Search/PolyMatcher.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/PolyMatcher.cfh
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/PolyMatcher.cfh?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/PolyMatcher.cfh (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/PolyMatcher.cfh Thu Oct 14 08:48:04 2010
@@ -0,0 +1,29 @@
+parcel KinoSearch cnick Kino;
+
+/** Base class for composite scorers.
+ */
+
+class KinoSearch::Search::PolyMatcher inherits KinoSearch::Search::Matcher {
+
+ VArray *children;
+ Similarity *sim;
+ uint32_t num_kids;
+ uint32_t matching_kids;
+ float *coord_factors;
+
+ inert incremented PolyMatcher*
+ new(VArray *children, Similarity *similarity);
+
+ inert PolyMatcher*
+ init(PolyMatcher *self, VArray *children, Similarity *similarity);
+
+ public void
+ Destroy(PolyMatcher *self);
+}
+
+/* Copyright 2008-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/PolyQuery.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/PolyQuery.c?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/PolyQuery.c (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/PolyQuery.c Thu Oct 14 08:48:04 2010
@@ -0,0 +1,197 @@
+#define C_KINO_POLYQUERY
+#define C_KINO_POLYCOMPILER
+#include "KinoSearch/Util/ToolSet.h"
+
+#include "KinoSearch/Search/PolyQuery.h"
+#include "KinoSearch/Index/DocVector.h"
+#include "KinoSearch/Index/Similarity.h"
+#include "KinoSearch/Plan/Schema.h"
+#include "KinoSearch/Search/Searcher.h"
+#include "KinoSearch/Search/Span.h"
+#include "KinoSearch/Store/InStream.h"
+#include "KinoSearch/Store/OutStream.h"
+#include "KinoSearch/Util/Freezer.h"
+
+PolyQuery*
+PolyQuery_init(PolyQuery *self, VArray *children)
+{
+ uint32_t i;
+ const uint32_t num_kids = children ? VA_Get_Size(children) : 0;
+ Query_init((Query*)self, 1.0f);
+ self->children = VA_new(num_kids);
+ for (i = 0; i < num_kids; i++) {
+ PolyQuery_Add_Child(self, (Query*)VA_Fetch(children, i));
+ }
+ return self;
+}
+
+void
+PolyQuery_destroy(PolyQuery *self)
+{
+ DECREF(self->children);
+ SUPER_DESTROY(self, POLYQUERY);
+}
+
+void
+PolyQuery_add_child(PolyQuery *self, Query *query)
+{
+ CERTIFY(query, QUERY);
+ VA_Push(self->children, INCREF(query));
+}
+
+void
+PolyQuery_set_children(PolyQuery *self, VArray *children)
+{
+ DECREF(self->children);
+ self->children = (VArray*)INCREF(children);
+}
+
+VArray*
+PolyQuery_get_children(PolyQuery *self) { return self->children; }
+
+void
+PolyQuery_serialize(PolyQuery *self, OutStream *outstream)
+{
+ const uint32_t num_kids = VA_Get_Size(self->children);
+ uint32_t i;
+ OutStream_Write_F32(outstream, self->boost);
+ OutStream_Write_U32(outstream, num_kids);
+ for (i = 0; i < num_kids; i++) {
+ Query *child = (Query*)VA_Fetch(self->children, i);
+ FREEZE(child, outstream);
+ }
+}
+
+PolyQuery*
+PolyQuery_deserialize(PolyQuery *self, InStream *instream)
+{
+ float boost = InStream_Read_F32(instream);
+ uint32_t num_children = InStream_Read_U32(instream);
+
+ if (!self) THROW(ERR, "Abstract class");
+ PolyQuery_init(self, NULL);
+ PolyQuery_Set_Boost(self, boost);
+
+ VA_Grow(self->children, num_children);
+ while (num_children--) {
+ VA_Push(self->children, THAW(instream));
+ }
+
+ return self;
+}
+
+bool_t
+PolyQuery_equals(PolyQuery *self, Obj *other)
+{
+ PolyQuery *evil_twin = (PolyQuery*)other;
+ if (evil_twin == self) return true;
+ if (!Obj_Is_A(other, POLYQUERY)) return false;
+ if (self->boost != evil_twin->boost) return false;
+ if (!VA_Equals(evil_twin->children, (Obj*)self->children)) return false;
+ return true;
+}
+
+/**********************************************************************/
+
+
+PolyCompiler*
+PolyCompiler_init(PolyCompiler *self, PolyQuery *parent,
+ Searcher *searcher, float boost)
+{
+ uint32_t i;
+ const uint32_t num_kids = VA_Get_Size(parent->children);
+
+ Compiler_init((Compiler*)self, (Query*)parent, searcher, NULL, boost);
+ self->children = VA_new(num_kids);
+
+ // Iterate over the children, creating a Compiler for each one.
+ for (i = 0; i < num_kids; i++) {
+ Query *child_query = (Query*)VA_Fetch(parent->children, i);
+ float sub_boost = boost * Query_Get_Boost(child_query);
+ VA_Push(self->children,
+ (Obj*)Query_Make_Compiler(child_query, searcher, sub_boost));
+ }
+
+ return self;
+}
+
+void
+PolyCompiler_destroy(PolyCompiler *self)
+{
+ DECREF(self->children);
+ SUPER_DESTROY(self, POLYCOMPILER);
+}
+
+float
+PolyCompiler_sum_of_squared_weights(PolyCompiler *self)
+{
+ float sum = 0;
+ uint32_t i, max;
+ float my_boost = PolyCompiler_Get_Boost(self);
+
+ for (i = 0, max = VA_Get_Size(self->children); i < max; i++) {
+ Compiler *child = (Compiler*)VA_Fetch(self->children, i);
+ sum += Compiler_Sum_Of_Squared_Weights(child);
+ }
+
+ // Compound the weight of each child.
+ sum *= my_boost * my_boost;
+
+ return sum;
+}
+
+void
+PolyCompiler_apply_norm_factor(PolyCompiler *self, float factor)
+{
+ uint32_t i, max;
+ for (i = 0, max = VA_Get_Size(self->children); i < max; i++) {
+ Compiler *child = (Compiler*)VA_Fetch(self->children, i);
+ Compiler_Apply_Norm_Factor(child, factor);
+ }
+}
+
+VArray*
+PolyCompiler_highlight_spans(PolyCompiler *self, Searcher *searcher,
+ DocVector *doc_vec, const CharBuf *field)
+{
+ VArray *spans = VA_new(0);
+ uint32_t i, max;
+ for (i = 0, max = VA_Get_Size(self->children); i < max; i++) {
+ Compiler *child = (Compiler*)VA_Fetch(self->children, i);
+ VArray *child_spans = Compiler_Highlight_Spans(child, searcher,
+ doc_vec, field);
+ if (child_spans) {
+ VA_Push_VArray(spans, child_spans);
+ VA_Dec_RefCount(child_spans);
+ }
+ }
+ return spans;
+}
+
+void
+PolyCompiler_serialize(PolyCompiler *self, OutStream *outstream)
+{
+ CB_Serialize(PolyCompiler_Get_Class_Name(self), outstream);
+ VA_Serialize(self->children, outstream);
+ Compiler_serialize((Compiler*)self, outstream);
+}
+
+PolyCompiler*
+PolyCompiler_deserialize(PolyCompiler *self, InStream *instream)
+{
+ CharBuf *class_name = CB_deserialize(NULL, instream);
+ if (!self) {
+ VTable *vtable = VTable_singleton(class_name, NULL);
+ self = (PolyCompiler*)VTable_Make_Obj(vtable);
+ }
+ DECREF(class_name);
+ self->children = VA_deserialize(NULL, instream);
+ return (PolyCompiler*)Compiler_deserialize((Compiler*)self, instream);
+}
+
+/* Copyright 2006-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Propchange: incubator/lucy/trunk/import/core/KinoSearch/Search/PolyQuery.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/PolyQuery.cfh
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/PolyQuery.cfh?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/PolyQuery.cfh (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/PolyQuery.cfh Thu Oct 14 08:48:04 2010
@@ -0,0 +1,83 @@
+parcel KinoSearch cnick Kino;
+
+/** Base class for composite Query objects.
+ *
+ * PolyQuery serves as a shared base class for ANDQuery, ORQuery, NOTQuery,
+ * and RequiredOptionalQuery. All of these classes may serve as nodes in
+ * composite Query with a tree structure which may be walked.
+ */
+abstract class KinoSearch::Search::PolyQuery
+ inherits KinoSearch::Search::Query : dumpable {
+
+ VArray *children;
+
+ /**
+ * @param children An array of child Queries.
+ */
+ public inert PolyQuery*
+ init(PolyQuery *self, VArray *children = NULL);
+
+ /** Add a child Query node.
+ */
+ public void
+ Add_Child(PolyQuery *self, Query *query);
+
+ void
+ Set_Children(PolyQuery *self, VArray *children);
+
+ VArray*
+ Get_Children(PolyQuery *self);
+
+ public void
+ Serialize(PolyQuery *self, OutStream *outstream);
+
+ public incremented PolyQuery*
+ Deserialize(PolyQuery *self, InStream *instream);
+
+ public bool_t
+ Equals(PolyQuery *self, Obj *other);
+
+ public void
+ Destroy(PolyQuery *self);
+}
+
+class KinoSearch::Search::PolyCompiler inherits KinoSearch::Search::Compiler {
+
+ VArray *children;
+
+ inert incremented PolyCompiler*
+ new(PolyQuery *parent, Searcher *searcher, float boost);
+
+ /** Initialize the Compiler, creating a Compiler child for each child
+ * Query. Normalization is left to the subclass.
+ */
+ inert PolyCompiler*
+ init(PolyCompiler *self, PolyQuery *parent, Searcher *searcher,
+ float boost);
+
+ public float
+ Sum_Of_Squared_Weights(PolyCompiler *self);
+
+ public void
+ Apply_Norm_Factor(PolyCompiler *self, float factor);
+
+ public incremented VArray*
+ Highlight_Spans(PolyCompiler *self, Searcher *searcher,
+ DocVector *doc_vec, const CharBuf *field);
+
+ public void
+ Destroy(PolyCompiler *self);
+
+ public void
+ Serialize(PolyCompiler *self, OutStream *outstream);
+
+ public incremented PolyCompiler*
+ Deserialize(PolyCompiler *self, InStream *instream);
+}
+
+/* Copyright 2006-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/PolySearcher.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/PolySearcher.c?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/PolySearcher.c (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/PolySearcher.c Thu Oct 14 08:48:04 2010
@@ -0,0 +1,186 @@
+#define C_KINO_POLYSEARCHER
+#include "KinoSearch/Util/ToolSet.h"
+
+#include "KinoSearch/Search/PolySearcher.h"
+
+#include "KinoSearch/Document/HitDoc.h"
+#include "KinoSearch/Index/DocVector.h"
+#include "KinoSearch/Index/PolyReader.h"
+#include "KinoSearch/Plan/Schema.h"
+#include "KinoSearch/Search/Collector.h"
+#include "KinoSearch/Search/HitQueue.h"
+#include "KinoSearch/Search/Query.h"
+#include "KinoSearch/Search/MatchDoc.h"
+#include "KinoSearch/Search/Matcher.h"
+#include "KinoSearch/Search/Searcher.h"
+#include "KinoSearch/Search/SortSpec.h"
+#include "KinoSearch/Search/TopDocs.h"
+#include "KinoSearch/Search/Compiler.h"
+
+PolySearcher*
+PolySearcher_init(PolySearcher *self, Schema *schema, VArray *searchers)
+{
+ const uint32_t num_searchers = VA_Get_Size(searchers);
+ uint32_t i;
+ int32_t *starts_array = (int32_t*)MALLOCATE(num_searchers * sizeof(int32_t));
+ int32_t doc_max = 0;
+
+ Searcher_init((Searcher*)self, schema);
+ self->searchers = (VArray*)INCREF(searchers);
+ self->starts = NULL; // Safe cleanup.
+
+ for (i = 0; i < num_searchers; i++) {
+ Searcher *searcher
+ = (Searcher*)CERTIFY(VA_Fetch(searchers, i), SEARCHER);
+ Schema *candidate = Searcher_Get_Schema(searcher);
+ VTable *orig_vt = Schema_Get_VTable(schema);
+ VTable *candidate_vt = Schema_Get_VTable(candidate);
+
+ // Confirm that searchers all use the same schema.
+ if (orig_vt != candidate_vt) {
+ THROW(ERR, "Conflicting schemas: '%o', '%o'",
+ Schema_Get_Class_Name(schema),
+ Schema_Get_Class_Name(candidate));
+ }
+
+ // Derive doc_max and relative start offsets.
+ starts_array[i] = (int32_t)doc_max;
+ doc_max += Searcher_Doc_Max(searcher);
+ }
+
+ self->doc_max = doc_max;
+ self->starts = I32Arr_new_steal(starts_array, num_searchers);
+
+ return self;
+}
+
+void
+PolySearcher_destroy(PolySearcher *self)
+{
+ DECREF(self->searchers);
+ DECREF(self->starts);
+ SUPER_DESTROY(self, POLYSEARCHER);
+}
+
+Obj*
+PolySearcher_fetch_doc(PolySearcher *self, int32_t doc_id, float score,
+ int32_t offset)
+{
+ uint32_t tick = PolyReader_sub_tick(self->starts, doc_id);
+ Searcher *searcher = (Searcher*)VA_Fetch(self->searchers, tick);
+ int32_t start = I32Arr_Get(self->starts, tick);
+ if (!searcher) { THROW(ERR, "Invalid doc id: %i32", doc_id); }
+ return Searcher_Fetch_Doc(searcher, doc_id - start, score,
+ offset + start);
+}
+
+DocVector*
+PolySearcher_fetch_doc_vec(PolySearcher *self, int32_t doc_id)
+{
+ uint32_t tick = PolyReader_sub_tick(self->starts, doc_id);
+ Searcher *searcher = (Searcher*)VA_Fetch(self->searchers, tick);
+ int32_t start = I32Arr_Get(self->starts, tick);
+ if (!searcher) { THROW(ERR, "Invalid doc id: %i32", doc_id); }
+ return Searcher_Fetch_Doc_Vec(searcher, doc_id - start);
+}
+
+int32_t
+PolySearcher_doc_max(PolySearcher *self)
+{
+ return self->doc_max;
+}
+
+uint32_t
+PolySearcher_doc_freq(PolySearcher *self, const CharBuf *field, Obj *term)
+{
+ uint32_t i, max;
+ uint32_t doc_freq = 0;
+ for (i = 0, max = VA_Get_Size(self->searchers); i < max; i++) {
+ Searcher *searcher = (Searcher*)VA_Fetch(self->searchers, i);
+ doc_freq += Searcher_Doc_Freq(searcher, field, term);
+ }
+ return doc_freq;
+}
+
+static void
+S_modify_doc_ids(VArray *match_docs, int32_t base)
+{
+ uint32_t i, max;
+ for (i = 0, max = VA_Get_Size(match_docs); i < max; i++) {
+ MatchDoc *match_doc = (MatchDoc*)VA_Fetch(match_docs, i);
+ int32_t new_doc_id = MatchDoc_Get_Doc_ID(match_doc) + base;
+ MatchDoc_Set_Doc_ID(match_doc, new_doc_id);
+ }
+}
+
+TopDocs*
+PolySearcher_top_docs(PolySearcher *self, Query *query, uint32_t num_wanted,
+ SortSpec *sort_spec)
+{
+ Schema *schema = PolySearcher_Get_Schema(self);
+ VArray *searchers = self->searchers;
+ I32Array *starts = self->starts;
+ HitQueue *hit_q = sort_spec
+ ? HitQ_new(schema, sort_spec, num_wanted)
+ : HitQ_new(NULL, NULL, num_wanted);
+ uint32_t total_hits = 0;
+ Compiler *compiler = Query_Is_A(query, COMPILER)
+ ? ((Compiler*)INCREF(query))
+ : Query_Make_Compiler(query, (Searcher*)self,
+ Query_Get_Boost(query));
+ uint32_t i, max;
+
+ for (i = 0, max = VA_Get_Size(searchers); i < max; i++) {
+ Searcher *searcher = (Searcher*)VA_Fetch(searchers, i);
+ int32_t base = I32Arr_Get(starts, i);
+ TopDocs *top_docs = Searcher_Top_Docs(searcher,
+ (Query*)compiler, num_wanted, sort_spec);
+ VArray *sub_match_docs = TopDocs_Get_Match_Docs(top_docs);
+ uint32_t j, jmax;
+
+ total_hits += TopDocs_Get_Total_Hits(top_docs);
+
+ S_modify_doc_ids(sub_match_docs, base);
+ for (j = 0, jmax = VA_Get_Size(sub_match_docs); j < jmax; j++) {
+ MatchDoc *match_doc = (MatchDoc*)VA_Fetch(sub_match_docs, j);
+ if (!HitQ_Insert(hit_q, INCREF(match_doc))) { break; }
+ }
+
+ DECREF(top_docs);
+ }
+
+ {
+ VArray *match_docs = HitQ_Pop_All(hit_q);
+ TopDocs *retval = TopDocs_new(match_docs, total_hits);
+
+ DECREF(match_docs);
+ DECREF(compiler);
+ DECREF(hit_q);
+ return retval;
+ }
+}
+
+
+void
+PolySearcher_collect(PolySearcher *self, Query *query,
+ Collector *collector)
+{
+ uint32_t i, max;
+ VArray *const searchers = self->searchers;
+ I32Array *starts = self->starts;
+
+ for (i = 0, max = VA_Get_Size(searchers); i < max; i++) {
+ int32_t start = I32Arr_Get(starts, i);
+ Searcher *searcher = (Searcher*)VA_Fetch(searchers, i);
+ OffsetCollector *offset_coll = OffsetColl_new(collector, start);
+ Searcher_Collect(searcher, query, (Collector*)offset_coll);
+ DECREF(offset_coll);
+ }
+}
+
+/* Copyright 2006-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Propchange: incubator/lucy/trunk/import/core/KinoSearch/Search/PolySearcher.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/PolySearcher.cfh
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/PolySearcher.cfh?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/PolySearcher.cfh (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/PolySearcher.cfh Thu Oct 14 08:48:04 2010
@@ -0,0 +1,57 @@
+parcel KinoSearch cnick Kino;
+
+/** Aggregate results from multiple searchers.
+ *
+ * The primary use for PolySearcher is to aggregate results from several
+ * remote searchers via L<KSx::Remote::SearchClient>, diffusing the cost of
+ * searching a large corpus over multiple machines. It is also possible to
+ * aggregate results from multiple Searchers on a single machine.
+ */
+
+class KinoSearch::Search::PolySearcher
+ inherits KinoSearch::Search::Searcher {
+
+ VArray *searchers;
+ I32Array *starts;
+ int32_t doc_max;
+
+ inert incremented PolySearcher*
+ new(Schema *schema, VArray *searchers);
+
+ /**
+ * @param schema A Schema.
+ * @param searchers An array of Searchers.
+ */
+ public inert PolySearcher*
+ init(PolySearcher *self, Schema *schema, VArray *searchers);
+
+ public void
+ Destroy(PolySearcher *self);
+
+ public int32_t
+ Doc_Max(PolySearcher *self);
+
+ public uint32_t
+ Doc_Freq(PolySearcher *self, const CharBuf *field, Obj *term);
+
+ public void
+ Collect(PolySearcher *self, Query *query, Collector *collector);
+
+ incremented TopDocs*
+ Top_Docs(PolySearcher *self, Query *query, uint32_t num_wanted,
+ SortSpec *sort_spec = NULL);
+
+ public incremented Obj*
+ Fetch_Doc(PolySearcher *self, int32_t doc_id, float score = 0.0,
+ int32_t offset = 0);
+
+ incremented DocVector*
+ Fetch_Doc_Vec(PolySearcher *self, int32_t doc_id);
+}
+
+/* Copyright 2006-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Added: incubator/lucy/trunk/import/core/KinoSearch/Search/Query.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/import/core/KinoSearch/Search/Query.c?rev=1022422&view=auto
==============================================================================
--- incubator/lucy/trunk/import/core/KinoSearch/Search/Query.c (added)
+++ incubator/lucy/trunk/import/core/KinoSearch/Search/Query.c Thu Oct 14 08:48:04 2010
@@ -0,0 +1,43 @@
+#define C_KINO_QUERY
+#include "KinoSearch/Util/ToolSet.h"
+
+#include "KinoSearch/Search/Query.h"
+#include "KinoSearch/Search/Compiler.h"
+#include "KinoSearch/Search/Searcher.h"
+#include "KinoSearch/Store/InStream.h"
+#include "KinoSearch/Store/OutStream.h"
+
+Query*
+Query_init(Query *self, float boost)
+{
+ self->boost = boost;
+ ABSTRACT_CLASS_CHECK(self, QUERY);
+ return self;
+}
+
+void
+Query_set_boost(Query *self, float boost) { self->boost = boost; }
+float
+Query_get_boost(Query *self) { return self->boost; }
+
+void
+Query_serialize(Query *self, OutStream *outstream)
+{
+ OutStream_Write_F32(outstream, self->boost);
+}
+
+Query*
+Query_deserialize(Query *self, InStream *instream)
+{
+ float boost = InStream_Read_F32(instream);
+ self = self ? self : (Query*)VTable_Make_Obj(QUERY);
+ Query_init(self, boost);
+ return self;
+}
+
+/* Copyright 2006-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+
Propchange: incubator/lucy/trunk/import/core/KinoSearch/Search/Query.c
------------------------------------------------------------------------------
svn:eol-style = native