~ubuntu-branches/ubuntu/lucid/bogofilter/lucid-security

« back to all changes in this revision

Viewing changes to src/rstats.c

  • Committer: Bazaar Package Importer
  • Author(s): Bhavani Shankar
  • Date: 2009-05-06 05:41:52 UTC
  • mfrom: (1.1.11 upstream) (2.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090506054152-tgameecssbuv4np6
Tags: 1.2.0-2ubuntu1
* Merge from debian unstable, remaining changes: LP: #372497
  - don't build qdbm.
  - Don't build tokyocabinet support as it's in universe.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: rstats.c 6514 2006-07-02 21:38:10Z relson $ */
 
1
/* $Id: rstats.c 6816 2009-02-21 21:11:01Z relson $ */
2
2
 
3
3
/*****************************************************************************
4
4
 
18
18
#include <stdlib.h>
19
19
 
20
20
#include "bogofilter.h"
 
21
#include "listsort.h"
21
22
#include "msgcounts.h"
22
23
#include "prob.h"
23
24
#include "rstats.h"
32
33
    u_int32_t   bad;
33
34
    u_int32_t   msgs_good;
34
35
    u_int32_t   msgs_bad;
 
36
    bool   used;
35
37
    double prob;
36
38
};
37
39
 
49
51
    uint      robn;             /* words in score */
50
52
    FLOAT     p;                /* Robinson's P */
51
53
    FLOAT     q;                /* Robinson's Q */
 
54
    double    min_dev;
52
55
    double    spamicity;
53
56
};
54
57
 
57
60
 
58
61
/* Function Prototypes */
59
62
 
60
 
static void rstats_print_histogram(size_t robn, rstats_t **rstats_array, size_t count);
61
 
static void rstats_print_rtable(rstats_t **rstats_array, size_t count);
 
63
static void rstats_print_histogram(size_t robn, rstats_t *rstats_head);
 
64
static void rstats_print_rtable(rstats_t *rstats_head);
62
65
 
63
66
/* Function Definitions */
64
67
 
66
69
{
67
70
    if (stats_head == NULL) {
68
71
        stats_head = xcalloc(1, sizeof(header_t));
69
 
        stats_tail = (rstats_t *) xcalloc( 1, sizeof(rstats_t));
 
72
        stats_tail = (rstats_t *)xcalloc(1, sizeof(rstats_t));
70
73
        stats_head->list = stats_tail;
71
74
    }
72
75
}
85
88
    stats_tail = NULL;
86
89
}
87
90
 
88
 
void rstats_add(const word_t *token, double prob, wordcnts_t *cnts)
 
91
void rstats_add(const word_t *token, double prob, bool used, wordcnts_t *cnts)
89
92
{
90
93
    if (token == NULL)
91
94
        return;
92
95
 
93
96
    stats_head->count += 1;
94
97
    stats_tail->next  = NULL;
 
98
 
95
99
    /* Using externally controlled data;
96
100
       token must not be freed before calling rstats_cleanup()
97
101
    */
98
102
    stats_tail->token = token;
99
103
    stats_tail->prob  = prob;
 
104
    stats_tail->used  = used;
100
105
    stats_tail->good  = cnts->good;
101
106
    stats_tail->bad   = cnts->bad;
102
107
    stats_tail->msgs_good = cnts->msgs_good;
103
108
    stats_tail->msgs_bad = cnts->msgs_bad;
 
109
 
104
110
    stats_tail->next = (rstats_t *)xcalloc(1, sizeof(rstats_t));
105
111
    stats_tail = stats_tail->next;
106
112
}
107
113
 
108
 
static int compare_rstats_t(const void *const ir1, const void *const ir2)
 
114
/* compare_rstats_t - sort by ascending spamicity */
 
115
 
 
116
static int compare_rstats_t(const void *const pv1, const void *const pv2)
109
117
{
110
 
    const rstats_t *r1 = *(const rstats_t *const *)ir1;
111
 
    const rstats_t *r2 = *(const rstats_t *const *)ir2;
 
118
    const rstats_t *r1 = (const rstats_t *)pv1;
 
119
    const rstats_t *r2 = (const rstats_t *)pv2;
112
120
 
113
 
    if (r1->prob - r2->prob > EPS) return 1;
114
 
    if (r2->prob - r1->prob > EPS) return -1;
 
121
    if (r1->prob > r2->prob) return 1;
 
122
    if (r2->prob > r1->prob) return -1;
115
123
 
116
124
    return word_cmp(r1->token, r2->token);
117
125
}
128
136
 
129
137
void rstats_print(bool unsure)
130
138
{
131
 
    size_t r;
132
139
    size_t robn  = stats_head->robn;
133
 
    size_t count = stats_head->count;
134
 
    rstats_t *cur;
135
 
    rstats_t **rstats_array = (rstats_t **) xcalloc(count, sizeof(rstats_t *));
136
 
 
137
 
    for (r=0, cur=stats_head->list; r<count; r+=1, cur=cur->next)
138
 
        rstats_array[r] = cur;
139
 
 
140
 
    /* sort by ascending probability, then name */
141
 
    qsort(rstats_array, count, sizeof(rstats_t *), compare_rstats_t);
 
140
 
 
141
    /* sort by ascending spamicity */
 
142
    stats_head->list = (rstats_t *)listsort((element *)stats_head->list, (fcn_compare *)&compare_rstats_t);
142
143
 
143
144
    if (Rtable || verbose>=3)
144
 
        rstats_print_rtable(rstats_array, count);
 
145
        rstats_print_rtable(stats_head->list);
145
146
    else if (verbose==2 || (unsure && verbose))
146
 
        rstats_print_histogram(robn, rstats_array, count);
147
 
 
148
 
    xfree(rstats_array);
 
147
        rstats_print_histogram(robn, stats_head->list);
149
148
}
150
149
 
151
 
static void rstats_print_histogram(size_t robn, rstats_t **rstats_array, size_t count)
 
150
static void rstats_print_histogram(size_t robn, rstats_t *rstats_head)
152
151
{
153
 
    size_t i, r;
 
152
    size_t i;
154
153
    size_t maxcnt=0;
 
154
    rstats_t *cur=rstats_head;
155
155
    rhistogram_t hist[INTERVALS];
156
156
 
157
157
    double invn = (double) robn;
163
163
        (void)fprintf(fpo, "\n" );
164
164
 
165
165
    /* Compute histogram */
166
 
    for (i=r=0; i<INTERVALS; i+=1)
 
166
    for (i=0; i<INTERVALS; i+=1)
167
167
    {
168
168
        rhistogram_t *h = &hist[i];
169
169
        double fin = 1.0*(i+1)/INTERVALS;
170
170
        size_t cnt = 0;
 
171
 
171
172
        h->prob = 0.0;
172
173
        h->spamicity=0.0;
173
 
        while (r < count)
 
174
 
 
175
        while (cur != NULL)
174
176
        {
175
 
            double prob = rstats_array[r]->prob;
 
177
            double prob = cur->prob;
176
178
            if (prob >= fin)
177
179
                break;
178
180
 
179
 
            if (fabs(EVEN_ODDS - prob) - min_dev >= EPS)
 
181
            if (cur->used)
180
182
            {
181
183
                cnt += 1;
182
184
                h->prob += prob;
184
186
                logsum += log(prob);
185
187
            }
186
188
 
187
 
            r += 1;
 
189
            cur = cur->next;
188
190
        }
189
191
 
190
192
        if (robn == 0)
191
193
            h->spamicity = robx;
192
 
        else 
 
194
        else
193
195
        {
194
196
            double invproduct, product;
195
197
            invproduct = 1.0 - exp(invlogsum / invn);
196
198
            product = 1.0 - exp(logsum / invn);
197
 
            h->spamicity = (invproduct + product < EPS) 
198
 
                ? 0.0 
 
199
            h->spamicity = (invproduct + product < EPS)
 
200
                ? 0.0
199
201
                : (1.0 + (invproduct - product) / (invproduct + product)) / 2.0;
200
202
        }
201
203
        h->count=cnt;
219
221
        if (maxcnt>48) cnt = (cnt * 48 + maxcnt - 1) / maxcnt;
220
222
 
221
223
        /* display histogram */
222
 
        for (r=0; r<cnt; r+=1)
 
224
        while (cnt-- > 0)
223
225
            (void)fputc( '#', fpo);
224
226
        (void)fputc( '\n', fpo);
225
227
    }
226
228
}
227
229
 
228
 
static void rstats_print_rtable(rstats_t **rstats_array, size_t count)
 
230
static void rstats_print_rtable(rstats_t *rstats_head)
229
231
{
230
 
    size_t r;
231
232
    const char *pfx = !stats_in_header ? "" : "  ";
232
233
 
 
234
    rstats_t *cur;
 
235
 
233
236
    /* print header */
234
237
    if (!Rtable)
235
238
        (void)fprintf(fpo, "%s%*s %6s    %-6s    %-6s    %-6s %s\n",
236
 
                      pfx, max_token_len+2,"","n", "pgood", "pbad", "fw", "U");
 
239
                      pfx, max_token_len+2, "", "n", "pgood", "pbad", "fw", "U");
237
240
    else
238
241
        (void)fprintf(fpo, "%s%*s %6s    %-6s    %-6s    %-6s  %-6s    %-6s %s\n",
239
 
                      pfx, max_token_len+2,"","n", "pgood", "pbad", "fw","invfwlog", "fwlog", "U");
 
242
                      pfx, max_token_len+2, "", "n", "pgood", "pbad", "fw", "invfwlog", "fwlog", "U");
240
243
 
241
244
    /* Print 1 line per token */
242
 
    for (r= 0; r<count; r+=1)
 
245
    for (cur=rstats_head->next; cur != NULL; cur=cur->next)
243
246
    {
244
 
        rstats_t *cur = rstats_array[r];
245
247
        int len = (cur->token->leng >= max_token_len) ? 0 : (max_token_len - cur->token->leng);
246
248
        double fw = calc_prob(cur->good, cur->bad, cur->msgs_good, cur->msgs_bad);
247
 
        char flag = (fabs(fw-EVEN_ODDS) - min_dev >= EPS) ? '+' : '-';
 
249
        char flag = cur->used ? '+' : '-';
248
250
 
249
251
        (void)fprintf(fpo, "%s\"", pfx);
250
252
        (void)word_puts(cur->token, 0, fpo);