C++ compilation.
[idzebra-moved-to-github.git] / index / rank1.c
1 /*
2  * Copyright (C) 1998-1999, Index Data
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: rank1.c,v $
7  * Revision 1.5  1999-05-26 07:49:13  adam
8  * C++ compilation.
9  *
10  * Revision 1.4  1999/02/02 14:51:01  adam
11  * Updated WIN32 code specific sections. Changed header.
12  *
13  * Revision 1.3  1998/06/12 12:21:53  adam
14  * Fixed memory-leak.
15  *
16  * Revision 1.2  1998/03/05 13:03:29  adam
17  * Improved ranking.
18  *
19  * Revision 1.1  1998/03/05 08:45:12  adam
20  * New result set model and modular ranking system. Moved towards
21  * descent server API. System information stored as "SGML" records.
22  *
23  */
24
25 #include <stdio.h>
26 #include <assert.h>
27 #ifdef WIN32
28 #include <io.h>
29 #else
30 #include <unistd.h>
31 #endif
32
33 #include "zserver.h"
34
35 struct rank_class_info {
36     int dummy;
37 };
38
39 struct rank_term_info {
40     int local_occur;
41     int global_occur;
42     int global_inv;
43     int rank_flag;
44 };
45
46 struct rank_set_info {
47     int last_pos;
48     int no_entries;
49     int no_rank_entries;
50     struct rank_term_info *entries;
51 };
52
53 static int log2_int (unsigned g)
54 {
55     int n = 0;
56     while ((g = g>>1))
57         n++;
58     return n;
59 }
60
61 /*
62  * create: Creates/Initialises this rank handler. This routine is 
63  *  called exactly once. The routine returns the class_handle.
64  */
65 static void *create (ZebraHandle zh)
66 {
67     struct rank_class_info *ci = (struct rank_class_info *)
68         xmalloc (sizeof(*ci));
69
70     logf (LOG_DEBUG, "rank-1 create");
71     return ci;
72 }
73
74 /*
75  * destroy: Destroys this rank handler. This routine is called
76  *  when the handler is no longer needed - i.e. when the server
77  *  dies. The class_handle was previously returned by create.
78  */
79 static void destroy (ZebraHandle zh, void *class_handle)
80 {
81     struct rank_class_info *ci = (struct rank_class_info *) class_handle;
82
83     logf (LOG_DEBUG, "rank-1 destroy");
84     xfree (ci);
85 }
86
87
88 /*
89  * begin: Prepares beginning of "real" ranking. Called once for
90  *  each result set. The returned handle is a "set handle" and
91  *  will be used in each of the handlers below.
92  */
93 static void *begin (ZebraHandle zh, void *class_handle, RSET rset)
94 {
95     struct rank_set_info *si = (struct rank_set_info *) xmalloc (sizeof(*si));
96     int i;
97
98     logf (LOG_DEBUG, "rank-1 begin");
99     si->no_entries = rset->no_rset_terms;
100     si->no_rank_entries = 0;
101     si->entries = (struct rank_term_info *)
102         xmalloc (sizeof(*si->entries)*si->no_entries);
103     for (i = 0; i < si->no_entries; i++)
104     {
105         int g = rset->rset_terms[i]->nn;
106         if (!strcmp (rset->rset_terms[i]->flags, "rank"))
107         {
108             si->entries[i].rank_flag = 1;
109             (si->no_rank_entries)++;
110         }
111         else
112             si->entries[i].rank_flag = 0;
113         si->entries[i].local_occur = 0;
114         si->entries[i].global_occur = g;
115         si->entries[i].global_inv = 32 - log2_int (g);
116         logf (LOG_DEBUG, "-------- %d ------", 32 - log2_int (g));
117     }
118     return si;
119 }
120
121 /*
122  * end: Terminates ranking process. Called after a result set
123  *  has been ranked.
124  */
125 static void end (ZebraHandle zh, void *set_handle)
126 {
127     struct rank_set_info *si = (struct rank_set_info *) set_handle;
128     logf (LOG_DEBUG, "rank-1 end");
129     xfree (si->entries);
130     xfree (si);
131 }
132
133 /*
134  * add: Called for each word occurence in a result set. This routine
135  *  should be as fast as possible. This routine should "incrementally"
136  *  update the score.
137  */
138 static void add (void *set_handle, int seqno, int term_index)
139 {
140     struct rank_set_info *si = (struct rank_set_info *) set_handle;
141     logf (LOG_DEBUG, "rank-1 add seqno=%d term_index=%d", seqno, term_index);
142     si->last_pos = seqno;
143     si->entries[term_index].local_occur++;
144 }
145
146 /*
147  * calc: Called for each document in a result. This handler should 
148  *  produce a score based on previous call(s) to the add handler. The
149  *  score should be between 0 and 1000. If score cannot be obtained
150  *  -1 should be returned.
151  */
152 static int calc (void *set_handle, int sysno)
153 {
154     int i, lo, divisor, score = 0;
155     struct rank_set_info *si = (struct rank_set_info *) set_handle;
156
157     logf (LOG_DEBUG, "rank-1 calc sysno=%d", sysno);
158
159     if (!si->no_rank_entries)
160         return -1;
161     for (i = 0; i < si->no_entries; i++)
162         if (si->entries[i].rank_flag && (lo = si->entries[i].local_occur))
163             score += (8+log2_int (lo)) * si->entries[i].global_inv;
164     score *= 34;
165     divisor = si->no_rank_entries * (8+log2_int (si->last_pos/si->no_entries));
166     score = score / divisor;
167     if (score > 1000)
168         score = 1000;
169     for (i = 0; i < si->no_entries; i++)
170         si->entries[i].local_occur = 0;
171     return score;
172 }
173
174 /*
175  * Pseudo-meta code with sequence of calls as they occur in a
176  * server. Handlers are prefixed by --:
177  *
178  *     server init
179  *     -- create
180  *     foreach search
181  *        rank result set
182  *        -- begin
183  *        foreach record
184  *           foreach word
185  *              -- add
186  *           -- calc
187  *        -- end
188  *     -- destroy
189  *     server close
190  */
191
192 static struct rank_control rank_control = {
193     "rank-1",
194     create,
195     destroy,
196     begin,
197     end,
198     calc,
199     add,
200 };
201  
202 struct rank_control *rank1_class = &rank_control;