+ yaz_log(YLOG_DEBUG, "SNIPPET match: %s", wrbuf_cstr(w_snippet));
+ }
+ return no;
+}
+
+void relevance_countwords(struct relevance *r, struct record_cluster *cluster,
+ const char *words, const char *rank,
+ const char *name)
+{
+ int *w = r->term_frequency_vec_tmp;
+ const char *norm_str;
+ int i, length = 0;
+ double lead_decay = r->lead_decay;
+ struct word_entry *e;
+ WRBUF wr = cluster->relevance_explain1;
+ int printed_about_field = 0;
+
+ pp2_charset_token_first(r->prt, words, 0);
+ for (e = r->entries, i = 1; i < r->vec_len; i++, e = e->next)
+ {
+ w[i] = 0;
+ r->term_pos[i] = 0;
+ }
+
+ assert(rank);
+ while ((norm_str = pp2_charset_token_next(r->prt)))
+ {
+ int local_weight = 0;
+ e = word_entry_match(r, norm_str, rank, &local_weight);
+ if (e)
+ {
+ int res = e->termno;
+ int j;
+
+ if (!printed_about_field)
+ {
+ printed_about_field = 1;
+ wrbuf_printf(wr, "field=%s content=", name);
+ if (strlen(words) > 50)
+ {
+ wrbuf_xmlputs_n(wr, words, 49);
+ wrbuf_puts(wr, " ...");
+ }
+ else
+ wrbuf_xmlputs(wr, words);
+ wrbuf_puts(wr, ";\n");
+ }
+ assert(res < r->vec_len);
+ w[res] += local_weight / (1 + log2(1 + lead_decay * length));
+ wrbuf_printf(wr, "%s: w[%d] += w(%d) / "
+ "(1+log2(1+lead_decay(%f) * length(%d)));\n",
+ e->display_str, res, local_weight, lead_decay, length);
+ j = res - 1;
+ if (j > 0 && r->term_pos[j])
+ {
+ int d = length + 1 - r->term_pos[j];
+ wrbuf_printf(wr, "%s: w[%d] += w[%d](%d) * follow(%f) / "
+ "(1+log2(d(%d));\n",
+ e->display_str, res, res, w[res],
+ r->follow_factor, d);
+ w[res] += w[res] * r->follow_factor / (1 + log2(d));
+ }
+ for (j = 0; j < r->vec_len; j++)
+ r->term_pos[j] = j < res ? 0 : length + 1;
+ }
+ length++;
+ }
+
+ for (e = r->entries, i = 1; i < r->vec_len; i++, e = e->next)
+ {
+ if (length == 0 || w[i] == 0)
+ continue;
+ wrbuf_printf(wr, "%s: tf[%d] += w[%d](%d)", e->display_str, i, i, w[i]);
+ switch (r->length_divide)