Changeset e37ef045516872af81e36339debad2296a2d7506

Show
Ignore:
Timestamp:
04/28/08 11:42:00 (8 months ago)
Author:
dave <dave@…>
Parents:
afa46936e67e892eb5c8429bd0991a4630cbd71f, 8f4fd07de7bf767b30c219684608535cb9cb6f19
Children:
a2344576c2573c3b9a6fb40dfc614fd4cfe178f7
git-committer:
dave <dave@06fd6eb0-0002-0410-a719-e5602cce40bc> / 2008-04-28T01:42:00Z+0000
Message:

Merge branch 'master' into local-svn

git-svn-id: svn+ssh://davebalmain.com/home/dave/repos/ferret/trunk@1046 06fd6eb0-0002-0410-a719-e5602cce40bc

Files:
2 added
13 modified

Legend:

Unmodified
Added
Removed
  • c/.rake/.gitignore

    r31d0b3 r190f7a  
    33copts 
    44gcov_results.html 
     5gcov_history.jpg 
     6gcov_history.data 
  • c/.rake/gcov_results.erb

    rb78e07 r190f7a  
    1616    <h1>Ferret gcov Results</h1> 
    1717    <table cellpadding="0" cellspacing="5"> 
    18     <% $gcov_results.each do |percent, line_cnt, filename| %> 
     18    <% gcov_sorted_keys.each do |fn| %> 
    1919      <tr> 
    20         <th class="filename"><%= filename %></th> 
     20        <th class="filename"><%= fn %></th> 
    2121        <td class="result"> 
    22           <div class="bar" style="width:<%=percent%>%;">&nbsp;<div> 
     22          <div class="bar" style="width:<%=$gcov_results.files[fn].percent%>%;">&nbsp;<div> 
    2323        </td> 
    2424      </tr> 
    2525    <% end %> 
    2626    </table> 
     27    <img src="gcov_history.jpg" alt="Overall gcov coverage results"/> 
    2728    <script type="text/javascript"> 
    2829      var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); 
  • c/Rakefile

    r3d5c1b r2142bb  
    33require 'rake' 
    44require 'rake/clean' 
     5require 'ostruct' 
    56 
    67class String 
     
    5455  sh script 
    5556end 
     57 
     58### 
     59# Useful Constants 
     60### 
     61 
     62DAY = 24 * 60 * 60 # seconds in day 
    5663 
    5764### 
     
    105112  basename 
    106113end 
    107 $gcov_results   = [] 
     114 
     115$gcov_results   = OpenStruct.new(:files => {}) 
     116def gcov_sorted_keys 
     117  $gcov_results.files.keys.sort {|fn1, fn2| 
     118      res = $gcov_results.files[fn1].percent <=> 
     119            $gcov_results.files[fn2].percent 
     120      res = fn2 <=> fn1 if res == 0 
     121      res 
     122  }.reverse 
     123end 
    108124 
    109125### 
     
    172188  if copts != old_copts 
    173189    File.open(copts_file, 'w') {|f| f.write(Marshal.dump(copts))} 
    174     Rake::Task[:clean].invoke 
     190    Rake::Task[:scrub].invoke 
    175191  end 
    176192end 
     
    190206                  '*.gcov', 
    191207                  'y.tab.c']) 
    192  
    193208CLOBBER.include([ '*.a', 
    194209                  '**/*.o', 
     
    200215                  GCOV_DIR]) 
    201216 
    202 task :default => :testall 
    203  
     217SCRUB = FileList[CLEAN, '**/*.o'] 
     218desc "clean for rebuild" 
     219task :scrub do 
     220  SCRUB.each {|fn| rm_r fn rescue nil} 
     221end 
     222 
     223### 
     224# Test Helpers 
     225### 
    204226def run_tests 
    205227  check_coptions 
     
    215237end 
    216238 
     239### 
     240# gcov Helpers 
     241### 
     242GCOV_HIST_FILE = ".rake/gcov.history" 
     243def load_gcov_history 
     244  Marshal.load(File.read(GCOV_HIST_FILE)) 
     245end 
     246 
     247task :default => :testall 
     248 
    217249desc "Run all tests" 
    218250task :test do 
     
    229261task :gcov => :do_gcov do 
    230262  puts "\ngcov Results\n=============\n" 
    231   $gcov_results.each do |percent, line_cnt, fn| 
    232     puts "%25s %6.2f%% (%4d)" % [fn, percent, line_cnt] 
    233   end 
    234 end 
    235  
    236 task :gcov2html => :do_gcov do 
     263  total_lines = 0 
     264  total_lines_covered = 0 
     265  gcov_sorted_keys.each do |fn| 
     266    res = $gcov_results.files[fn] 
     267    puts "%25s %6.2f%% (%4d)" % [fn, res.percent, res.line_count] 
     268  end 
     269  puts "Total Lines:         %s" % $gcov_results.total_lines 
     270  puts "Total Lines covered: %s (%0.2f%%)" %  
     271            [$gcov_results.covered_lines, $gcov_results.percent] 
     272end 
     273 
     274desc "Generate .rake/gcov_results.html" 
     275task :gcov2html => [:do_gcov, '.rake/gcov_history.jpg'] do 
    237276  puts "Generating .rake/gcov_results.html..." 
    238277  File.open('.rake/gcov_results.html', 'w') do |f| 
     
    241280end 
    242281 
     282file '.rake/gcov_history.data' => GCOV_HIST_FILE do |t| 
     283  history = load_gcov_history 
     284  start = history.start_date 
     285  File.open(t.name, 'w') do |f| 
     286    history.data.each do |d| 
     287      f.write "%s %.2f\n" % 
     288        [Time.at((d.day + start) * DAY).strftime("%Y-%m-%d"), d.percent] 
     289    end 
     290  end 
     291end 
     292 
     293file '.rake/gcov_history.jpg' => '.rake/gcov_history.data' do |t| 
     294  sh "gnuplot .rake/gcov_history.plot" 
     295end 
     296 
    243297task :do_gcov do 
    244298  CFLAGS << " -fprofile-arcs -ftest-coverage" 
    245299  run_tests 
    246   gcov_results = [] 
     300  gcov_result_map = {} 
    247301  gcov_scanner = /File '([^']+)'\nLines executed:(\d+.\d+)% of (\d+)/ 
     302  total_lines = covered_lines = 0 
    248303  OBJS.each do |obj| 
    249304    bn = obj.pathmap('%n') 
     
    256311    gcov_cmd = "gcov -o .gcov/ #{obj}" 
    257312    details = IO.popen(gcov_cmd).read.scan(gcov_scanner) 
    258     details.each do |filename, percent, line_cnt| 
     313    details.each do |filename, percent, line_count| 
    259314      next if filename =~ /^\// 
    260       $gcov_results << [percent.to_f, line_cnt, filename] 
    261     end 
    262   end 
    263   $gcov_results = $gcov_results.sort_by{|res| res[0]}.reverse 
     315      line_count = line_count.to_i 
     316      percent = percent.to_f 
     317      $gcov_results.files[filename] = OpenStruct.new(:percent => percent, 
     318                                                     :line_count => line_count) 
     319      total_lines += line_count 
     320      covered_lines += (0.01 * percent * line_count).to_i 
     321    end 
     322  end 
     323  $gcov_results.total_lines = total_lines 
     324  $gcov_results.covered_lines = covered_lines 
     325  $gcov_results.percent = percent = 100.0 * covered_lines /total_lines 
     326  history = load_gcov_history 
     327  today = Time.now.to_i/DAY - history.start_date 
     328  history.data.pop if history.data.last.day == today 
     329  history.data << OpenStruct.new(:day => today, 
     330                                 :total => total_lines, 
     331                                 :covered => covered_lines, 
     332                                 :percent => percent) 
     333  File.open(GCOV_HIST_FILE, 'w') {|f| f.write(Marshal.dump(history))} 
    264334end 
    265335 
     
    451521  desc "Publish the gcoverage results" 
    452522  task :gcov => :gcov2html do 
    453     sh %{scp .rake/gcov_results.html www@davebalmain.com:/var/www/ferret} 
     523    sh "scp .rake/gcov_results.html .rake/gcov_history.jpg " +  
     524         "www@davebalmain.com:/var/www/ferret" 
    454525  end 
    455526end 
  • c/include/internal.h

    ra04da2 r8f4fd0  
    738738#define phq_append_multi_term                   frt_phq_append_multi_term 
    739739#define phq_new                                 frt_phq_new 
     740#define phq_set_slop                            frt_phq_set_slop 
    740741#define pl_add_occ                              frt_pl_add_occ 
    741742#define pl_cmp                                  frt_pl_cmp 
  • c/include/search.h

    r950230 r8f4fd0  
    326326extern void frt_phq_add_term_abs(FrtQuery *self, const char *term, int position); 
    327327extern void frt_phq_append_multi_term(FrtQuery *self, const char *term); 
     328extern void frt_phq_set_slop(FrtQuery *self, int slop); 
    328329 
    329330/*************************************************************************** 
  • c/src/index.c

    r0c11a5 rafa469  
    366366FieldInfo *fis_get_field(FieldInfos *fis, Symbol name) 
    367367{ 
    368     return (FieldInfo *)h_get(fis->field_dict, name); 
     368    return (FieldInfo *)h_get(fis->field_dict, I(name)); 
    369369} 
    370370 
    371371int fis_get_field_num(FieldInfos *fis, Symbol name) 
    372372{ 
    373     FieldInfo *fi = (FieldInfo *)h_get(fis->field_dict, name); 
     373    FieldInfo *fi = (FieldInfo *)h_get(fis->field_dict, I(name)); 
    374374    if (fi) { 
    375375        return fi->number; 
     
    382382FieldInfo *fis_get_or_add_field(FieldInfos *fis, Symbol name) 
    383383{ 
    384     FieldInfo *fi = (FieldInfo *)h_get(fis->field_dict, name); 
     384    FieldInfo *fi = (FieldInfo *)h_get(fis->field_dict, I(name)); 
    385385    if (!fi) { 
    386386        fi = (FieldInfo*)fi_new(name, fis->store, fis->index, fis->term_vector); 
     
    45484548                                  Symbol field) 
    45494549{ 
    4550     FieldInfo *fi = (FieldInfo *)h_get(ir->fis->field_dict, field); 
     4550    FieldInfo *fi = (FieldInfo *)h_get(ir->fis->field_dict, I(field)); 
    45514551    FieldsReader *fr; 
    45524552 
  • c/src/q_fuzzy.c

    r950230 r88f53b  
    88 * FuzzyStuff 
    99 * 
    10  * The main method here is the fuzq_score method which scores a term against 
    11  * another term. The other methods all act in support. 
     10 * The main method here is the fuzq_score_mn method which scores a term 
     11 * against another term. The other methods all act in support. 
     12 * 
     13 * To learn more about the fuzzy scoring algorithm see; 
     14 * 
     15 *     http://en.wikipedia.org/wiki/Levenshtein_distance 
    1216 * 
    1317 ****************************************************************************/ 
    1418 
     19/** 
     20 * Calculate the maximum nomber of allowed edits (or maximum edit distance) 
     21 * for a word to be a match. 
     22 * 
     23 * Note that fuzq->text_len and m are both the lengths text *after* the prefix 
     24 * so `MIN(fuzq->text_len, m) + fuzq->pre_len)` actually gets the byte length 
     25 * of the shorter string out of the query string and the index term being 
     26 * compared. 
     27 */ 
    1528static INLINE int fuzq_calculate_max_distance(FuzzyQuery *fuzq, int m) 
    1629{ 
     
    1831} 
    1932 
     33/** 
     34 * The max-distance formula gets used a lot - it needs to be calculated for 
     35 * every possible match in the index - so we cache the results for all 
     36 * lengths up to the TYPICAL_LONGEST_WORD limit. For words longer than this we 
     37 * calculate the value live. 
     38 */ 
    2039static void fuzq_initialize_max_distances(FuzzyQuery *fuzq) 
    2140{ 
     
    2645} 
    2746 
     47/** 
     48 * Return the cached max-distance value if the word is within the 
     49 * TYPICAL_LONGEST_WORD limit. 
     50 */ 
    2851static INLINE int fuzq_get_max_distance(FuzzyQuery *fuzq, int m) 
    2952{ 
     
    3356} 
    3457 
     58/** 
     59 * Calculate the similarity score for the +target+ against the query. 
     60 * 
     61 * @params fuzq The Fuzzy Query 
     62 * @params target *the term to compare against minus the prefix 
     63 * @params m the string length of +target+ 
     64 * @params n the string length of the query string minus length of the prefix 
     65 */ 
    3566static INLINE float fuzq_score_mn(FuzzyQuery *fuzq, 
    3667                                  const char *target, 
     
    173204    } 
    174205 
    175     if (te == NULL) { 
    176         if (prefix) free(prefix); 
    177         return q; 
    178     } 
     206    assert(NULL != te); 
    179207 
    180208    fuzq->scale_factor = (float)(1.0 / (1.0 - fuzq->min_sim)); 
  • c/src/q_phrase.c

    r0c11a5 r8f4fd0  
    117117static bool pp_less_than(const PhPos *pp1, const PhPos *pp2) 
    118118{ 
    119     /* docs will all be equal when this method is used */ 
    120     return pp1->position < pp2->position; 
    121     /* 
    122     if (PP(p)->doc == PP(p)->doc) { 
    123         return PP(p)->position < PP(p)->position; 
     119    if (pp1->position == pp2->position) { 
     120        return pp1->offset < pp2->offset; 
    124121    } 
    125122    else { 
    126         return PP(p)->doc < PP(p)->doc; 
    127     } 
    128     */ 
     123        return pp1->position < pp2->position; 
     124    } 
    129125} 
    130126 
     
    168164    bool    first_time : 1; 
    169165    bool    more : 1; 
     166    bool    check_repeats : 1; 
    170167} PhraseScorer; 
    171168 
     
    235232    return raw_score * sim_decode_norm( 
    236233        self->similarity, 
    237         phsc->norms[phsc->phrase_pos[phsc->pp_first_idx]->doc]); 
     234        phsc->norms[self->doc]); 
    238235} 
    239236 
     
    279276    phsc_skip_to(self, doc_num); 
    280277 
    281     phrase_freq = (self->doc == doc_num) ? phsc->freq : (float)0.0; 
     278    phrase_freq = (self->doc == doc_num) ? phsc->freq : 0.0f; 
    282279    return expl_new(sim_tf(self->similarity, phrase_freq), 
    283280                    "tf(phrase_freq=%f)", phrase_freq); 
     
    295292} 
    296293 
    297 static Scorer *phsc_new(Weight *weight, TermDocEnum **term_pos_enum, 
     294static Scorer *phsc_new(Weight *weight, 
     295                        TermDocEnum **term_pos_enum, 
    298296                        PhrasePosition *positions, int pos_cnt, 
    299                         Similarity *similarity, uchar *norms) 
     297                        Similarity *similarity, 
     298                        uchar *norms, 
     299                        int slop) 
    300300{ 
    301301    int i; 
    302302    Scorer *self                = scorer_new(PhraseScorer, similarity); 
     303    HashSet *term_set           = NULL; 
     304 
    303305 
    304306    PhSc(self)->weight          = weight; 
     
    308310    PhSc(self)->pp_first_idx    = 0; 
    309311    PhSc(self)->pp_cnt          = pos_cnt; 
    310     PhSc(self)->slop            = 0; 
     312    PhSc(self)->slop            = slop; 
    311313    PhSc(self)->first_time      = true; 
    312314    PhSc(self)->more            = true; 
    313  
     315    PhSc(self)->check_repeats   = false; 
     316     
     317    if (slop) { 
     318        term_set = hs_new_str((free_ft)NULL); 
     319    } 
    314320    for (i = 0; i < pos_cnt; i++) { 
     321        /* check for repeats */ 
     322        if (slop && !PhSc(self)->check_repeats) { 
     323            char **terms = positions[i].terms; 
     324            const int t_cnt = ary_size(terms); 
     325            int j; 
     326            for (j = 0; j < t_cnt; j++) { 
     327                if (hs_add(term_set, terms[j])) { 
     328                    PhSc(self)->check_repeats = true; 
     329                    goto repeat_check_done; 
     330                } 
     331            } 
     332        } 
     333repeat_check_done: 
    315334        PhSc(self)->phrase_pos[i] = pp_new(term_pos_enum[i], positions[i].pos); 
     335    } 
     336 
     337    if (slop) { 
     338        hs_destroy(term_set); 
    316339    } 
    317340 
     
    376399                                       Similarity *similarity, uchar *norms) 
    377400{ 
    378     Scorer *self = 
    379         phsc_new(weight, term_pos_enum, positions, pp_cnt, similarity, norms); 
     401    Scorer *self = phsc_new(weight, 
     402                            term_pos_enum, 
     403                            positions, 
     404                            pp_cnt, 
     405                            similarity, 
     406                            norms, 
     407                            0); 
    380408 
    381409    PhSc(self)->phrase_freq = &ephsc_phrase_freq; 
     
    386414 * SloppyPhraseScorer 
    387415 ***************************************************************************/ 
     416 
     417static bool sphsc_check_repeats(PhPos *pp, 
     418                                PhPos **positions, 
     419                                const int p_cnt) 
     420{ 
     421    int j; 
     422    for (j = 0; j < p_cnt; j++) { 
     423        PhPos *ppj = positions[j]; 
     424        /* If offsets are equal, either we are at the current PhPos +pp+ or 
     425         * +pp+ and +ppj+ are supposed to match in the same position in which 
     426         * case we don't need to check. */ 
     427        if (ppj->offset == pp->offset) { 
     428            continue; 
     429        } 
     430        /* the two phrase positions are matching on the same term 
     431         * which we want to avoid */ 
     432        if ((ppj->position + ppj->offset) == (pp->position + pp->offset)) { 
     433            if (!pp_next_position(pp)) { 
     434                /* We have no matches for this document */ 
     435                return false; 
     436            } 
     437            /* we changed the position so we need to start check again */ 
     438            j = -1; 
     439        } 
     440    } 
     441    return true; 
     442} 
    388443 
    389444static float sphsc_phrase_freq(Scorer *self) 
     
    396451    int last_pos = 0, pos, next_pos, start, match_length, i; 
    397452    bool done = false; 
     453    bool check_repeats = phsc->check_repeats; 
    398454    float freq = 0.0; 
    399455 
    400456    for (i = 0; i < pp_cnt; i++) { 
    401457        pp = phsc->phrase_pos[i]; 
    402         pp_first_position(pp); 
     458        /* we should always have at least one position or this functions 
     459         * shouldn't have been called. */ 
     460        assert(pp_first_position(pp)); 
     461        if (check_repeats && i > 0) { 
     462            if (!sphsc_check_repeats(pp, phsc->phrase_pos, i - 1)) { 
     463                goto return_freq; 
     464            } 
     465        } 
    403466        if (pp->position > last_pos) { 
    404467            last_pos = pp->position; 
     
    413476        while (pos <= next_pos) { 
    414477            start = pos;        /* advance pp to min window */ 
    415             if (!pp_next_position(pp)) { 
    416                 done = true;    /* ran out of a positions for a term - done */ 
     478            if (!pp_next_position(pp) 
     479                || (check_repeats 
     480                    && !sphsc_check_repeats(pp, phsc->phrase_pos, pp_cnt))) { 
     481                done = true; 
    417482                break; 
    418483            } 
     
    431496        pq_push(pq, pp);        /* restore pq */ 
    432497    } while (!done); 
     498 
     499return_freq: 
    433500 
    434501    pq_destroy(pq); 
     
    442509                                        int slop, uchar *norms) 
    443510{ 
    444     Scorer *self = 
    445         phsc_new(weight, term_pos_enum, positions, pp_cnt, similarity, norms); 
    446  
    447     PhSc(self)->slop        = slop; 
     511    Scorer *self = phsc_new(weight, 
     512                            term_pos_enum, 
     513                            positions, 
     514                            pp_cnt, 
     515                            similarity, 
     516                            norms, 
     517                            slop); 
     518 
    448519    PhSc(self)->phrase_freq = &sphsc_phrase_freq; 
    449520    return self; 
     
    11251196    } 
    11261197} 
     1198 
     1199void frt_phq_set_slop(FrtQuery *self, int slop) 
     1200{ 
     1201    PhQ(self)->slop = slop; 
     1202} 
  • c/test/test.c

    r03f3cf r8f4fd0  
    259259 
    260260    dptr = suite->head; 
    261     fprintf(stdout, "%-15s\t\tTotal\tFail\tFailed %%\n", "Failed Tests"); 
     261    fprintf(stdout, "%-24sTotal\tFail\tFailed %%\n", "Failed Tests"); 
    262262    fprintf(stdout, "===================================================\n"); 
    263263    while (dptr != NULL) { 
     
    265265            double percent = 
    266266                ((double) dptr->failed / (double) dptr->num_test); 
    267             fprintf(stdout, "%-15s\t\t%5d\t%4d\t%6.2f%%\n", dptr->name, 
     267            fprintf(stdout, "%-24s%5d\t%4d\t%6.2f%%\n", dptr->name, 
    268268                    dptr->num_test, dptr->failed, percent * 100); 
    269269        } 
     
    456456        return true; 
    457457    } 
     458    fprintf(stderr, "diff = %g\n", diff); 
    458459 
    459460    tc->failed = true; 
  • c/test/test_bitvector.c

    r48290f rcf8e43  
    147147} 
    148148 
     149#define test_bveq(_bv1, _bv2)                                       \ 
     150do {                                                                \ 
     151    BitVector *_not_bv1, *_not_bv2;                                 \ 
     152    Assert(bv_eq(_bv1, _bv2), "BitVectors are equal");              \ 
     153    Assert(bv_eq(_bv2, _bv1), "BitVectors are equal");              \ 
     154    Assert(bv_eq(_bv1, _bv1), "bv_eq on self should work");         \ 
     155    Aiequal(bv_hash(_bv1), bv_hash(_bv2));                          \ 
     156    /* test flipped bitvectors */                                   \ 
     157    _not_bv1 = bv_not(_bv1); _not_bv2 = bv_not(_bv2);               \ 
     158    bv_set(_not_bv1, 1100); /* should make no difference */         \ 
     159    Assert(bv_eq(_not_bv1, _not_bv2), "BitVectors are equal");      \ 
     160    Assert(bv_eq(_not_bv2, _not_bv1), "BitVectors are equal");      \ 
     161    Assert(bv_eq(_not_bv1, _not_bv1), "bv_eq on self should work"); \ 
     162    Aiequal(bv_hash(_not_bv1), bv_hash(_not_bv2));                  \ 
     163    bv_destroy(_not_bv1); bv_destroy(_not_bv2);                     \ 
     164} while (0) 
     165 
     166#define test_bvneq(_bv1, _bv2)                                      \ 
     167do {                                                                \ 
     168    BitVector *_not_bv1, *_not_bv2;                                 \ 
     169    Assert(!bv_eq(_bv1, _bv2), "BitVectors are not equal");         \ 
     170    Assert(!bv_eq(_bv2, _bv1), "BitVectors are not equal");         \ 
     171    Assert(bv_hash(_bv1) != bv_hash(_bv2), "BitVectors not equal"); \ 
     172    /* test flipped bitvectors */                                   \