diff -puNr xapian-core-1.0.8/api/sorter.cc xapian-core-1.0.8-sorter/api/sorter.cc --- xapian-core-1.0.8/api/sorter.cc 2008-09-04 07:52:21.000000000 +0200 +++ xapian-core-1.0.8-sorter/api/sorter.cc 2008-09-16 14:52:58.000000000 +0200 @@ -32,7 +32,7 @@ namespace Xapian { Sorter::~Sorter() { } string -MultiValueSorter::operator()(const Xapian::Document & doc) const +MultiValueSorter::operator()(const Xapian::Document & doc, const Xapian::weight) const { string result; @@ -82,4 +82,49 @@ MultiValueSorter::operator()(const Xapia MultiValueSorter::~MultiValueSorter() { } +string +RoundedWeightSorter::operator()(const Xapian::Document & doc, const Xapian::weight wt) const +{ + string result = ""; + + // Round the weight, using the given factor, to the nearest int + int intwt = (int)((wt * factor) + 0.5); + char buffer[4]; + + // Convert it into four bytes and use those as the primary part of the sort-value + buffer[0] = (intwt >> 24) % 256; + buffer[1] = (intwt >> 16) % 256; + buffer[2] = (intwt >> 8) % 256; + buffer[3] = intwt % 256; + + result += buffer[0]; + result += buffer[1]; + result += buffer[2]; + result += buffer[3]; + + // The value needs to be adjusted if it isn't sorted forward. + string v = doc.get_value(valno); + + if (!forward) { + // For a reverse ordered value, we subtract each byte from '\xff', + // except for '\0' which we convert to "\xff\0". We insert + // "\xff\xff" after the encoded value. + for (string::const_iterator j = v.begin(); j != v.end(); ++j) { + unsigned char ch(*j); + result += char(255 - ch); + if (ch == 0) result += '\0'; + } + result.append("\xff\xff", 2); + } else { + result += v; + } + return result; } + +RoundedWeightSorter::~RoundedWeightSorter() { } + +} + + + + diff -puNr xapian-core-1.0.8/include/xapian/sorter.h xapian-core-1.0.8-sorter/include/xapian/sorter.h --- xapian-core-1.0.8/include/xapian/sorter.h 2008-09-04 07:52:19.000000000 +0200 +++ xapian-core-1.0.8-sorter/include/xapian/sorter.h 2008-09-16 14:47:41.000000000 +0200 @@ -36,7 +36,7 @@ class XAPIAN_VISIBILITY_DEFAULT Sorter { * * Documents are then ordered by a string compare on the sort keys. */ - virtual std::string operator()(const Xapian::Document & doc) const = 0; + virtual std::string operator()(const Xapian::Document & doc, const Xapian::weight wt) const = 0; /** Virtual destructor, because we have virtual methods. */ virtual ~Sorter(); @@ -59,7 +59,7 @@ class XAPIAN_VISIBILITY_DEFAULT MultiVal while (begin != end) add(*begin++); } - virtual std::string operator()(const Xapian::Document & doc) const; + virtual std::string operator()(const Xapian::Document & doci, const Xapian::weight wt) const; void add(Xapian::valueno valno, bool forward = true) { valnos.push_back(std::make_pair(valno, forward)); @@ -68,6 +68,29 @@ class XAPIAN_VISIBILITY_DEFAULT MultiVal virtual ~MultiValueSorter(); }; +/** Sorter subclass which multiplies the weight with a specified factor and then sorts by value. + * + * This sorter basically returns a rounded version of the weight, by multiplying it with the specified factor. + * The result of this multiplication is cast to int, and used as the primary part of the sorting value. + * One has to specify a value number which is then retrieved and appended to the weight, similar to + * the way the last value is appended in the MultiValueSorter. + */ +class XAPIAN_VISIBILITY_DEFAULT RoundedWeightSorter : public Sorter { + int factor; + Xapian::valueno valno; + bool forward; + + public: + RoundedWeightSorter() { } + + RoundedWeightSorter(int factor_, Xapian::valueno valno_, bool forward_) : factor(factor_), valno(valno_), forward(forward_) { } + + virtual std::string operator()(const Xapian::Document & doci, const Xapian::weight wt) const; + + virtual ~RoundedWeightSorter(); +}; + } + #endif // XAPIAN_INCLUDED_SORTER_H diff -puNr xapian-core-1.0.8/matcher/multimatch.cc xapian-core-1.0.8-sorter/matcher/multimatch.cc --- xapian-core-1.0.8/matcher/multimatch.cc 2008-09-04 07:52:16.000000000 +0200 +++ xapian-core-1.0.8-sorter/matcher/multimatch.cc 2008-09-16 12:11:18.000000000 +0200 @@ -512,7 +512,7 @@ MultiMatch::get_mset(Xapian::doccount fi // below if we haven't already rejected this candidate. Xapian::weight wt = 0.0; bool calculated_weight = false; - if (sort_by != VAL || min_weight > 0.0) { + if (sort_by != VAL || min_weight > 0.0 || sorter) { wt = pl->get_weight(); if (wt < min_weight) { DEBUGLINE(MATCH, "Rejecting potential match due to insufficient weight"); @@ -531,7 +531,7 @@ MultiMatch::get_mset(Xapian::doccount fi Xapian::docid m = (new_item.did - 1) / multiplier + 1; // real docid in that database Xapian::Internal::RefCntPtr doc(db.internal[n]->open_document(m, true)); if (sorter) { - new_item.sort_key = (*sorter)(Xapian::Document(doc.get())); + new_item.sort_key = (*sorter)(Xapian::Document(doc.get()), wt); } else { new_item.sort_key = doc->get_value(sort_key); }