Branch data Line data Source code
1 : : /* msetcmp.cc - MSetItem comparison functions and functors.
2 : : *
3 : : * Copyright (C) 2006,2009 Olly Betts
4 : : *
5 : : * This program is free software; you can redistribute it and/or
6 : : * modify it under the terms of the GNU General Public License as
7 : : * published by the Free Software Foundation; either version 2 of the
8 : : * License, or (at your option) any later version.
9 : : *
10 : : * This program is distributed in the hope that it will be useful,
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : : * GNU General Public License for more details.
14 : : *
15 : : * You should have received a copy of the GNU General Public License
16 : : * along with this program; if not, write to the Free Software
17 : : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
18 : : * USA
19 : : */
20 : :
21 : : #include <config.h>
22 : : #include "msetcmp.h"
23 : :
24 : : /* We use templates to generate the 14 different comparison functions
25 : : * which we need. This avoids having to write them all out by hand.
26 : : */
27 : :
28 : : // Order by did. Helper comparison template function, which is used as the
29 : : // last fallback by the others.
30 : : template<bool FORWARD_DID, bool CHECK_DID_ZERO> inline bool
31 : 21209710 : msetcmp_by_did(const Xapian::Internal::MSetItem &a,
32 : : const Xapian::Internal::MSetItem &b)
33 : : {
34 : : if (FORWARD_DID) {
35 : : if (CHECK_DID_ZERO) {
36 : : // We want dummy did 0 to compare worse than any other.
37 [ - + ]: 21201601 : if (a.did == 0) return false;
38 [ + + ]: 21201601 : if (b.did == 0) return true;
39 : : }
40 : 21204513 : return (a.did < b.did);
41 : : } else {
42 : 5197 : return (a.did > b.did);
43 : : }
44 : : }
45 : :
46 : : // Order by relevance, then docid.
47 : : template<bool FORWARD_DID> bool
48 : 426757918 : msetcmp_by_relevance(const Xapian::Internal::MSetItem &a,
49 : : const Xapian::Internal::MSetItem &b)
50 : : {
51 [ + + ][ + + ]: 426757918 : if (a.wt > b.wt) return true;
52 [ + + ][ + + ]: 216428057 : if (a.wt < b.wt) return false;
53 : 426757918 : return msetcmp_by_did<FORWARD_DID, true>(a, b);
54 : : }
55 : :
56 : : // Order by value, then docid.
57 : : template<bool FORWARD_VALUE, bool FORWARD_DID> bool
58 : 140678 : msetcmp_by_value(const Xapian::Internal::MSetItem &a,
59 : : const Xapian::Internal::MSetItem &b)
60 : : {
61 : : if (!FORWARD_VALUE) {
62 : : // We want dummy did 0 to compare worse than any other.
63 [ - + ][ - + ]: 60590 : if (a.did == 0) return false;
64 [ + + ][ + + ]: 60590 : if (b.did == 0) return true;
65 : : }
66 [ + + ][ + + ]: 134608 : if (a.sort_key > b.sort_key) return FORWARD_VALUE;
[ + + ][ + + ]
67 [ + + ][ + + ]: 66890 : if (a.sort_key < b.sort_key) return !FORWARD_VALUE;
[ + + ][ + + ]
68 : 140678 : return msetcmp_by_did<FORWARD_DID, FORWARD_VALUE>(a, b);
69 : : }
70 : :
71 : : // Order by value, then relevance, then docid.
72 : : template<bool FORWARD_VALUE, bool FORWARD_DID> bool
73 : 107380 : msetcmp_by_value_then_relevance(const Xapian::Internal::MSetItem &a,
74 : : const Xapian::Internal::MSetItem &b)
75 : : {
76 : : if (!FORWARD_VALUE) {
77 : : // two special cases to make min_item compares work when did == 0
78 [ - + ][ - + ]: 54406 : if (a.did == 0) return false;
79 [ + + ][ + + ]: 54406 : if (b.did == 0) return true;
80 : : }
81 [ + + ][ + + ]: 102388 : if (a.sort_key > b.sort_key) return FORWARD_VALUE;
[ + + ][ + + ]
82 [ + + ][ + + ]: 49709 : if (a.sort_key < b.sort_key) return !FORWARD_VALUE;
[ + + ][ + + ]
83 [ + + ][ + + ]: 1766 : if (a.wt > b.wt) return true;
[ + + ][ + + ]
84 [ + + ][ + + ]: 1278 : if (a.wt < b.wt) return false;
[ + + ][ + + ]
85 : 107380 : return msetcmp_by_did<FORWARD_DID, FORWARD_VALUE>(a, b);
86 : : }
87 : :
88 : : // Order by relevance, then value, then docid.
89 : : template<bool FORWARD_VALUE, bool FORWARD_DID> bool
90 : 103358 : msetcmp_by_relevance_then_value(const Xapian::Internal::MSetItem &a,
91 : : const Xapian::Internal::MSetItem &b)
92 : : {
93 : : if (!FORWARD_VALUE) {
94 : : // two special cases to make min_item compares work when did == 0
95 [ - + ][ - + ]: 51368 : if (a.did == 0) return false;
96 [ + + ][ + + ]: 51368 : if (b.did == 0) return true;
97 : : }
98 [ + + ][ + + ]: 98338 : if (a.wt > b.wt) return true;
[ + + ][ + + ]
99 [ + + ][ + + ]: 46499 : if (a.wt < b.wt) return false;
[ + + ][ + + ]
100 [ + + ][ + + ]: 4336 : if (a.sort_key > b.sort_key) return FORWARD_VALUE;
[ + + ][ + + ]
101 [ + + ][ + + ]: 2911 : if (a.sort_key < b.sort_key) return !FORWARD_VALUE;
[ + + ][ + + ]
102 : 103358 : return msetcmp_by_did<FORWARD_DID, FORWARD_VALUE>(a, b);
103 : : }
104 : :
105 : : static mset_cmp mset_cmp_table[] = {
106 : : // Xapian::Enquire::Internal::REL
107 : : msetcmp_by_relevance<false>,
108 : : 0,
109 : : msetcmp_by_relevance<true>,
110 : : 0,
111 : : // Xapian::Enquire::Internal::VAL
112 : : msetcmp_by_value<false, false>,
113 : : msetcmp_by_value<true, false>,
114 : : msetcmp_by_value<false, true>,
115 : : msetcmp_by_value<true, true>,
116 : : // Xapian::Enquire::Internal::VAL_REL
117 : : msetcmp_by_value_then_relevance<false, false>,
118 : : msetcmp_by_value_then_relevance<true, false>,
119 : : msetcmp_by_value_then_relevance<false, true>,
120 : : msetcmp_by_value_then_relevance<true, true>,
121 : : // Xapian::Enquire::Internal::REL_VAL
122 : : msetcmp_by_relevance_then_value<true, true>,
123 : : msetcmp_by_relevance_then_value<false, true>,
124 : : msetcmp_by_relevance_then_value<true, false>,
125 : : msetcmp_by_relevance_then_value<false, false>
126 : : };
127 : :
128 : 173480 : mset_cmp get_msetcmp_function(Xapian::Enquire::Internal::sort_setting sort_by, bool sort_forward, bool sort_value_forward) {
129 [ + + ]: 173480 : if (sort_by == Xapian::Enquire::Internal::REL) sort_value_forward = false;
130 : 173480 : return mset_cmp_table[sort_by * 4 + sort_forward * 2 + sort_value_forward];
131 : : }
|