File Coverage

blib/lib/Search/Binary.pm
Criterion Covered Total %
statement 37 39 94.8
branch 10 12 83.3
condition 3 5 60.0
subroutine 5 5 100.0
pod 0 1 0.0
total 55 62 88.7


line stmt bran cond sub pod time code
1             package Search::Binary;
2              
3 3     3   73901 use strict;
  3         8  
  3         118  
4 3     3   17 use warnings;
  3         7  
  3         89  
5 3     3   28 use Carp;
  3         6  
  3         275  
6 3     3   1831 use parent 'Exporter';
  3         751  
  3         16  
7             our @EXPORT = qw(binary_search);
8              
9             our $VERSION = '0.96_02';
10              
11             sub binary_search {
12 24     24 0 16484 my ($posmin, $posmax, $target, $readfn, $handle, $smallblock) = @_;
13 24   50     103 $smallblock ||= 0;
14 24 100       56 if ($posmin > $posmax) {
15 1         198 carp 'First argument must be less then or equal to second argument'
16             . " (min: $posmin, max: $posmax)";
17 1         32 return 0; # some libraries rely on this behavior
18             }
19              
20 23         30 my ($x, $compare, $mid);
21              
22             # assert $posmin <= $posmax
23              
24 23         28 my $seeks = my $reads = 0;
25 23         54 my $lastmid = int($posmin + (($posmax - $posmin) / 2)) - 1;
26 23         58 while ($posmax - $posmin > $smallblock) {
27              
28             # assert: $posmin is the beginning of a record
29             # and $target >= index value for that record
30              
31 97         97 $seeks++;
32 97         140 $x = int($posmin + (($posmax - $posmin) / 2));
33 97         210 ($compare, $mid) = $readfn->($handle, $target, $x);
34              
35 97 50       801 unless (defined($compare)) {
36 0         0 $posmax = $mid;
37 0         0 next;
38             }
39 97 100       167 last if ($mid == $lastmid);
40 78 100       131 if ($compare > 0) {
41 37         52 $posmin = $mid;
42             } else {
43 41         47 $posmax = $mid;
44             }
45 78         152 $lastmid = $mid;
46             }
47              
48             # Switch to sequential search.
49              
50 23         32 $x = $posmin;
51 23         50 while ($posmin <= $posmax) {
52              
53             # same loop invarient as above applies here
54              
55 44         41 $reads++;
56 44         94 ($compare, $posmin) = $readfn->($handle, $target, $x);
57 44 100 66     453 last unless (defined($compare) && $compare > 0);
58 21         42 $x = undef;
59             }
60 23 50       140 return wantarray ? ($posmin, $seeks, $reads) : $posmin;
61             }
62              
63             1;
64             __END__